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/user/data/webkitgtk-2.25.2/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 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, inlineCapacity);
50 }
51
52 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
53 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity)
54 {
55 auto __metadataID = gen->addMetadataFor(opcodeID);
56 return emit<size, shouldAssert>(gen, dst, callee, inlineCapacity, __metadataID);
57 }
58
59 template<OpcodeSize size>
60 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity)
61 {
62 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
63 return checkImpl<size>(gen, dst, callee, inlineCapacity, __metadataID);
64 }
65
66 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
67 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity, unsigned __metadataID)
68 {
69 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, inlineCapacity, __metadataID);
70 if (shouldAssert == Assert)
71 ASSERT(didEmit);
72 return didEmit;
73 }
74
75 template<OpcodeSize size>
76 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity)
77 {
78
79 auto __metadataID = gen->addMetadataFor(opcodeID);
80 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
81 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, inlineCapacity, __metadataID))
82 return;
83 }
84 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
85 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, inlineCapacity, __metadataID))
86 return;
87 }
88 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, inlineCapacity, __metadataID);
89 }
90
91private:
92 template<OpcodeSize size>
93 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& inlineCapacity, unsigned __metadataID)
94 {
95 UNUSED_PARAM(gen);
96#if OS(WINDOWS) && ENABLE(C_LOOP)
97 // FIXME: Disable wide16 optimization for Windows CLoop
98 // https://bugs.webkit.org/show_bug.cgi?id=198283
99 if (size == OpcodeSize::Wide16)
100 return false;
101#endif
102 return Fits<OpcodeID, size>::check(opcodeID)
103 && Fits<VirtualRegister, size>::check(dst)
104 && Fits<VirtualRegister, size>::check(callee)
105 && Fits<unsigned, size>::check(inlineCapacity)
106 && Fits<unsigned, size>::check(__metadataID)
107 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
108 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
109 }
110
111 template<OpcodeSize size, bool recordOpcode>
112 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity, unsigned __metadataID)
113 {
114 if (size == OpcodeSize::Wide16)
115 gen->alignWideOpcode16();
116 else if (size == OpcodeSize::Wide32)
117 gen->alignWideOpcode32();
118 if (checkImpl<size>(gen, dst, callee, inlineCapacity, __metadataID)) {
119 if (recordOpcode)
120 gen->recordOpcode(opcodeID);
121 if (size == OpcodeSize::Wide16)
122 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
123 else if (size == OpcodeSize::Wide32)
124 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
125 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
126 gen->write(Fits<VirtualRegister, size>::convert(dst));
127 gen->write(Fits<VirtualRegister, size>::convert(callee));
128 gen->write(Fits<unsigned, size>::convert(inlineCapacity));
129 gen->write(Fits<unsigned, size>::convert(__metadataID));
130 return true;
131 }
132 return false;
133 }
134
135public:
136 template<typename Block>
137 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
138 {
139 dumper->printLocationAndOp(__location, &"**create_this"[2 - __sizeShiftAmount]);
140 dumper->dumpOperand(m_dst, true);
141 dumper->dumpOperand(m_callee, false);
142 dumper->dumpOperand(m_inlineCapacity, false);
143 }
144
145 OpCreateThis(const uint8_t* stream)
146 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
147 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
148 , m_inlineCapacity(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
149 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
150 {
151 ASSERT_UNUSED(stream, stream[0] == opcodeID);
152 }
153
154 OpCreateThis(const uint16_t* stream)
155 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
156 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
157 , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
158 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
159 {
160 ASSERT_UNUSED(stream, stream[0] == opcodeID);
161 }
162
163
164 OpCreateThis(const uint32_t* stream)
165 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
166 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
167 , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
168 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
169 {
170 ASSERT_UNUSED(stream, stream[0] == opcodeID);
171 }
172
173 static OpCreateThis decode(const uint8_t* stream)
174 {
175 if (*stream == op_wide32)
176 return { bitwise_cast<const uint32_t*>(stream + 1) };
177 if (*stream == op_wide16)
178 return { bitwise_cast<const uint16_t*>(stream + 1) };
179 return { stream };
180 }
181
182 template<typename Functor>
183 void setDst(VirtualRegister value, Functor func)
184 {
185 if (isWide32())
186 setDst<OpcodeSize::Wide32>(value, func);
187 else if (isWide16())
188 setDst<OpcodeSize::Wide16>(value, func);
189 else
190 setDst<OpcodeSize::Narrow>(value, func);
191 }
192
193 template <OpcodeSize size, typename Functor>
194 void setDst(VirtualRegister value, Functor func)
195 {
196 if (!Fits<VirtualRegister, size>::check(value))
197 value = func();
198 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
199 *stream = Fits<VirtualRegister, size>::convert(value);
200 }
201
202 template<typename Functor>
203 void setCallee(VirtualRegister value, Functor func)
204 {
205 if (isWide32())
206 setCallee<OpcodeSize::Wide32>(value, func);
207 else if (isWide16())
208 setCallee<OpcodeSize::Wide16>(value, func);
209 else
210 setCallee<OpcodeSize::Narrow>(value, func);
211 }
212
213 template <OpcodeSize size, typename Functor>
214 void setCallee(VirtualRegister value, Functor func)
215 {
216 if (!Fits<VirtualRegister, size>::check(value))
217 value = func();
218 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
219 *stream = Fits<VirtualRegister, size>::convert(value);
220 }
221
222 template<typename Functor>
223 void setInlineCapacity(unsigned value, Functor func)
224 {
225 if (isWide32())
226 setInlineCapacity<OpcodeSize::Wide32>(value, func);
227 else if (isWide16())
228 setInlineCapacity<OpcodeSize::Wide16>(value, func);
229 else
230 setInlineCapacity<OpcodeSize::Narrow>(value, func);
231 }
232
233 template <OpcodeSize size, typename Functor>
234 void setInlineCapacity(unsigned value, Functor func)
235 {
236 if (!Fits<unsigned, size>::check(value))
237 value = func();
238 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
239 *stream = Fits<unsigned, size>::convert(value);
240 }
241
242 struct Metadata {
243 WTF_MAKE_NONCOPYABLE(Metadata);
244
245 public:
246 Metadata(const OpCreateThis&) { }
247
248 WriteBarrier<JSCell> m_cachedCallee;
249 };
250
251 Metadata& metadata(CodeBlock* codeBlock) const
252 {
253 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
254 }
255
256 Metadata& metadata(ExecState* exec) const
257 {
258 return metadata(exec->codeBlock());
259 }
260
261 VirtualRegister m_dst;
262 VirtualRegister m_callee;
263 unsigned m_inlineCapacity;
264 unsigned m_metadataID;
265};
266
267struct OpGetArgument : public Instruction {
268 static constexpr OpcodeID opcodeID = op_get_argument;
269
270 static void emit(BytecodeGenerator* gen, VirtualRegister dst, int index)
271 {
272 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, index);
273 }
274
275 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
276 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, int index)
277 {
278 auto __metadataID = gen->addMetadataFor(opcodeID);
279 return emit<size, shouldAssert>(gen, dst, index, __metadataID);
280 }
281
282 template<OpcodeSize size>
283 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, int index)
284 {
285 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
286 return checkImpl<size>(gen, dst, index, __metadataID);
287 }
288
289 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
290 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, int index, unsigned __metadataID)
291 {
292 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, index, __metadataID);
293 if (shouldAssert == Assert)
294 ASSERT(didEmit);
295 return didEmit;
296 }
297
298 template<OpcodeSize size>
299 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, int index)
300 {
301
302 auto __metadataID = gen->addMetadataFor(opcodeID);
303 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
304 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, index, __metadataID))
305 return;
306 }
307 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
308 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, index, __metadataID))
309 return;
310 }
311 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, index, __metadataID);
312 }
313
314private:
315 template<OpcodeSize size>
316 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, int& index, unsigned __metadataID)
317 {
318 UNUSED_PARAM(gen);
319#if OS(WINDOWS) && ENABLE(C_LOOP)
320 // FIXME: Disable wide16 optimization for Windows CLoop
321 // https://bugs.webkit.org/show_bug.cgi?id=198283
322 if (size == OpcodeSize::Wide16)
323 return false;
324#endif
325 return Fits<OpcodeID, size>::check(opcodeID)
326 && Fits<VirtualRegister, size>::check(dst)
327 && Fits<int, size>::check(index)
328 && Fits<unsigned, size>::check(__metadataID)
329 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
330 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
331 }
332
333 template<OpcodeSize size, bool recordOpcode>
334 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, int index, unsigned __metadataID)
335 {
336 if (size == OpcodeSize::Wide16)
337 gen->alignWideOpcode16();
338 else if (size == OpcodeSize::Wide32)
339 gen->alignWideOpcode32();
340 if (checkImpl<size>(gen, dst, index, __metadataID)) {
341 if (recordOpcode)
342 gen->recordOpcode(opcodeID);
343 if (size == OpcodeSize::Wide16)
344 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
345 else if (size == OpcodeSize::Wide32)
346 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
347 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
348 gen->write(Fits<VirtualRegister, size>::convert(dst));
349 gen->write(Fits<int, size>::convert(index));
350 gen->write(Fits<unsigned, size>::convert(__metadataID));
351 return true;
352 }
353 return false;
354 }
355
356public:
357 template<typename Block>
358 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
359 {
360 dumper->printLocationAndOp(__location, &"**get_argument"[2 - __sizeShiftAmount]);
361 dumper->dumpOperand(m_dst, true);
362 dumper->dumpOperand(m_index, false);
363 }
364
365 OpGetArgument(const uint8_t* stream)
366 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
367 , m_index(Fits<int, OpcodeSize::Narrow>::convert(stream[2]))
368 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
369 {
370 ASSERT_UNUSED(stream, stream[0] == opcodeID);
371 }
372
373 OpGetArgument(const uint16_t* stream)
374 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
375 , m_index(Fits<int, OpcodeSize::Wide16>::convert(stream[2]))
376 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
377 {
378 ASSERT_UNUSED(stream, stream[0] == opcodeID);
379 }
380
381
382 OpGetArgument(const uint32_t* stream)
383 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
384 , m_index(Fits<int, OpcodeSize::Wide32>::convert(stream[2]))
385 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
386 {
387 ASSERT_UNUSED(stream, stream[0] == opcodeID);
388 }
389
390 static OpGetArgument decode(const uint8_t* stream)
391 {
392 if (*stream == op_wide32)
393 return { bitwise_cast<const uint32_t*>(stream + 1) };
394 if (*stream == op_wide16)
395 return { bitwise_cast<const uint16_t*>(stream + 1) };
396 return { stream };
397 }
398
399 template<typename Functor>
400 void setDst(VirtualRegister value, Functor func)
401 {
402 if (isWide32())
403 setDst<OpcodeSize::Wide32>(value, func);
404 else if (isWide16())
405 setDst<OpcodeSize::Wide16>(value, func);
406 else
407 setDst<OpcodeSize::Narrow>(value, func);
408 }
409
410 template <OpcodeSize size, typename Functor>
411 void setDst(VirtualRegister value, Functor func)
412 {
413 if (!Fits<VirtualRegister, size>::check(value))
414 value = func();
415 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
416 *stream = Fits<VirtualRegister, size>::convert(value);
417 }
418
419 template<typename Functor>
420 void setIndex(int value, Functor func)
421 {
422 if (isWide32())
423 setIndex<OpcodeSize::Wide32>(value, func);
424 else if (isWide16())
425 setIndex<OpcodeSize::Wide16>(value, func);
426 else
427 setIndex<OpcodeSize::Narrow>(value, func);
428 }
429
430 template <OpcodeSize size, typename Functor>
431 void setIndex(int value, Functor func)
432 {
433 if (!Fits<int, size>::check(value))
434 value = func();
435 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
436 *stream = Fits<int, size>::convert(value);
437 }
438
439 struct Metadata {
440 WTF_MAKE_NONCOPYABLE(Metadata);
441
442 public:
443 Metadata(const OpGetArgument&) { }
444
445 ValueProfile m_profile;
446 };
447
448 Metadata& metadata(CodeBlock* codeBlock) const
449 {
450 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
451 }
452
453 Metadata& metadata(ExecState* exec) const
454 {
455 return metadata(exec->codeBlock());
456 }
457
458 VirtualRegister m_dst;
459 int m_index;
460 unsigned m_metadataID;
461};
462
463struct OpToThis : public Instruction {
464 static constexpr OpcodeID opcodeID = op_to_this;
465
466 static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
467 {
468 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst);
469 }
470
471 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
472 static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst)
473 {
474 auto __metadataID = gen->addMetadataFor(opcodeID);
475 return emit<size, shouldAssert>(gen, srcDst, __metadataID);
476 }
477
478 template<OpcodeSize size>
479 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister srcDst)
480 {
481 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
482 return checkImpl<size>(gen, srcDst, __metadataID);
483 }
484
485 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
486 static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID)
487 {
488 bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst, __metadataID);
489 if (shouldAssert == Assert)
490 ASSERT(didEmit);
491 return didEmit;
492 }
493
494 template<OpcodeSize size>
495 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst)
496 {
497
498 auto __metadataID = gen->addMetadataFor(opcodeID);
499 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
500 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst, __metadataID))
501 return;
502 }
503 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
504 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst, __metadataID))
505 return;
506 }
507 emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst, __metadataID);
508 }
509
510private:
511 template<OpcodeSize size>
512 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst, unsigned __metadataID)
513 {
514 UNUSED_PARAM(gen);
515#if OS(WINDOWS) && ENABLE(C_LOOP)
516 // FIXME: Disable wide16 optimization for Windows CLoop
517 // https://bugs.webkit.org/show_bug.cgi?id=198283
518 if (size == OpcodeSize::Wide16)
519 return false;
520#endif
521 return Fits<OpcodeID, size>::check(opcodeID)
522 && Fits<VirtualRegister, size>::check(srcDst)
523 && Fits<unsigned, size>::check(__metadataID)
524 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
525 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
526 }
527
528 template<OpcodeSize size, bool recordOpcode>
529 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID)
530 {
531 if (size == OpcodeSize::Wide16)
532 gen->alignWideOpcode16();
533 else if (size == OpcodeSize::Wide32)
534 gen->alignWideOpcode32();
535 if (checkImpl<size>(gen, srcDst, __metadataID)) {
536 if (recordOpcode)
537 gen->recordOpcode(opcodeID);
538 if (size == OpcodeSize::Wide16)
539 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
540 else if (size == OpcodeSize::Wide32)
541 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
542 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
543 gen->write(Fits<VirtualRegister, size>::convert(srcDst));
544 gen->write(Fits<unsigned, size>::convert(__metadataID));
545 return true;
546 }
547 return false;
548 }
549
550public:
551 template<typename Block>
552 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
553 {
554 dumper->printLocationAndOp(__location, &"**to_this"[2 - __sizeShiftAmount]);
555 dumper->dumpOperand(m_srcDst, true);
556 }
557
558 OpToThis(const uint8_t* stream)
559 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
560 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
561 {
562 ASSERT_UNUSED(stream, stream[0] == opcodeID);
563 }
564
565 OpToThis(const uint16_t* stream)
566 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
567 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
568 {
569 ASSERT_UNUSED(stream, stream[0] == opcodeID);
570 }
571
572
573 OpToThis(const uint32_t* stream)
574 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
575 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
576 {
577 ASSERT_UNUSED(stream, stream[0] == opcodeID);
578 }
579
580 static OpToThis decode(const uint8_t* stream)
581 {
582 if (*stream == op_wide32)
583 return { bitwise_cast<const uint32_t*>(stream + 1) };
584 if (*stream == op_wide16)
585 return { bitwise_cast<const uint16_t*>(stream + 1) };
586 return { stream };
587 }
588
589 template<typename Functor>
590 void setSrcDst(VirtualRegister value, Functor func)
591 {
592 if (isWide32())
593 setSrcDst<OpcodeSize::Wide32>(value, func);
594 else if (isWide16())
595 setSrcDst<OpcodeSize::Wide16>(value, func);
596 else
597 setSrcDst<OpcodeSize::Narrow>(value, func);
598 }
599
600 template <OpcodeSize size, typename Functor>
601 void setSrcDst(VirtualRegister value, Functor func)
602 {
603 if (!Fits<VirtualRegister, size>::check(value))
604 value = func();
605 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
606 *stream = Fits<VirtualRegister, size>::convert(value);
607 }
608
609 struct Metadata {
610 WTF_MAKE_NONCOPYABLE(Metadata);
611
612 public:
613 Metadata(const OpToThis&) { }
614
615 StructureID m_cachedStructureID;
616 ToThisStatus m_toThisStatus;
617 ValueProfile m_profile;
618 };
619
620 Metadata& metadata(CodeBlock* codeBlock) const
621 {
622 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
623 }
624
625 Metadata& metadata(ExecState* exec) const
626 {
627 return metadata(exec->codeBlock());
628 }
629
630 VirtualRegister m_srcDst;
631 unsigned m_metadataID;
632};
633
634struct OpNewObject : public Instruction {
635 static constexpr OpcodeID opcodeID = op_new_object;
636
637 static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
638 {
639 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, inlineCapacity);
640 }
641
642 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
643 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
644 {
645 auto __metadataID = gen->addMetadataFor(opcodeID);
646 return emit<size, shouldAssert>(gen, dst, inlineCapacity, __metadataID);
647 }
648
649 template<OpcodeSize size>
650 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
651 {
652 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
653 return checkImpl<size>(gen, dst, inlineCapacity, __metadataID);
654 }
655
656 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
657 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity, unsigned __metadataID)
658 {
659 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, inlineCapacity, __metadataID);
660 if (shouldAssert == Assert)
661 ASSERT(didEmit);
662 return didEmit;
663 }
664
665 template<OpcodeSize size>
666 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
667 {
668
669 auto __metadataID = gen->addMetadataFor(opcodeID);
670 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
671 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, inlineCapacity, __metadataID))
672 return;
673 }
674 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
675 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, inlineCapacity, __metadataID))
676 return;
677 }
678 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, inlineCapacity, __metadataID);
679 }
680
681private:
682 template<OpcodeSize size>
683 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& inlineCapacity, unsigned __metadataID)
684 {
685 UNUSED_PARAM(gen);
686#if OS(WINDOWS) && ENABLE(C_LOOP)
687 // FIXME: Disable wide16 optimization for Windows CLoop
688 // https://bugs.webkit.org/show_bug.cgi?id=198283
689 if (size == OpcodeSize::Wide16)
690 return false;
691#endif
692 return Fits<OpcodeID, size>::check(opcodeID)
693 && Fits<VirtualRegister, size>::check(dst)
694 && Fits<unsigned, size>::check(inlineCapacity)
695 && Fits<unsigned, size>::check(__metadataID)
696 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
697 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
698 }
699
700 template<OpcodeSize size, bool recordOpcode>
701 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity, unsigned __metadataID)
702 {
703 if (size == OpcodeSize::Wide16)
704 gen->alignWideOpcode16();
705 else if (size == OpcodeSize::Wide32)
706 gen->alignWideOpcode32();
707 if (checkImpl<size>(gen, dst, inlineCapacity, __metadataID)) {
708 if (recordOpcode)
709 gen->recordOpcode(opcodeID);
710 if (size == OpcodeSize::Wide16)
711 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
712 else if (size == OpcodeSize::Wide32)
713 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
714 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
715 gen->write(Fits<VirtualRegister, size>::convert(dst));
716 gen->write(Fits<unsigned, size>::convert(inlineCapacity));
717 gen->write(Fits<unsigned, size>::convert(__metadataID));
718 return true;
719 }
720 return false;
721 }
722
723public:
724 template<typename Block>
725 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
726 {
727 dumper->printLocationAndOp(__location, &"**new_object"[2 - __sizeShiftAmount]);
728 dumper->dumpOperand(m_dst, true);
729 dumper->dumpOperand(m_inlineCapacity, false);
730 }
731
732 OpNewObject(const uint8_t* stream)
733 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
734 , m_inlineCapacity(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
735 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
736 {
737 ASSERT_UNUSED(stream, stream[0] == opcodeID);
738 }
739
740 OpNewObject(const uint16_t* stream)
741 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
742 , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
743 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
744 {
745 ASSERT_UNUSED(stream, stream[0] == opcodeID);
746 }
747
748
749 OpNewObject(const uint32_t* stream)
750 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
751 , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
752 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
753 {
754 ASSERT_UNUSED(stream, stream[0] == opcodeID);
755 }
756
757 static OpNewObject decode(const uint8_t* stream)
758 {
759 if (*stream == op_wide32)
760 return { bitwise_cast<const uint32_t*>(stream + 1) };
761 if (*stream == op_wide16)
762 return { bitwise_cast<const uint16_t*>(stream + 1) };
763 return { stream };
764 }
765
766 template<typename Functor>
767 void setDst(VirtualRegister value, Functor func)
768 {
769 if (isWide32())
770 setDst<OpcodeSize::Wide32>(value, func);
771 else if (isWide16())
772 setDst<OpcodeSize::Wide16>(value, func);
773 else
774 setDst<OpcodeSize::Narrow>(value, func);
775 }
776
777 template <OpcodeSize size, typename Functor>
778 void setDst(VirtualRegister value, Functor func)
779 {
780 if (!Fits<VirtualRegister, size>::check(value))
781 value = func();
782 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
783 *stream = Fits<VirtualRegister, size>::convert(value);
784 }
785
786 template<typename Functor>
787 void setInlineCapacity(unsigned value, Functor func)
788 {
789 if (isWide32())
790 setInlineCapacity<OpcodeSize::Wide32>(value, func);
791 else if (isWide16())
792 setInlineCapacity<OpcodeSize::Wide16>(value, func);
793 else
794 setInlineCapacity<OpcodeSize::Narrow>(value, func);
795 }
796
797 template <OpcodeSize size, typename Functor>
798 void setInlineCapacity(unsigned value, Functor func)
799 {
800 if (!Fits<unsigned, size>::check(value))
801 value = func();
802 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
803 *stream = Fits<unsigned, size>::convert(value);
804 }
805
806 struct Metadata {
807 WTF_MAKE_NONCOPYABLE(Metadata);
808
809 public:
810 Metadata(const OpNewObject&) { }
811
812 ObjectAllocationProfile m_objectAllocationProfile;
813 };
814
815 Metadata& metadata(CodeBlock* codeBlock) const
816 {
817 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
818 }
819
820 Metadata& metadata(ExecState* exec) const
821 {
822 return metadata(exec->codeBlock());
823 }
824
825 VirtualRegister m_dst;
826 unsigned m_inlineCapacity;
827 unsigned m_metadataID;
828};
829
830struct OpNewArray : public Instruction {
831 static constexpr OpcodeID opcodeID = op_new_array;
832
833 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
834 {
835 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, argv, argc, recommendedIndexingType);
836 }
837
838 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
839 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
840 {
841 auto __metadataID = gen->addMetadataFor(opcodeID);
842 return emit<size, shouldAssert>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
843 }
844
845 template<OpcodeSize size>
846 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
847 {
848 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
849 return checkImpl<size>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
850 }
851
852 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
853 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType, unsigned __metadataID)
854 {
855 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
856 if (shouldAssert == Assert)
857 ASSERT(didEmit);
858 return didEmit;
859 }
860
861 template<OpcodeSize size>
862 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
863 {
864
865 auto __metadataID = gen->addMetadataFor(opcodeID);
866 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
867 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID))
868 return;
869 }
870 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
871 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID))
872 return;
873 }
874 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
875 }
876
877private:
878 template<OpcodeSize size>
879 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& argv, unsigned& argc, IndexingType& recommendedIndexingType, unsigned __metadataID)
880 {
881 UNUSED_PARAM(gen);
882#if OS(WINDOWS) && ENABLE(C_LOOP)
883 // FIXME: Disable wide16 optimization for Windows CLoop
884 // https://bugs.webkit.org/show_bug.cgi?id=198283
885 if (size == OpcodeSize::Wide16)
886 return false;
887#endif
888 return Fits<OpcodeID, size>::check(opcodeID)
889 && Fits<VirtualRegister, size>::check(dst)
890 && Fits<VirtualRegister, size>::check(argv)
891 && Fits<unsigned, size>::check(argc)
892 && Fits<IndexingType, size>::check(recommendedIndexingType)
893 && Fits<unsigned, size>::check(__metadataID)
894 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
895 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
896 }
897
898 template<OpcodeSize size, bool recordOpcode>
899 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType, unsigned __metadataID)
900 {
901 if (size == OpcodeSize::Wide16)
902 gen->alignWideOpcode16();
903 else if (size == OpcodeSize::Wide32)
904 gen->alignWideOpcode32();
905 if (checkImpl<size>(gen, dst, argv, argc, recommendedIndexingType, __metadataID)) {
906 if (recordOpcode)
907 gen->recordOpcode(opcodeID);
908 if (size == OpcodeSize::Wide16)
909 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
910 else if (size == OpcodeSize::Wide32)
911 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
912 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
913 gen->write(Fits<VirtualRegister, size>::convert(dst));
914 gen->write(Fits<VirtualRegister, size>::convert(argv));
915 gen->write(Fits<unsigned, size>::convert(argc));
916 gen->write(Fits<IndexingType, size>::convert(recommendedIndexingType));
917 gen->write(Fits<unsigned, size>::convert(__metadataID));
918 return true;
919 }
920 return false;
921 }
922
923public:
924 template<typename Block>
925 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
926 {
927 dumper->printLocationAndOp(__location, &"**new_array"[2 - __sizeShiftAmount]);
928 dumper->dumpOperand(m_dst, true);
929 dumper->dumpOperand(m_argv, false);
930 dumper->dumpOperand(m_argc, false);
931 dumper->dumpOperand(m_recommendedIndexingType, false);
932 }
933
934 OpNewArray(const uint8_t* stream)
935 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
936 , m_argv(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
937 , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
938 , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Narrow>::convert(stream[4]))
939 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
940 {
941 ASSERT_UNUSED(stream, stream[0] == opcodeID);
942 }
943
944 OpNewArray(const uint16_t* stream)
945 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
946 , m_argv(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
947 , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
948 , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide16>::convert(stream[4]))
949 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
950 {
951 ASSERT_UNUSED(stream, stream[0] == opcodeID);
952 }
953
954
955 OpNewArray(const uint32_t* stream)
956 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
957 , m_argv(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
958 , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
959 , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide32>::convert(stream[4]))
960 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
961 {
962 ASSERT_UNUSED(stream, stream[0] == opcodeID);
963 }
964
965 static OpNewArray decode(const uint8_t* stream)
966 {
967 if (*stream == op_wide32)
968 return { bitwise_cast<const uint32_t*>(stream + 1) };
969 if (*stream == op_wide16)
970 return { bitwise_cast<const uint16_t*>(stream + 1) };
971 return { stream };
972 }
973
974 template<typename Functor>
975 void setDst(VirtualRegister value, Functor func)
976 {
977 if (isWide32())
978 setDst<OpcodeSize::Wide32>(value, func);
979 else if (isWide16())
980 setDst<OpcodeSize::Wide16>(value, func);
981 else
982 setDst<OpcodeSize::Narrow>(value, func);
983 }
984
985 template <OpcodeSize size, typename Functor>
986 void setDst(VirtualRegister value, Functor func)
987 {
988 if (!Fits<VirtualRegister, size>::check(value))
989 value = func();
990 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
991 *stream = Fits<VirtualRegister, size>::convert(value);
992 }
993
994 template<typename Functor>
995 void setArgv(VirtualRegister value, Functor func)
996 {
997 if (isWide32())
998 setArgv<OpcodeSize::Wide32>(value, func);
999 else if (isWide16())
1000 setArgv<OpcodeSize::Wide16>(value, func);
1001 else
1002 setArgv<OpcodeSize::Narrow>(value, func);
1003 }
1004
1005 template <OpcodeSize size, typename Functor>
1006 void setArgv(VirtualRegister value, Functor func)
1007 {
1008 if (!Fits<VirtualRegister, size>::check(value))
1009 value = func();
1010 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
1011 *stream = Fits<VirtualRegister, size>::convert(value);
1012 }
1013
1014 template<typename Functor>
1015 void setArgc(unsigned value, Functor func)
1016 {
1017 if (isWide32())
1018 setArgc<OpcodeSize::Wide32>(value, func);
1019 else if (isWide16())
1020 setArgc<OpcodeSize::Wide16>(value, func);
1021 else
1022 setArgc<OpcodeSize::Narrow>(value, func);
1023 }
1024
1025 template <OpcodeSize size, typename Functor>
1026 void setArgc(unsigned value, Functor func)
1027 {
1028 if (!Fits<unsigned, size>::check(value))
1029 value = func();
1030 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
1031 *stream = Fits<unsigned, size>::convert(value);
1032 }
1033
1034 template<typename Functor>
1035 void setRecommendedIndexingType(IndexingType value, Functor func)
1036 {
1037 if (isWide32())
1038 setRecommendedIndexingType<OpcodeSize::Wide32>(value, func);
1039 else if (isWide16())
1040 setRecommendedIndexingType<OpcodeSize::Wide16>(value, func);
1041 else
1042 setRecommendedIndexingType<OpcodeSize::Narrow>(value, func);
1043 }
1044
1045 template <OpcodeSize size, typename Functor>
1046 void setRecommendedIndexingType(IndexingType value, Functor func)
1047 {
1048 if (!Fits<IndexingType, size>::check(value))
1049 value = func();
1050 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
1051 *stream = Fits<IndexingType, size>::convert(value);
1052 }
1053
1054 struct Metadata {
1055 WTF_MAKE_NONCOPYABLE(Metadata);
1056
1057 public:
1058 Metadata(const OpNewArray&) { }
1059
1060 ArrayAllocationProfile m_arrayAllocationProfile;
1061 };
1062
1063 Metadata& metadata(CodeBlock* codeBlock) const
1064 {
1065 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
1066 }
1067
1068 Metadata& metadata(ExecState* exec) const
1069 {
1070 return metadata(exec->codeBlock());
1071 }
1072
1073 VirtualRegister m_dst;
1074 VirtualRegister m_argv;
1075 unsigned m_argc;
1076 IndexingType m_recommendedIndexingType;
1077 unsigned m_metadataID;
1078};
1079
1080struct OpNewArrayWithSize : public Instruction {
1081 static constexpr OpcodeID opcodeID = op_new_array_with_size;
1082
1083 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
1084 {
1085 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, length);
1086 }
1087
1088 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
1089 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
1090 {
1091 auto __metadataID = gen->addMetadataFor(opcodeID);
1092 return emit<size, shouldAssert>(gen, dst, length, __metadataID);
1093 }
1094
1095 template<OpcodeSize size>
1096 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
1097 {
1098 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
1099 return checkImpl<size>(gen, dst, length, __metadataID);
1100 }
1101
1102 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
1103 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length, unsigned __metadataID)
1104 {
1105 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, length, __metadataID);
1106 if (shouldAssert == Assert)
1107 ASSERT(didEmit);
1108 return didEmit;
1109 }
1110
1111 template<OpcodeSize size>
1112 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
1113 {
1114
1115 auto __metadataID = gen->addMetadataFor(opcodeID);
1116 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
1117 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, length, __metadataID))
1118 return;
1119 }
1120 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
1121 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, length, __metadataID))
1122 return;
1123 }
1124 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, length, __metadataID);
1125 }
1126
1127private:
1128 template<OpcodeSize size>
1129 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& length, unsigned __metadataID)
1130 {
1131 UNUSED_PARAM(gen);
1132#if OS(WINDOWS) && ENABLE(C_LOOP)
1133 // FIXME: Disable wide16 optimization for Windows CLoop
1134 // https://bugs.webkit.org/show_bug.cgi?id=198283
1135 if (size == OpcodeSize::Wide16)
1136 return false;
1137#endif
1138 return Fits<OpcodeID, size>::check(opcodeID)
1139 && Fits<VirtualRegister, size>::check(dst)
1140 && Fits<VirtualRegister, size>::check(length)
1141 && Fits<unsigned, size>::check(__metadataID)
1142 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
1143 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
1144 }
1145
1146 template<OpcodeSize size, bool recordOpcode>
1147 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length, unsigned __metadataID)
1148 {
1149 if (size == OpcodeSize::Wide16)
1150 gen->alignWideOpcode16();
1151 else if (size == OpcodeSize::Wide32)
1152 gen->alignWideOpcode32();
1153 if (checkImpl<size>(gen, dst, length, __metadataID)) {
1154 if (recordOpcode)
1155 gen->recordOpcode(opcodeID);
1156 if (size == OpcodeSize::Wide16)
1157 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
1158 else if (size == OpcodeSize::Wide32)
1159 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
1160 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
1161 gen->write(Fits<VirtualRegister, size>::convert(dst));
1162 gen->write(Fits<VirtualRegister, size>::convert(length));
1163 gen->write(Fits<unsigned, size>::convert(__metadataID));
1164 return true;
1165 }
1166 return false;
1167 }
1168
1169public:
1170 template<typename Block>
1171 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
1172 {
1173 dumper->printLocationAndOp(__location, &"**new_array_with_size"[2 - __sizeShiftAmount]);
1174 dumper->dumpOperand(m_dst, true);
1175 dumper->dumpOperand(m_length, false);
1176 }
1177
1178 OpNewArrayWithSize(const uint8_t* stream)
1179 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
1180 , m_length(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
1181 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
1182 {
1183 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1184 }
1185
1186 OpNewArrayWithSize(const uint16_t* stream)
1187 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
1188 , m_length(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
1189 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
1190 {
1191 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1192 }
1193
1194
1195 OpNewArrayWithSize(const uint32_t* stream)
1196 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
1197 , m_length(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
1198 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
1199 {
1200 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1201 }
1202
1203 static OpNewArrayWithSize decode(const uint8_t* stream)
1204 {
1205 if (*stream == op_wide32)
1206 return { bitwise_cast<const uint32_t*>(stream + 1) };
1207 if (*stream == op_wide16)
1208 return { bitwise_cast<const uint16_t*>(stream + 1) };
1209 return { stream };
1210 }
1211
1212 template<typename Functor>
1213 void setDst(VirtualRegister value, Functor func)
1214 {
1215 if (isWide32())
1216 setDst<OpcodeSize::Wide32>(value, func);
1217 else if (isWide16())
1218 setDst<OpcodeSize::Wide16>(value, func);
1219 else
1220 setDst<OpcodeSize::Narrow>(value, func);
1221 }
1222
1223 template <OpcodeSize size, typename Functor>
1224 void setDst(VirtualRegister value, Functor func)
1225 {
1226 if (!Fits<VirtualRegister, size>::check(value))
1227 value = func();
1228 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
1229 *stream = Fits<VirtualRegister, size>::convert(value);
1230 }
1231
1232 template<typename Functor>
1233 void setLength(VirtualRegister value, Functor func)
1234 {
1235 if (isWide32())
1236 setLength<OpcodeSize::Wide32>(value, func);
1237 else if (isWide16())
1238 setLength<OpcodeSize::Wide16>(value, func);
1239 else
1240 setLength<OpcodeSize::Narrow>(value, func);
1241 }
1242
1243 template <OpcodeSize size, typename Functor>
1244 void setLength(VirtualRegister value, Functor func)
1245 {
1246 if (!Fits<VirtualRegister, size>::check(value))
1247 value = func();
1248 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
1249 *stream = Fits<VirtualRegister, size>::convert(value);
1250 }
1251
1252 struct Metadata {
1253 WTF_MAKE_NONCOPYABLE(Metadata);
1254
1255 public:
1256 Metadata(const OpNewArrayWithSize&) { }
1257
1258 ArrayAllocationProfile m_arrayAllocationProfile;
1259 };
1260
1261 Metadata& metadata(CodeBlock* codeBlock) const
1262 {
1263 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
1264 }
1265
1266 Metadata& metadata(ExecState* exec) const
1267 {
1268 return metadata(exec->codeBlock());
1269 }
1270
1271 VirtualRegister m_dst;
1272 VirtualRegister m_length;
1273 unsigned m_metadataID;
1274};
1275
1276struct OpNewArrayBuffer : public Instruction {
1277 static constexpr OpcodeID opcodeID = op_new_array_buffer;
1278
1279 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
1280 {
1281 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, immutableButterfly, recommendedIndexingType);
1282 }
1283
1284 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
1285 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
1286 {
1287 auto __metadataID = gen->addMetadataFor(opcodeID);
1288 return emit<size, shouldAssert>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
1289 }
1290
1291 template<OpcodeSize size>
1292 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
1293 {
1294 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
1295 return checkImpl<size>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
1296 }
1297
1298 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
1299 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType, unsigned __metadataID)
1300 {
1301 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
1302 if (shouldAssert == Assert)
1303 ASSERT(didEmit);
1304 return didEmit;
1305 }
1306
1307 template<OpcodeSize size>
1308 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
1309 {
1310
1311 auto __metadataID = gen->addMetadataFor(opcodeID);
1312 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
1313 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID))
1314 return;
1315 }
1316 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
1317 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID))
1318 return;
1319 }
1320 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
1321 }
1322
1323private:
1324 template<OpcodeSize size>
1325 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& immutableButterfly, IndexingType& recommendedIndexingType, unsigned __metadataID)
1326 {
1327 UNUSED_PARAM(gen);
1328#if OS(WINDOWS) && ENABLE(C_LOOP)
1329 // FIXME: Disable wide16 optimization for Windows CLoop
1330 // https://bugs.webkit.org/show_bug.cgi?id=198283
1331 if (size == OpcodeSize::Wide16)
1332 return false;
1333#endif
1334 return Fits<OpcodeID, size>::check(opcodeID)
1335 && Fits<VirtualRegister, size>::check(dst)
1336 && Fits<VirtualRegister, size>::check(immutableButterfly)
1337 && Fits<IndexingType, size>::check(recommendedIndexingType)
1338 && Fits<unsigned, size>::check(__metadataID)
1339 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
1340 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
1341 }
1342
1343 template<OpcodeSize size, bool recordOpcode>
1344 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType, unsigned __metadataID)
1345 {
1346 if (size == OpcodeSize::Wide16)
1347 gen->alignWideOpcode16();
1348 else if (size == OpcodeSize::Wide32)
1349 gen->alignWideOpcode32();
1350 if (checkImpl<size>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID)) {
1351 if (recordOpcode)
1352 gen->recordOpcode(opcodeID);
1353 if (size == OpcodeSize::Wide16)
1354 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
1355 else if (size == OpcodeSize::Wide32)
1356 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
1357 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
1358 gen->write(Fits<VirtualRegister, size>::convert(dst));
1359 gen->write(Fits<VirtualRegister, size>::convert(immutableButterfly));
1360 gen->write(Fits<IndexingType, size>::convert(recommendedIndexingType));
1361 gen->write(Fits<unsigned, size>::convert(__metadataID));
1362 return true;
1363 }
1364 return false;
1365 }
1366
1367public:
1368 template<typename Block>
1369 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
1370 {
1371 dumper->printLocationAndOp(__location, &"**new_array_buffer"[2 - __sizeShiftAmount]);
1372 dumper->dumpOperand(m_dst, true);
1373 dumper->dumpOperand(m_immutableButterfly, false);
1374 dumper->dumpOperand(m_recommendedIndexingType, false);
1375 }
1376
1377 OpNewArrayBuffer(const uint8_t* stream)
1378 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
1379 , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
1380 , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Narrow>::convert(stream[3]))
1381 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
1382 {
1383 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1384 }
1385
1386 OpNewArrayBuffer(const uint16_t* stream)
1387 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
1388 , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
1389 , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide16>::convert(stream[3]))
1390 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
1391 {
1392 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1393 }
1394
1395
1396 OpNewArrayBuffer(const uint32_t* stream)
1397 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
1398 , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
1399 , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide32>::convert(stream[3]))
1400 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
1401 {
1402 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1403 }
1404
1405 static OpNewArrayBuffer decode(const uint8_t* stream)
1406 {
1407 if (*stream == op_wide32)
1408 return { bitwise_cast<const uint32_t*>(stream + 1) };
1409 if (*stream == op_wide16)
1410 return { bitwise_cast<const uint16_t*>(stream + 1) };
1411 return { stream };
1412 }
1413
1414 template<typename Functor>
1415 void setDst(VirtualRegister value, Functor func)
1416 {
1417 if (isWide32())
1418 setDst<OpcodeSize::Wide32>(value, func);
1419 else if (isWide16())
1420 setDst<OpcodeSize::Wide16>(value, func);
1421 else
1422 setDst<OpcodeSize::Narrow>(value, func);
1423 }
1424
1425 template <OpcodeSize size, typename Functor>
1426 void setDst(VirtualRegister value, Functor func)
1427 {
1428 if (!Fits<VirtualRegister, size>::check(value))
1429 value = func();
1430 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
1431 *stream = Fits<VirtualRegister, size>::convert(value);
1432 }
1433
1434 template<typename Functor>
1435 void setImmutableButterfly(VirtualRegister value, Functor func)
1436 {
1437 if (isWide32())
1438 setImmutableButterfly<OpcodeSize::Wide32>(value, func);
1439 else if (isWide16())
1440 setImmutableButterfly<OpcodeSize::Wide16>(value, func);
1441 else
1442 setImmutableButterfly<OpcodeSize::Narrow>(value, func);
1443 }
1444
1445 template <OpcodeSize size, typename Functor>
1446 void setImmutableButterfly(VirtualRegister value, Functor func)
1447 {
1448 if (!Fits<VirtualRegister, size>::check(value))
1449 value = func();
1450 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
1451 *stream = Fits<VirtualRegister, size>::convert(value);
1452 }
1453
1454 template<typename Functor>
1455 void setRecommendedIndexingType(IndexingType value, Functor func)
1456 {
1457 if (isWide32())
1458 setRecommendedIndexingType<OpcodeSize::Wide32>(value, func);
1459 else if (isWide16())
1460 setRecommendedIndexingType<OpcodeSize::Wide16>(value, func);
1461 else
1462 setRecommendedIndexingType<OpcodeSize::Narrow>(value, func);
1463 }
1464
1465 template <OpcodeSize size, typename Functor>
1466 void setRecommendedIndexingType(IndexingType value, Functor func)
1467 {
1468 if (!Fits<IndexingType, size>::check(value))
1469 value = func();
1470 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
1471 *stream = Fits<IndexingType, size>::convert(value);
1472 }
1473
1474 struct Metadata {
1475 WTF_MAKE_NONCOPYABLE(Metadata);
1476
1477 public:
1478 Metadata(const OpNewArrayBuffer&) { }
1479
1480 ArrayAllocationProfile m_arrayAllocationProfile;
1481 };
1482
1483 Metadata& metadata(CodeBlock* codeBlock) const
1484 {
1485 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
1486 }
1487
1488 Metadata& metadata(ExecState* exec) const
1489 {
1490 return metadata(exec->codeBlock());
1491 }
1492
1493 VirtualRegister m_dst;
1494 VirtualRegister m_immutableButterfly;
1495 IndexingType m_recommendedIndexingType;
1496 unsigned m_metadataID;
1497};
1498
1499struct OpAdd : public Instruction {
1500 static constexpr OpcodeID opcodeID = op_add;
1501
1502 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1503 {
1504 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs, operandTypes);
1505 }
1506
1507 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
1508 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1509 {
1510 auto __metadataID = gen->addMetadataFor(opcodeID);
1511 return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1512 }
1513
1514 template<OpcodeSize size>
1515 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1516 {
1517 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
1518 return checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1519 }
1520
1521 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
1522 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
1523 {
1524 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1525 if (shouldAssert == Assert)
1526 ASSERT(didEmit);
1527 return didEmit;
1528 }
1529
1530 template<OpcodeSize size>
1531 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1532 {
1533
1534 auto __metadataID = gen->addMetadataFor(opcodeID);
1535 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
1536 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
1537 return;
1538 }
1539 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
1540 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
1541 return;
1542 }
1543 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1544 }
1545
1546private:
1547 template<OpcodeSize size>
1548 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
1549 {
1550 UNUSED_PARAM(gen);
1551#if OS(WINDOWS) && ENABLE(C_LOOP)
1552 // FIXME: Disable wide16 optimization for Windows CLoop
1553 // https://bugs.webkit.org/show_bug.cgi?id=198283
1554 if (size == OpcodeSize::Wide16)
1555 return false;
1556#endif
1557 return Fits<OpcodeID, size>::check(opcodeID)
1558 && Fits<VirtualRegister, size>::check(dst)
1559 && Fits<VirtualRegister, size>::check(lhs)
1560 && Fits<VirtualRegister, size>::check(rhs)
1561 && Fits<OperandTypes, size>::check(operandTypes)
1562 && Fits<unsigned, size>::check(__metadataID)
1563 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
1564 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
1565 }
1566
1567 template<OpcodeSize size, bool recordOpcode>
1568 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
1569 {
1570 if (size == OpcodeSize::Wide16)
1571 gen->alignWideOpcode16();
1572 else if (size == OpcodeSize::Wide32)
1573 gen->alignWideOpcode32();
1574 if (checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
1575 if (recordOpcode)
1576 gen->recordOpcode(opcodeID);
1577 if (size == OpcodeSize::Wide16)
1578 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
1579 else if (size == OpcodeSize::Wide32)
1580 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
1581 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
1582 gen->write(Fits<VirtualRegister, size>::convert(dst));
1583 gen->write(Fits<VirtualRegister, size>::convert(lhs));
1584 gen->write(Fits<VirtualRegister, size>::convert(rhs));
1585 gen->write(Fits<OperandTypes, size>::convert(operandTypes));
1586 gen->write(Fits<unsigned, size>::convert(__metadataID));
1587 return true;
1588 }
1589 return false;
1590 }
1591
1592public:
1593 template<typename Block>
1594 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
1595 {
1596 dumper->printLocationAndOp(__location, &"**add"[2 - __sizeShiftAmount]);
1597 dumper->dumpOperand(m_dst, true);
1598 dumper->dumpOperand(m_lhs, false);
1599 dumper->dumpOperand(m_rhs, false);
1600 dumper->dumpOperand(m_operandTypes, false);
1601 }
1602
1603 OpAdd(const uint8_t* stream)
1604 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
1605 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
1606 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
1607 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4]))
1608 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
1609 {
1610 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1611 }
1612
1613 OpAdd(const uint16_t* stream)
1614 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
1615 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
1616 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
1617 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[4]))
1618 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
1619 {
1620 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1621 }
1622
1623
1624 OpAdd(const uint32_t* stream)
1625 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
1626 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
1627 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
1628 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[4]))
1629 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
1630 {
1631 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1632 }
1633
1634 static OpAdd decode(const uint8_t* stream)
1635 {
1636 if (*stream == op_wide32)
1637 return { bitwise_cast<const uint32_t*>(stream + 1) };
1638 if (*stream == op_wide16)
1639 return { bitwise_cast<const uint16_t*>(stream + 1) };
1640 return { stream };
1641 }
1642
1643 template<typename Functor>
1644 void setDst(VirtualRegister value, Functor func)
1645 {
1646 if (isWide32())
1647 setDst<OpcodeSize::Wide32>(value, func);
1648 else if (isWide16())
1649 setDst<OpcodeSize::Wide16>(value, func);
1650 else
1651 setDst<OpcodeSize::Narrow>(value, func);
1652 }
1653
1654 template <OpcodeSize size, typename Functor>
1655 void setDst(VirtualRegister value, Functor func)
1656 {
1657 if (!Fits<VirtualRegister, size>::check(value))
1658 value = func();
1659 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
1660 *stream = Fits<VirtualRegister, size>::convert(value);
1661 }
1662
1663 template<typename Functor>
1664 void setLhs(VirtualRegister value, Functor func)
1665 {
1666 if (isWide32())
1667 setLhs<OpcodeSize::Wide32>(value, func);
1668 else if (isWide16())
1669 setLhs<OpcodeSize::Wide16>(value, func);
1670 else
1671 setLhs<OpcodeSize::Narrow>(value, func);
1672 }
1673
1674 template <OpcodeSize size, typename Functor>
1675 void setLhs(VirtualRegister value, Functor func)
1676 {
1677 if (!Fits<VirtualRegister, size>::check(value))
1678 value = func();
1679 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
1680 *stream = Fits<VirtualRegister, size>::convert(value);
1681 }
1682
1683 template<typename Functor>
1684 void setRhs(VirtualRegister value, Functor func)
1685 {
1686 if (isWide32())
1687 setRhs<OpcodeSize::Wide32>(value, func);
1688 else if (isWide16())
1689 setRhs<OpcodeSize::Wide16>(value, func);
1690 else
1691 setRhs<OpcodeSize::Narrow>(value, func);
1692 }
1693
1694 template <OpcodeSize size, typename Functor>
1695 void setRhs(VirtualRegister value, Functor func)
1696 {
1697 if (!Fits<VirtualRegister, size>::check(value))
1698 value = func();
1699 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
1700 *stream = Fits<VirtualRegister, size>::convert(value);
1701 }
1702
1703 template<typename Functor>
1704 void setOperandTypes(OperandTypes value, Functor func)
1705 {
1706 if (isWide32())
1707 setOperandTypes<OpcodeSize::Wide32>(value, func);
1708 else if (isWide16())
1709 setOperandTypes<OpcodeSize::Wide16>(value, func);
1710 else
1711 setOperandTypes<OpcodeSize::Narrow>(value, func);
1712 }
1713
1714 template <OpcodeSize size, typename Functor>
1715 void setOperandTypes(OperandTypes value, Functor func)
1716 {
1717 if (!Fits<OperandTypes, size>::check(value))
1718 value = func();
1719 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
1720 *stream = Fits<OperandTypes, size>::convert(value);
1721 }
1722
1723 struct Metadata {
1724 WTF_MAKE_NONCOPYABLE(Metadata);
1725
1726 public:
1727 Metadata(const OpAdd& __op)
1728 : m_arithProfile(__op.m_operandTypes)
1729 { }
1730
1731 ArithProfile m_arithProfile;
1732 };
1733
1734 Metadata& metadata(CodeBlock* codeBlock) const
1735 {
1736 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
1737 }
1738
1739 Metadata& metadata(ExecState* exec) const
1740 {
1741 return metadata(exec->codeBlock());
1742 }
1743
1744 VirtualRegister m_dst;
1745 VirtualRegister m_lhs;
1746 VirtualRegister m_rhs;
1747 OperandTypes m_operandTypes;
1748 unsigned m_metadataID;
1749};
1750
1751struct OpMul : public Instruction {
1752 static constexpr OpcodeID opcodeID = op_mul;
1753
1754 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1755 {
1756 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs, operandTypes);
1757 }
1758
1759 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
1760 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1761 {
1762 auto __metadataID = gen->addMetadataFor(opcodeID);
1763 return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1764 }
1765
1766 template<OpcodeSize size>
1767 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1768 {
1769 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
1770 return checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1771 }
1772
1773 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
1774 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
1775 {
1776 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1777 if (shouldAssert == Assert)
1778 ASSERT(didEmit);
1779 return didEmit;
1780 }
1781
1782 template<OpcodeSize size>
1783 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
1784 {
1785
1786 auto __metadataID = gen->addMetadataFor(opcodeID);
1787 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
1788 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
1789 return;
1790 }
1791 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
1792 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
1793 return;
1794 }
1795 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
1796 }
1797
1798private:
1799 template<OpcodeSize size>
1800 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
1801 {
1802 UNUSED_PARAM(gen);
1803#if OS(WINDOWS) && ENABLE(C_LOOP)
1804 // FIXME: Disable wide16 optimization for Windows CLoop
1805 // https://bugs.webkit.org/show_bug.cgi?id=198283
1806 if (size == OpcodeSize::Wide16)
1807 return false;
1808#endif
1809 return Fits<OpcodeID, size>::check(opcodeID)
1810 && Fits<VirtualRegister, size>::check(dst)
1811 && Fits<VirtualRegister, size>::check(lhs)
1812 && Fits<VirtualRegister, size>::check(rhs)
1813 && Fits<OperandTypes, size>::check(operandTypes)
1814 && Fits<unsigned, size>::check(__metadataID)
1815 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
1816 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
1817 }
1818
1819 template<OpcodeSize size, bool recordOpcode>
1820 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
1821 {
1822 if (size == OpcodeSize::Wide16)
1823 gen->alignWideOpcode16();
1824 else if (size == OpcodeSize::Wide32)
1825 gen->alignWideOpcode32();
1826 if (checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
1827 if (recordOpcode)
1828 gen->recordOpcode(opcodeID);
1829 if (size == OpcodeSize::Wide16)
1830 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
1831 else if (size == OpcodeSize::Wide32)
1832 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
1833 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
1834 gen->write(Fits<VirtualRegister, size>::convert(dst));
1835 gen->write(Fits<VirtualRegister, size>::convert(lhs));
1836 gen->write(Fits<VirtualRegister, size>::convert(rhs));
1837 gen->write(Fits<OperandTypes, size>::convert(operandTypes));
1838 gen->write(Fits<unsigned, size>::convert(__metadataID));
1839 return true;
1840 }
1841 return false;
1842 }
1843
1844public:
1845 template<typename Block>
1846 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
1847 {
1848 dumper->printLocationAndOp(__location, &"**mul"[2 - __sizeShiftAmount]);
1849 dumper->dumpOperand(m_dst, true);
1850 dumper->dumpOperand(m_lhs, false);
1851 dumper->dumpOperand(m_rhs, false);
1852 dumper->dumpOperand(m_operandTypes, false);
1853 }
1854
1855 OpMul(const uint8_t* stream)
1856 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
1857 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
1858 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
1859 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4]))
1860 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
1861 {
1862 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1863 }
1864
1865 OpMul(const uint16_t* stream)
1866 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
1867 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
1868 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
1869 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[4]))
1870 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
1871 {
1872 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1873 }
1874
1875
1876 OpMul(const uint32_t* stream)
1877 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
1878 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
1879 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
1880 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[4]))
1881 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
1882 {
1883 ASSERT_UNUSED(stream, stream[0] == opcodeID);
1884 }
1885
1886 static OpMul decode(const uint8_t* stream)
1887 {
1888 if (*stream == op_wide32)
1889 return { bitwise_cast<const uint32_t*>(stream + 1) };
1890 if (*stream == op_wide16)
1891 return { bitwise_cast<const uint16_t*>(stream + 1) };
1892 return { stream };
1893 }
1894
1895 template<typename Functor>
1896 void setDst(VirtualRegister value, Functor func)
1897 {
1898 if (isWide32())
1899 setDst<OpcodeSize::Wide32>(value, func);
1900 else if (isWide16())
1901 setDst<OpcodeSize::Wide16>(value, func);
1902 else
1903 setDst<OpcodeSize::Narrow>(value, func);
1904 }
1905
1906 template <OpcodeSize size, typename Functor>
1907 void setDst(VirtualRegister value, Functor func)
1908 {
1909 if (!Fits<VirtualRegister, size>::check(value))
1910 value = func();
1911 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
1912 *stream = Fits<VirtualRegister, size>::convert(value);
1913 }
1914
1915 template<typename Functor>
1916 void setLhs(VirtualRegister value, Functor func)
1917 {
1918 if (isWide32())
1919 setLhs<OpcodeSize::Wide32>(value, func);
1920 else if (isWide16())
1921 setLhs<OpcodeSize::Wide16>(value, func);
1922 else
1923 setLhs<OpcodeSize::Narrow>(value, func);
1924 }
1925
1926 template <OpcodeSize size, typename Functor>
1927 void setLhs(VirtualRegister value, Functor func)
1928 {
1929 if (!Fits<VirtualRegister, size>::check(value))
1930 value = func();
1931 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
1932 *stream = Fits<VirtualRegister, size>::convert(value);
1933 }
1934
1935 template<typename Functor>
1936 void setRhs(VirtualRegister value, Functor func)
1937 {
1938 if (isWide32())
1939 setRhs<OpcodeSize::Wide32>(value, func);
1940 else if (isWide16())
1941 setRhs<OpcodeSize::Wide16>(value, func);
1942 else
1943 setRhs<OpcodeSize::Narrow>(value, func);
1944 }
1945
1946 template <OpcodeSize size, typename Functor>
1947 void setRhs(VirtualRegister value, Functor func)
1948 {
1949 if (!Fits<VirtualRegister, size>::check(value))
1950 value = func();
1951 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
1952 *stream = Fits<VirtualRegister, size>::convert(value);
1953 }
1954
1955 template<typename Functor>
1956 void setOperandTypes(OperandTypes value, Functor func)
1957 {
1958 if (isWide32())
1959 setOperandTypes<OpcodeSize::Wide32>(value, func);
1960 else if (isWide16())
1961 setOperandTypes<OpcodeSize::Wide16>(value, func);
1962 else
1963 setOperandTypes<OpcodeSize::Narrow>(value, func);
1964 }
1965
1966 template <OpcodeSize size, typename Functor>
1967 void setOperandTypes(OperandTypes value, Functor func)
1968 {
1969 if (!Fits<OperandTypes, size>::check(value))
1970 value = func();
1971 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
1972 *stream = Fits<OperandTypes, size>::convert(value);
1973 }
1974
1975 struct Metadata {
1976 WTF_MAKE_NONCOPYABLE(Metadata);
1977
1978 public:
1979 Metadata(const OpMul& __op)
1980 : m_arithProfile(__op.m_operandTypes)
1981 { }
1982
1983 ArithProfile m_arithProfile;
1984 };
1985
1986 Metadata& metadata(CodeBlock* codeBlock) const
1987 {
1988 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
1989 }
1990
1991 Metadata& metadata(ExecState* exec) const
1992 {
1993 return metadata(exec->codeBlock());
1994 }
1995
1996 VirtualRegister m_dst;
1997 VirtualRegister m_lhs;
1998 VirtualRegister m_rhs;
1999 OperandTypes m_operandTypes;
2000 unsigned m_metadataID;
2001};
2002
2003struct OpDiv : public Instruction {
2004 static constexpr OpcodeID opcodeID = op_div;
2005
2006 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2007 {
2008 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs, operandTypes);
2009 }
2010
2011 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
2012 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2013 {
2014 auto __metadataID = gen->addMetadataFor(opcodeID);
2015 return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2016 }
2017
2018 template<OpcodeSize size>
2019 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2020 {
2021 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
2022 return checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2023 }
2024
2025 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
2026 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
2027 {
2028 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2029 if (shouldAssert == Assert)
2030 ASSERT(didEmit);
2031 return didEmit;
2032 }
2033
2034 template<OpcodeSize size>
2035 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2036 {
2037
2038 auto __metadataID = gen->addMetadataFor(opcodeID);
2039 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
2040 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
2041 return;
2042 }
2043 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
2044 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
2045 return;
2046 }
2047 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2048 }
2049
2050private:
2051 template<OpcodeSize size>
2052 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
2053 {
2054 UNUSED_PARAM(gen);
2055#if OS(WINDOWS) && ENABLE(C_LOOP)
2056 // FIXME: Disable wide16 optimization for Windows CLoop
2057 // https://bugs.webkit.org/show_bug.cgi?id=198283
2058 if (size == OpcodeSize::Wide16)
2059 return false;
2060#endif
2061 return Fits<OpcodeID, size>::check(opcodeID)
2062 && Fits<VirtualRegister, size>::check(dst)
2063 && Fits<VirtualRegister, size>::check(lhs)
2064 && Fits<VirtualRegister, size>::check(rhs)
2065 && Fits<OperandTypes, size>::check(operandTypes)
2066 && Fits<unsigned, size>::check(__metadataID)
2067 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
2068 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
2069 }
2070
2071 template<OpcodeSize size, bool recordOpcode>
2072 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
2073 {
2074 if (size == OpcodeSize::Wide16)
2075 gen->alignWideOpcode16();
2076 else if (size == OpcodeSize::Wide32)
2077 gen->alignWideOpcode32();
2078 if (checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
2079 if (recordOpcode)
2080 gen->recordOpcode(opcodeID);
2081 if (size == OpcodeSize::Wide16)
2082 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
2083 else if (size == OpcodeSize::Wide32)
2084 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
2085 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
2086 gen->write(Fits<VirtualRegister, size>::convert(dst));
2087 gen->write(Fits<VirtualRegister, size>::convert(lhs));
2088 gen->write(Fits<VirtualRegister, size>::convert(rhs));
2089 gen->write(Fits<OperandTypes, size>::convert(operandTypes));
2090 gen->write(Fits<unsigned, size>::convert(__metadataID));
2091 return true;
2092 }
2093 return false;
2094 }
2095
2096public:
2097 template<typename Block>
2098 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
2099 {
2100 dumper->printLocationAndOp(__location, &"**div"[2 - __sizeShiftAmount]);
2101 dumper->dumpOperand(m_dst, true);
2102 dumper->dumpOperand(m_lhs, false);
2103 dumper->dumpOperand(m_rhs, false);
2104 dumper->dumpOperand(m_operandTypes, false);
2105 }
2106
2107 OpDiv(const uint8_t* stream)
2108 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
2109 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
2110 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
2111 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4]))
2112 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
2113 {
2114 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2115 }
2116
2117 OpDiv(const uint16_t* stream)
2118 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
2119 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
2120 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
2121 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[4]))
2122 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
2123 {
2124 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2125 }
2126
2127
2128 OpDiv(const uint32_t* stream)
2129 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
2130 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
2131 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
2132 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[4]))
2133 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
2134 {
2135 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2136 }
2137
2138 static OpDiv decode(const uint8_t* stream)
2139 {
2140 if (*stream == op_wide32)
2141 return { bitwise_cast<const uint32_t*>(stream + 1) };
2142 if (*stream == op_wide16)
2143 return { bitwise_cast<const uint16_t*>(stream + 1) };
2144 return { stream };
2145 }
2146
2147 template<typename Functor>
2148 void setDst(VirtualRegister value, Functor func)
2149 {
2150 if (isWide32())
2151 setDst<OpcodeSize::Wide32>(value, func);
2152 else if (isWide16())
2153 setDst<OpcodeSize::Wide16>(value, func);
2154 else
2155 setDst<OpcodeSize::Narrow>(value, func);
2156 }
2157
2158 template <OpcodeSize size, typename Functor>
2159 void setDst(VirtualRegister value, Functor func)
2160 {
2161 if (!Fits<VirtualRegister, size>::check(value))
2162 value = func();
2163 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
2164 *stream = Fits<VirtualRegister, size>::convert(value);
2165 }
2166
2167 template<typename Functor>
2168 void setLhs(VirtualRegister value, Functor func)
2169 {
2170 if (isWide32())
2171 setLhs<OpcodeSize::Wide32>(value, func);
2172 else if (isWide16())
2173 setLhs<OpcodeSize::Wide16>(value, func);
2174 else
2175 setLhs<OpcodeSize::Narrow>(value, func);
2176 }
2177
2178 template <OpcodeSize size, typename Functor>
2179 void setLhs(VirtualRegister value, Functor func)
2180 {
2181 if (!Fits<VirtualRegister, size>::check(value))
2182 value = func();
2183 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
2184 *stream = Fits<VirtualRegister, size>::convert(value);
2185 }
2186
2187 template<typename Functor>
2188 void setRhs(VirtualRegister value, Functor func)
2189 {
2190 if (isWide32())
2191 setRhs<OpcodeSize::Wide32>(value, func);
2192 else if (isWide16())
2193 setRhs<OpcodeSize::Wide16>(value, func);
2194 else
2195 setRhs<OpcodeSize::Narrow>(value, func);
2196 }
2197
2198 template <OpcodeSize size, typename Functor>
2199 void setRhs(VirtualRegister value, Functor func)
2200 {
2201 if (!Fits<VirtualRegister, size>::check(value))
2202 value = func();
2203 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
2204 *stream = Fits<VirtualRegister, size>::convert(value);
2205 }
2206
2207 template<typename Functor>
2208 void setOperandTypes(OperandTypes value, Functor func)
2209 {
2210 if (isWide32())
2211 setOperandTypes<OpcodeSize::Wide32>(value, func);
2212 else if (isWide16())
2213 setOperandTypes<OpcodeSize::Wide16>(value, func);
2214 else
2215 setOperandTypes<OpcodeSize::Narrow>(value, func);
2216 }
2217
2218 template <OpcodeSize size, typename Functor>
2219 void setOperandTypes(OperandTypes value, Functor func)
2220 {
2221 if (!Fits<OperandTypes, size>::check(value))
2222 value = func();
2223 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
2224 *stream = Fits<OperandTypes, size>::convert(value);
2225 }
2226
2227 struct Metadata {
2228 WTF_MAKE_NONCOPYABLE(Metadata);
2229
2230 public:
2231 Metadata(const OpDiv& __op)
2232 : m_arithProfile(__op.m_operandTypes)
2233 { }
2234
2235 ArithProfile m_arithProfile;
2236 };
2237
2238 Metadata& metadata(CodeBlock* codeBlock) const
2239 {
2240 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
2241 }
2242
2243 Metadata& metadata(ExecState* exec) const
2244 {
2245 return metadata(exec->codeBlock());
2246 }
2247
2248 VirtualRegister m_dst;
2249 VirtualRegister m_lhs;
2250 VirtualRegister m_rhs;
2251 OperandTypes m_operandTypes;
2252 unsigned m_metadataID;
2253};
2254
2255struct OpSub : public Instruction {
2256 static constexpr OpcodeID opcodeID = op_sub;
2257
2258 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2259 {
2260 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs, operandTypes);
2261 }
2262
2263 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
2264 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2265 {
2266 auto __metadataID = gen->addMetadataFor(opcodeID);
2267 return emit<size, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2268 }
2269
2270 template<OpcodeSize size>
2271 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2272 {
2273 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
2274 return checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2275 }
2276
2277 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
2278 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
2279 {
2280 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2281 if (shouldAssert == Assert)
2282 ASSERT(didEmit);
2283 return didEmit;
2284 }
2285
2286 template<OpcodeSize size>
2287 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
2288 {
2289
2290 auto __metadataID = gen->addMetadataFor(opcodeID);
2291 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
2292 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
2293 return;
2294 }
2295 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
2296 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
2297 return;
2298 }
2299 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
2300 }
2301
2302private:
2303 template<OpcodeSize size>
2304 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
2305 {
2306 UNUSED_PARAM(gen);
2307#if OS(WINDOWS) && ENABLE(C_LOOP)
2308 // FIXME: Disable wide16 optimization for Windows CLoop
2309 // https://bugs.webkit.org/show_bug.cgi?id=198283
2310 if (size == OpcodeSize::Wide16)
2311 return false;
2312#endif
2313 return Fits<OpcodeID, size>::check(opcodeID)
2314 && Fits<VirtualRegister, size>::check(dst)
2315 && Fits<VirtualRegister, size>::check(lhs)
2316 && Fits<VirtualRegister, size>::check(rhs)
2317 && Fits<OperandTypes, size>::check(operandTypes)
2318 && Fits<unsigned, size>::check(__metadataID)
2319 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
2320 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
2321 }
2322
2323 template<OpcodeSize size, bool recordOpcode>
2324 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
2325 {
2326 if (size == OpcodeSize::Wide16)
2327 gen->alignWideOpcode16();
2328 else if (size == OpcodeSize::Wide32)
2329 gen->alignWideOpcode32();
2330 if (checkImpl<size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
2331 if (recordOpcode)
2332 gen->recordOpcode(opcodeID);
2333 if (size == OpcodeSize::Wide16)
2334 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
2335 else if (size == OpcodeSize::Wide32)
2336 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
2337 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
2338 gen->write(Fits<VirtualRegister, size>::convert(dst));
2339 gen->write(Fits<VirtualRegister, size>::convert(lhs));
2340 gen->write(Fits<VirtualRegister, size>::convert(rhs));
2341 gen->write(Fits<OperandTypes, size>::convert(operandTypes));
2342 gen->write(Fits<unsigned, size>::convert(__metadataID));
2343 return true;
2344 }
2345 return false;
2346 }
2347
2348public:
2349 template<typename Block>
2350 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
2351 {
2352 dumper->printLocationAndOp(__location, &"**sub"[2 - __sizeShiftAmount]);
2353 dumper->dumpOperand(m_dst, true);
2354 dumper->dumpOperand(m_lhs, false);
2355 dumper->dumpOperand(m_rhs, false);
2356 dumper->dumpOperand(m_operandTypes, false);
2357 }
2358
2359 OpSub(const uint8_t* stream)
2360 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
2361 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
2362 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
2363 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[4]))
2364 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
2365 {
2366 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2367 }
2368
2369 OpSub(const uint16_t* stream)
2370 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
2371 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
2372 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
2373 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[4]))
2374 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
2375 {
2376 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2377 }
2378
2379
2380 OpSub(const uint32_t* stream)
2381 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
2382 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
2383 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
2384 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[4]))
2385 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
2386 {
2387 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2388 }
2389
2390 static OpSub decode(const uint8_t* stream)
2391 {
2392 if (*stream == op_wide32)
2393 return { bitwise_cast<const uint32_t*>(stream + 1) };
2394 if (*stream == op_wide16)
2395 return { bitwise_cast<const uint16_t*>(stream + 1) };
2396 return { stream };
2397 }
2398
2399 template<typename Functor>
2400 void setDst(VirtualRegister value, Functor func)
2401 {
2402 if (isWide32())
2403 setDst<OpcodeSize::Wide32>(value, func);
2404 else if (isWide16())
2405 setDst<OpcodeSize::Wide16>(value, func);
2406 else
2407 setDst<OpcodeSize::Narrow>(value, func);
2408 }
2409
2410 template <OpcodeSize size, typename Functor>
2411 void setDst(VirtualRegister value, Functor func)
2412 {
2413 if (!Fits<VirtualRegister, size>::check(value))
2414 value = func();
2415 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
2416 *stream = Fits<VirtualRegister, size>::convert(value);
2417 }
2418
2419 template<typename Functor>
2420 void setLhs(VirtualRegister value, Functor func)
2421 {
2422 if (isWide32())
2423 setLhs<OpcodeSize::Wide32>(value, func);
2424 else if (isWide16())
2425 setLhs<OpcodeSize::Wide16>(value, func);
2426 else
2427 setLhs<OpcodeSize::Narrow>(value, func);
2428 }
2429
2430 template <OpcodeSize size, typename Functor>
2431 void setLhs(VirtualRegister value, Functor func)
2432 {
2433 if (!Fits<VirtualRegister, size>::check(value))
2434 value = func();
2435 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
2436 *stream = Fits<VirtualRegister, size>::convert(value);
2437 }
2438
2439 template<typename Functor>
2440 void setRhs(VirtualRegister value, Functor func)
2441 {
2442 if (isWide32())
2443 setRhs<OpcodeSize::Wide32>(value, func);
2444 else if (isWide16())
2445 setRhs<OpcodeSize::Wide16>(value, func);
2446 else
2447 setRhs<OpcodeSize::Narrow>(value, func);
2448 }
2449
2450 template <OpcodeSize size, typename Functor>
2451 void setRhs(VirtualRegister value, Functor func)
2452 {
2453 if (!Fits<VirtualRegister, size>::check(value))
2454 value = func();
2455 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
2456 *stream = Fits<VirtualRegister, size>::convert(value);
2457 }
2458
2459 template<typename Functor>
2460 void setOperandTypes(OperandTypes value, Functor func)
2461 {
2462 if (isWide32())
2463 setOperandTypes<OpcodeSize::Wide32>(value, func);
2464 else if (isWide16())
2465 setOperandTypes<OpcodeSize::Wide16>(value, func);
2466 else
2467 setOperandTypes<OpcodeSize::Narrow>(value, func);
2468 }
2469
2470 template <OpcodeSize size, typename Functor>
2471 void setOperandTypes(OperandTypes value, Functor func)
2472 {
2473 if (!Fits<OperandTypes, size>::check(value))
2474 value = func();
2475 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
2476 *stream = Fits<OperandTypes, size>::convert(value);
2477 }
2478
2479 struct Metadata {
2480 WTF_MAKE_NONCOPYABLE(Metadata);
2481
2482 public:
2483 Metadata(const OpSub& __op)
2484 : m_arithProfile(__op.m_operandTypes)
2485 { }
2486
2487 ArithProfile m_arithProfile;
2488 };
2489
2490 Metadata& metadata(CodeBlock* codeBlock) const
2491 {
2492 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
2493 }
2494
2495 Metadata& metadata(ExecState* exec) const
2496 {
2497 return metadata(exec->codeBlock());
2498 }
2499
2500 VirtualRegister m_dst;
2501 VirtualRegister m_lhs;
2502 VirtualRegister m_rhs;
2503 OperandTypes m_operandTypes;
2504 unsigned m_metadataID;
2505};
2506
2507struct OpBitand : public Instruction {
2508 static constexpr OpcodeID opcodeID = op_bitand;
2509
2510 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2511 {
2512 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
2513 }
2514
2515 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
2516 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2517 {
2518 auto __metadataID = gen->addMetadataFor(opcodeID);
2519 return emit<size, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
2520 }
2521
2522 template<OpcodeSize size>
2523 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2524 {
2525 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
2526 return checkImpl<size>(gen, dst, lhs, rhs, __metadataID);
2527 }
2528
2529 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
2530 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
2531 {
2532 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, __metadataID);
2533 if (shouldAssert == Assert)
2534 ASSERT(didEmit);
2535 return didEmit;
2536 }
2537
2538 template<OpcodeSize size>
2539 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2540 {
2541
2542 auto __metadataID = gen->addMetadataFor(opcodeID);
2543 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
2544 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
2545 return;
2546 }
2547 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
2548 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
2549 return;
2550 }
2551 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, __metadataID);
2552 }
2553
2554private:
2555 template<OpcodeSize size>
2556 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
2557 {
2558 UNUSED_PARAM(gen);
2559#if OS(WINDOWS) && ENABLE(C_LOOP)
2560 // FIXME: Disable wide16 optimization for Windows CLoop
2561 // https://bugs.webkit.org/show_bug.cgi?id=198283
2562 if (size == OpcodeSize::Wide16)
2563 return false;
2564#endif
2565 return Fits<OpcodeID, size>::check(opcodeID)
2566 && Fits<VirtualRegister, size>::check(dst)
2567 && Fits<VirtualRegister, size>::check(lhs)
2568 && Fits<VirtualRegister, size>::check(rhs)
2569 && Fits<unsigned, size>::check(__metadataID)
2570 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
2571 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
2572 }
2573
2574 template<OpcodeSize size, bool recordOpcode>
2575 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
2576 {
2577 if (size == OpcodeSize::Wide16)
2578 gen->alignWideOpcode16();
2579 else if (size == OpcodeSize::Wide32)
2580 gen->alignWideOpcode32();
2581 if (checkImpl<size>(gen, dst, lhs, rhs, __metadataID)) {
2582 if (recordOpcode)
2583 gen->recordOpcode(opcodeID);
2584 if (size == OpcodeSize::Wide16)
2585 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
2586 else if (size == OpcodeSize::Wide32)
2587 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
2588 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
2589 gen->write(Fits<VirtualRegister, size>::convert(dst));
2590 gen->write(Fits<VirtualRegister, size>::convert(lhs));
2591 gen->write(Fits<VirtualRegister, size>::convert(rhs));
2592 gen->write(Fits<unsigned, size>::convert(__metadataID));
2593 return true;
2594 }
2595 return false;
2596 }
2597
2598public:
2599 template<typename Block>
2600 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
2601 {
2602 dumper->printLocationAndOp(__location, &"**bitand"[2 - __sizeShiftAmount]);
2603 dumper->dumpOperand(m_dst, true);
2604 dumper->dumpOperand(m_lhs, false);
2605 dumper->dumpOperand(m_rhs, false);
2606 }
2607
2608 OpBitand(const uint8_t* stream)
2609 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
2610 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
2611 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
2612 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
2613 {
2614 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2615 }
2616
2617 OpBitand(const uint16_t* stream)
2618 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
2619 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
2620 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
2621 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
2622 {
2623 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2624 }
2625
2626
2627 OpBitand(const uint32_t* stream)
2628 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
2629 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
2630 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
2631 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
2632 {
2633 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2634 }
2635
2636 static OpBitand decode(const uint8_t* stream)
2637 {
2638 if (*stream == op_wide32)
2639 return { bitwise_cast<const uint32_t*>(stream + 1) };
2640 if (*stream == op_wide16)
2641 return { bitwise_cast<const uint16_t*>(stream + 1) };
2642 return { stream };
2643 }
2644
2645 template<typename Functor>
2646 void setDst(VirtualRegister value, Functor func)
2647 {
2648 if (isWide32())
2649 setDst<OpcodeSize::Wide32>(value, func);
2650 else if (isWide16())
2651 setDst<OpcodeSize::Wide16>(value, func);
2652 else
2653 setDst<OpcodeSize::Narrow>(value, func);
2654 }
2655
2656 template <OpcodeSize size, typename Functor>
2657 void setDst(VirtualRegister value, Functor func)
2658 {
2659 if (!Fits<VirtualRegister, size>::check(value))
2660 value = func();
2661 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
2662 *stream = Fits<VirtualRegister, size>::convert(value);
2663 }
2664
2665 template<typename Functor>
2666 void setLhs(VirtualRegister value, Functor func)
2667 {
2668 if (isWide32())
2669 setLhs<OpcodeSize::Wide32>(value, func);
2670 else if (isWide16())
2671 setLhs<OpcodeSize::Wide16>(value, func);
2672 else
2673 setLhs<OpcodeSize::Narrow>(value, func);
2674 }
2675
2676 template <OpcodeSize size, typename Functor>
2677 void setLhs(VirtualRegister value, Functor func)
2678 {
2679 if (!Fits<VirtualRegister, size>::check(value))
2680 value = func();
2681 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
2682 *stream = Fits<VirtualRegister, size>::convert(value);
2683 }
2684
2685 template<typename Functor>
2686 void setRhs(VirtualRegister value, Functor func)
2687 {
2688 if (isWide32())
2689 setRhs<OpcodeSize::Wide32>(value, func);
2690 else if (isWide16())
2691 setRhs<OpcodeSize::Wide16>(value, func);
2692 else
2693 setRhs<OpcodeSize::Narrow>(value, func);
2694 }
2695
2696 template <OpcodeSize size, typename Functor>
2697 void setRhs(VirtualRegister value, Functor func)
2698 {
2699 if (!Fits<VirtualRegister, size>::check(value))
2700 value = func();
2701 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
2702 *stream = Fits<VirtualRegister, size>::convert(value);
2703 }
2704
2705 struct Metadata {
2706 WTF_MAKE_NONCOPYABLE(Metadata);
2707
2708 public:
2709 Metadata(const OpBitand&) { }
2710
2711 ValueProfile m_profile;
2712 };
2713
2714 Metadata& metadata(CodeBlock* codeBlock) const
2715 {
2716 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
2717 }
2718
2719 Metadata& metadata(ExecState* exec) const
2720 {
2721 return metadata(exec->codeBlock());
2722 }
2723
2724 VirtualRegister m_dst;
2725 VirtualRegister m_lhs;
2726 VirtualRegister m_rhs;
2727 unsigned m_metadataID;
2728};
2729
2730struct OpBitor : public Instruction {
2731 static constexpr OpcodeID opcodeID = op_bitor;
2732
2733 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2734 {
2735 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
2736 }
2737
2738 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
2739 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2740 {
2741 auto __metadataID = gen->addMetadataFor(opcodeID);
2742 return emit<size, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
2743 }
2744
2745 template<OpcodeSize size>
2746 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2747 {
2748 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
2749 return checkImpl<size>(gen, dst, lhs, rhs, __metadataID);
2750 }
2751
2752 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
2753 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
2754 {
2755 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, __metadataID);
2756 if (shouldAssert == Assert)
2757 ASSERT(didEmit);
2758 return didEmit;
2759 }
2760
2761 template<OpcodeSize size>
2762 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2763 {
2764
2765 auto __metadataID = gen->addMetadataFor(opcodeID);
2766 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
2767 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
2768 return;
2769 }
2770 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
2771 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
2772 return;
2773 }
2774 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, __metadataID);
2775 }
2776
2777private:
2778 template<OpcodeSize size>
2779 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
2780 {
2781 UNUSED_PARAM(gen);
2782#if OS(WINDOWS) && ENABLE(C_LOOP)
2783 // FIXME: Disable wide16 optimization for Windows CLoop
2784 // https://bugs.webkit.org/show_bug.cgi?id=198283
2785 if (size == OpcodeSize::Wide16)
2786 return false;
2787#endif
2788 return Fits<OpcodeID, size>::check(opcodeID)
2789 && Fits<VirtualRegister, size>::check(dst)
2790 && Fits<VirtualRegister, size>::check(lhs)
2791 && Fits<VirtualRegister, size>::check(rhs)
2792 && Fits<unsigned, size>::check(__metadataID)
2793 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
2794 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
2795 }
2796
2797 template<OpcodeSize size, bool recordOpcode>
2798 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
2799 {
2800 if (size == OpcodeSize::Wide16)
2801 gen->alignWideOpcode16();
2802 else if (size == OpcodeSize::Wide32)
2803 gen->alignWideOpcode32();
2804 if (checkImpl<size>(gen, dst, lhs, rhs, __metadataID)) {
2805 if (recordOpcode)
2806 gen->recordOpcode(opcodeID);
2807 if (size == OpcodeSize::Wide16)
2808 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
2809 else if (size == OpcodeSize::Wide32)
2810 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
2811 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
2812 gen->write(Fits<VirtualRegister, size>::convert(dst));
2813 gen->write(Fits<VirtualRegister, size>::convert(lhs));
2814 gen->write(Fits<VirtualRegister, size>::convert(rhs));
2815 gen->write(Fits<unsigned, size>::convert(__metadataID));
2816 return true;
2817 }
2818 return false;
2819 }
2820
2821public:
2822 template<typename Block>
2823 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
2824 {
2825 dumper->printLocationAndOp(__location, &"**bitor"[2 - __sizeShiftAmount]);
2826 dumper->dumpOperand(m_dst, true);
2827 dumper->dumpOperand(m_lhs, false);
2828 dumper->dumpOperand(m_rhs, false);
2829 }
2830
2831 OpBitor(const uint8_t* stream)
2832 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
2833 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
2834 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
2835 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
2836 {
2837 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2838 }
2839
2840 OpBitor(const uint16_t* stream)
2841 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
2842 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
2843 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
2844 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
2845 {
2846 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2847 }
2848
2849
2850 OpBitor(const uint32_t* stream)
2851 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
2852 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
2853 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
2854 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
2855 {
2856 ASSERT_UNUSED(stream, stream[0] == opcodeID);
2857 }
2858
2859 static OpBitor decode(const uint8_t* stream)
2860 {
2861 if (*stream == op_wide32)
2862 return { bitwise_cast<const uint32_t*>(stream + 1) };
2863 if (*stream == op_wide16)
2864 return { bitwise_cast<const uint16_t*>(stream + 1) };
2865 return { stream };
2866 }
2867
2868 template<typename Functor>
2869 void setDst(VirtualRegister value, Functor func)
2870 {
2871 if (isWide32())
2872 setDst<OpcodeSize::Wide32>(value, func);
2873 else if (isWide16())
2874 setDst<OpcodeSize::Wide16>(value, func);
2875 else
2876 setDst<OpcodeSize::Narrow>(value, func);
2877 }
2878
2879 template <OpcodeSize size, typename Functor>
2880 void setDst(VirtualRegister value, Functor func)
2881 {
2882 if (!Fits<VirtualRegister, size>::check(value))
2883 value = func();
2884 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
2885 *stream = Fits<VirtualRegister, size>::convert(value);
2886 }
2887
2888 template<typename Functor>
2889 void setLhs(VirtualRegister value, Functor func)
2890 {
2891 if (isWide32())
2892 setLhs<OpcodeSize::Wide32>(value, func);
2893 else if (isWide16())
2894 setLhs<OpcodeSize::Wide16>(value, func);
2895 else
2896 setLhs<OpcodeSize::Narrow>(value, func);
2897 }
2898
2899 template <OpcodeSize size, typename Functor>
2900 void setLhs(VirtualRegister value, Functor func)
2901 {
2902 if (!Fits<VirtualRegister, size>::check(value))
2903 value = func();
2904 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
2905 *stream = Fits<VirtualRegister, size>::convert(value);
2906 }
2907
2908 template<typename Functor>
2909 void setRhs(VirtualRegister value, Functor func)
2910 {
2911 if (isWide32())
2912 setRhs<OpcodeSize::Wide32>(value, func);
2913 else if (isWide16())
2914 setRhs<OpcodeSize::Wide16>(value, func);
2915 else
2916 setRhs<OpcodeSize::Narrow>(value, func);
2917 }
2918
2919 template <OpcodeSize size, typename Functor>
2920 void setRhs(VirtualRegister value, Functor func)
2921 {
2922 if (!Fits<VirtualRegister, size>::check(value))
2923 value = func();
2924 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
2925 *stream = Fits<VirtualRegister, size>::convert(value);
2926 }
2927
2928 struct Metadata {
2929 WTF_MAKE_NONCOPYABLE(Metadata);
2930
2931 public:
2932 Metadata(const OpBitor&) { }
2933
2934 ValueProfile m_profile;
2935 };
2936
2937 Metadata& metadata(CodeBlock* codeBlock) const
2938 {
2939 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
2940 }
2941
2942 Metadata& metadata(ExecState* exec) const
2943 {
2944 return metadata(exec->codeBlock());
2945 }
2946
2947 VirtualRegister m_dst;
2948 VirtualRegister m_lhs;
2949 VirtualRegister m_rhs;
2950 unsigned m_metadataID;
2951};
2952
2953struct OpBitxor : public Instruction {
2954 static constexpr OpcodeID opcodeID = op_bitxor;
2955
2956 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2957 {
2958 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
2959 }
2960
2961 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
2962 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2963 {
2964 auto __metadataID = gen->addMetadataFor(opcodeID);
2965 return emit<size, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
2966 }
2967
2968 template<OpcodeSize size>
2969 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2970 {
2971 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
2972 return checkImpl<size>(gen, dst, lhs, rhs, __metadataID);
2973 }
2974
2975 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
2976 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
2977 {
2978 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs, __metadataID);
2979 if (shouldAssert == Assert)
2980 ASSERT(didEmit);
2981 return didEmit;
2982 }
2983
2984 template<OpcodeSize size>
2985 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
2986 {
2987
2988 auto __metadataID = gen->addMetadataFor(opcodeID);
2989 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
2990 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
2991 return;
2992 }
2993 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
2994 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
2995 return;
2996 }
2997 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, __metadataID);
2998 }
2999
3000private:
3001 template<OpcodeSize size>
3002 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
3003 {
3004 UNUSED_PARAM(gen);
3005#if OS(WINDOWS) && ENABLE(C_LOOP)
3006 // FIXME: Disable wide16 optimization for Windows CLoop
3007 // https://bugs.webkit.org/show_bug.cgi?id=198283
3008 if (size == OpcodeSize::Wide16)
3009 return false;
3010#endif
3011 return Fits<OpcodeID, size>::check(opcodeID)
3012 && Fits<VirtualRegister, size>::check(dst)
3013 && Fits<VirtualRegister, size>::check(lhs)
3014 && Fits<VirtualRegister, size>::check(rhs)
3015 && Fits<unsigned, size>::check(__metadataID)
3016 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
3017 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
3018 }
3019
3020 template<OpcodeSize size, bool recordOpcode>
3021 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
3022 {
3023 if (size == OpcodeSize::Wide16)
3024 gen->alignWideOpcode16();
3025 else if (size == OpcodeSize::Wide32)
3026 gen->alignWideOpcode32();
3027 if (checkImpl<size>(gen, dst, lhs, rhs, __metadataID)) {
3028 if (recordOpcode)
3029 gen->recordOpcode(opcodeID);
3030 if (size == OpcodeSize::Wide16)
3031 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
3032 else if (size == OpcodeSize::Wide32)
3033 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
3034 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
3035 gen->write(Fits<VirtualRegister, size>::convert(dst));
3036 gen->write(Fits<VirtualRegister, size>::convert(lhs));
3037 gen->write(Fits<VirtualRegister, size>::convert(rhs));
3038 gen->write(Fits<unsigned, size>::convert(__metadataID));
3039 return true;
3040 }
3041 return false;
3042 }
3043
3044public:
3045 template<typename Block>
3046 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
3047 {
3048 dumper->printLocationAndOp(__location, &"**bitxor"[2 - __sizeShiftAmount]);
3049 dumper->dumpOperand(m_dst, true);
3050 dumper->dumpOperand(m_lhs, false);
3051 dumper->dumpOperand(m_rhs, false);
3052 }
3053
3054 OpBitxor(const uint8_t* stream)
3055 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
3056 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
3057 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
3058 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
3059 {
3060 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3061 }
3062
3063 OpBitxor(const uint16_t* stream)
3064 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
3065 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
3066 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
3067 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
3068 {
3069 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3070 }
3071
3072
3073 OpBitxor(const uint32_t* stream)
3074 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
3075 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
3076 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
3077 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
3078 {
3079 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3080 }
3081
3082 static OpBitxor decode(const uint8_t* stream)
3083 {
3084 if (*stream == op_wide32)
3085 return { bitwise_cast<const uint32_t*>(stream + 1) };
3086 if (*stream == op_wide16)
3087 return { bitwise_cast<const uint16_t*>(stream + 1) };
3088 return { stream };
3089 }
3090
3091 template<typename Functor>
3092 void setDst(VirtualRegister value, Functor func)
3093 {
3094 if (isWide32())
3095 setDst<OpcodeSize::Wide32>(value, func);
3096 else if (isWide16())
3097 setDst<OpcodeSize::Wide16>(value, func);
3098 else
3099 setDst<OpcodeSize::Narrow>(value, func);
3100 }
3101
3102 template <OpcodeSize size, typename Functor>
3103 void setDst(VirtualRegister value, Functor func)
3104 {
3105 if (!Fits<VirtualRegister, size>::check(value))
3106 value = func();
3107 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
3108 *stream = Fits<VirtualRegister, size>::convert(value);
3109 }
3110
3111 template<typename Functor>
3112 void setLhs(VirtualRegister value, Functor func)
3113 {
3114 if (isWide32())
3115 setLhs<OpcodeSize::Wide32>(value, func);
3116 else if (isWide16())
3117 setLhs<OpcodeSize::Wide16>(value, func);
3118 else
3119 setLhs<OpcodeSize::Narrow>(value, func);
3120 }
3121
3122 template <OpcodeSize size, typename Functor>
3123 void setLhs(VirtualRegister value, Functor func)
3124 {
3125 if (!Fits<VirtualRegister, size>::check(value))
3126 value = func();
3127 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
3128 *stream = Fits<VirtualRegister, size>::convert(value);
3129 }
3130
3131 template<typename Functor>
3132 void setRhs(VirtualRegister value, Functor func)
3133 {
3134 if (isWide32())
3135 setRhs<OpcodeSize::Wide32>(value, func);
3136 else if (isWide16())
3137 setRhs<OpcodeSize::Wide16>(value, func);
3138 else
3139 setRhs<OpcodeSize::Narrow>(value, func);
3140 }
3141
3142 template <OpcodeSize size, typename Functor>
3143 void setRhs(VirtualRegister value, Functor func)
3144 {
3145 if (!Fits<VirtualRegister, size>::check(value))
3146 value = func();
3147 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
3148 *stream = Fits<VirtualRegister, size>::convert(value);
3149 }
3150
3151 struct Metadata {
3152 WTF_MAKE_NONCOPYABLE(Metadata);
3153
3154 public:
3155 Metadata(const OpBitxor&) { }
3156
3157 ValueProfile m_profile;
3158 };
3159
3160 Metadata& metadata(CodeBlock* codeBlock) const
3161 {
3162 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
3163 }
3164
3165 Metadata& metadata(ExecState* exec) const
3166 {
3167 return metadata(exec->codeBlock());
3168 }
3169
3170 VirtualRegister m_dst;
3171 VirtualRegister m_lhs;
3172 VirtualRegister m_rhs;
3173 unsigned m_metadataID;
3174};
3175
3176struct OpBitnot : public Instruction {
3177 static constexpr OpcodeID opcodeID = op_bitnot;
3178
3179 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3180 {
3181 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
3182 }
3183
3184 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
3185 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3186 {
3187 auto __metadataID = gen->addMetadataFor(opcodeID);
3188 return emit<size, shouldAssert>(gen, dst, operand, __metadataID);
3189 }
3190
3191 template<OpcodeSize size>
3192 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3193 {
3194 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
3195 return checkImpl<size>(gen, dst, operand, __metadataID);
3196 }
3197
3198 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
3199 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
3200 {
3201 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, __metadataID);
3202 if (shouldAssert == Assert)
3203 ASSERT(didEmit);
3204 return didEmit;
3205 }
3206
3207 template<OpcodeSize size>
3208 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3209 {
3210
3211 auto __metadataID = gen->addMetadataFor(opcodeID);
3212 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
3213 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, __metadataID))
3214 return;
3215 }
3216 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
3217 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, __metadataID))
3218 return;
3219 }
3220 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, __metadataID);
3221 }
3222
3223private:
3224 template<OpcodeSize size>
3225 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, unsigned __metadataID)
3226 {
3227 UNUSED_PARAM(gen);
3228#if OS(WINDOWS) && ENABLE(C_LOOP)
3229 // FIXME: Disable wide16 optimization for Windows CLoop
3230 // https://bugs.webkit.org/show_bug.cgi?id=198283
3231 if (size == OpcodeSize::Wide16)
3232 return false;
3233#endif
3234 return Fits<OpcodeID, size>::check(opcodeID)
3235 && Fits<VirtualRegister, size>::check(dst)
3236 && Fits<VirtualRegister, size>::check(operand)
3237 && Fits<unsigned, size>::check(__metadataID)
3238 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
3239 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
3240 }
3241
3242 template<OpcodeSize size, bool recordOpcode>
3243 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
3244 {
3245 if (size == OpcodeSize::Wide16)
3246 gen->alignWideOpcode16();
3247 else if (size == OpcodeSize::Wide32)
3248 gen->alignWideOpcode32();
3249 if (checkImpl<size>(gen, dst, operand, __metadataID)) {
3250 if (recordOpcode)
3251 gen->recordOpcode(opcodeID);
3252 if (size == OpcodeSize::Wide16)
3253 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
3254 else if (size == OpcodeSize::Wide32)
3255 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
3256 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
3257 gen->write(Fits<VirtualRegister, size>::convert(dst));
3258 gen->write(Fits<VirtualRegister, size>::convert(operand));
3259 gen->write(Fits<unsigned, size>::convert(__metadataID));
3260 return true;
3261 }
3262 return false;
3263 }
3264
3265public:
3266 template<typename Block>
3267 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
3268 {
3269 dumper->printLocationAndOp(__location, &"**bitnot"[2 - __sizeShiftAmount]);
3270 dumper->dumpOperand(m_dst, true);
3271 dumper->dumpOperand(m_operand, false);
3272 }
3273
3274 OpBitnot(const uint8_t* stream)
3275 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
3276 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
3277 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
3278 {
3279 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3280 }
3281
3282 OpBitnot(const uint16_t* stream)
3283 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
3284 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
3285 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
3286 {
3287 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3288 }
3289
3290
3291 OpBitnot(const uint32_t* stream)
3292 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
3293 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
3294 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
3295 {
3296 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3297 }
3298
3299 static OpBitnot decode(const uint8_t* stream)
3300 {
3301 if (*stream == op_wide32)
3302 return { bitwise_cast<const uint32_t*>(stream + 1) };
3303 if (*stream == op_wide16)
3304 return { bitwise_cast<const uint16_t*>(stream + 1) };
3305 return { stream };
3306 }
3307
3308 template<typename Functor>
3309 void setDst(VirtualRegister value, Functor func)
3310 {
3311 if (isWide32())
3312 setDst<OpcodeSize::Wide32>(value, func);
3313 else if (isWide16())
3314 setDst<OpcodeSize::Wide16>(value, func);
3315 else
3316 setDst<OpcodeSize::Narrow>(value, func);
3317 }
3318
3319 template <OpcodeSize size, typename Functor>
3320 void setDst(VirtualRegister value, Functor func)
3321 {
3322 if (!Fits<VirtualRegister, size>::check(value))
3323 value = func();
3324 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
3325 *stream = Fits<VirtualRegister, size>::convert(value);
3326 }
3327
3328 template<typename Functor>
3329 void setOperand(VirtualRegister value, Functor func)
3330 {
3331 if (isWide32())
3332 setOperand<OpcodeSize::Wide32>(value, func);
3333 else if (isWide16())
3334 setOperand<OpcodeSize::Wide16>(value, func);
3335 else
3336 setOperand<OpcodeSize::Narrow>(value, func);
3337 }
3338
3339 template <OpcodeSize size, typename Functor>
3340 void setOperand(VirtualRegister value, Functor func)
3341 {
3342 if (!Fits<VirtualRegister, size>::check(value))
3343 value = func();
3344 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
3345 *stream = Fits<VirtualRegister, size>::convert(value);
3346 }
3347
3348 struct Metadata {
3349 WTF_MAKE_NONCOPYABLE(Metadata);
3350
3351 public:
3352 Metadata(const OpBitnot&) { }
3353
3354 ValueProfile m_profile;
3355 };
3356
3357 Metadata& metadata(CodeBlock* codeBlock) const
3358 {
3359 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
3360 }
3361
3362 Metadata& metadata(ExecState* exec) const
3363 {
3364 return metadata(exec->codeBlock());
3365 }
3366
3367 VirtualRegister m_dst;
3368 VirtualRegister m_operand;
3369 unsigned m_metadataID;
3370};
3371
3372struct OpToObject : public Instruction {
3373 static constexpr OpcodeID opcodeID = op_to_object;
3374
3375 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
3376 {
3377 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand, message);
3378 }
3379
3380 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
3381 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
3382 {
3383 auto __metadataID = gen->addMetadataFor(opcodeID);
3384 return emit<size, shouldAssert>(gen, dst, operand, message, __metadataID);
3385 }
3386
3387 template<OpcodeSize size>
3388 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
3389 {
3390 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
3391 return checkImpl<size>(gen, dst, operand, message, __metadataID);
3392 }
3393
3394 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
3395 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message, unsigned __metadataID)
3396 {
3397 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, message, __metadataID);
3398 if (shouldAssert == Assert)
3399 ASSERT(didEmit);
3400 return didEmit;
3401 }
3402
3403 template<OpcodeSize size>
3404 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
3405 {
3406
3407 auto __metadataID = gen->addMetadataFor(opcodeID);
3408 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
3409 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, message, __metadataID))
3410 return;
3411 }
3412 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
3413 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, message, __metadataID))
3414 return;
3415 }
3416 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, message, __metadataID);
3417 }
3418
3419private:
3420 template<OpcodeSize size>
3421 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, unsigned& message, unsigned __metadataID)
3422 {
3423 UNUSED_PARAM(gen);
3424#if OS(WINDOWS) && ENABLE(C_LOOP)
3425 // FIXME: Disable wide16 optimization for Windows CLoop
3426 // https://bugs.webkit.org/show_bug.cgi?id=198283
3427 if (size == OpcodeSize::Wide16)
3428 return false;
3429#endif
3430 return Fits<OpcodeID, size>::check(opcodeID)
3431 && Fits<VirtualRegister, size>::check(dst)
3432 && Fits<VirtualRegister, size>::check(operand)
3433 && Fits<unsigned, size>::check(message)
3434 && Fits<unsigned, size>::check(__metadataID)
3435 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
3436 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
3437 }
3438
3439 template<OpcodeSize size, bool recordOpcode>
3440 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message, unsigned __metadataID)
3441 {
3442 if (size == OpcodeSize::Wide16)
3443 gen->alignWideOpcode16();
3444 else if (size == OpcodeSize::Wide32)
3445 gen->alignWideOpcode32();
3446 if (checkImpl<size>(gen, dst, operand, message, __metadataID)) {
3447 if (recordOpcode)
3448 gen->recordOpcode(opcodeID);
3449 if (size == OpcodeSize::Wide16)
3450 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
3451 else if (size == OpcodeSize::Wide32)
3452 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
3453 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
3454 gen->write(Fits<VirtualRegister, size>::convert(dst));
3455 gen->write(Fits<VirtualRegister, size>::convert(operand));
3456 gen->write(Fits<unsigned, size>::convert(message));
3457 gen->write(Fits<unsigned, size>::convert(__metadataID));
3458 return true;
3459 }
3460 return false;
3461 }
3462
3463public:
3464 template<typename Block>
3465 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
3466 {
3467 dumper->printLocationAndOp(__location, &"**to_object"[2 - __sizeShiftAmount]);
3468 dumper->dumpOperand(m_dst, true);
3469 dumper->dumpOperand(m_operand, false);
3470 dumper->dumpOperand(m_message, false);
3471 }
3472
3473 OpToObject(const uint8_t* stream)
3474 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
3475 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
3476 , m_message(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
3477 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
3478 {
3479 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3480 }
3481
3482 OpToObject(const uint16_t* stream)
3483 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
3484 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
3485 , m_message(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
3486 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
3487 {
3488 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3489 }
3490
3491
3492 OpToObject(const uint32_t* stream)
3493 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
3494 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
3495 , m_message(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
3496 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
3497 {
3498 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3499 }
3500
3501 static OpToObject decode(const uint8_t* stream)
3502 {
3503 if (*stream == op_wide32)
3504 return { bitwise_cast<const uint32_t*>(stream + 1) };
3505 if (*stream == op_wide16)
3506 return { bitwise_cast<const uint16_t*>(stream + 1) };
3507 return { stream };
3508 }
3509
3510 template<typename Functor>
3511 void setDst(VirtualRegister value, Functor func)
3512 {
3513 if (isWide32())
3514 setDst<OpcodeSize::Wide32>(value, func);
3515 else if (isWide16())
3516 setDst<OpcodeSize::Wide16>(value, func);
3517 else
3518 setDst<OpcodeSize::Narrow>(value, func);
3519 }
3520
3521 template <OpcodeSize size, typename Functor>
3522 void setDst(VirtualRegister value, Functor func)
3523 {
3524 if (!Fits<VirtualRegister, size>::check(value))
3525 value = func();
3526 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
3527 *stream = Fits<VirtualRegister, size>::convert(value);
3528 }
3529
3530 template<typename Functor>
3531 void setOperand(VirtualRegister value, Functor func)
3532 {
3533 if (isWide32())
3534 setOperand<OpcodeSize::Wide32>(value, func);
3535 else if (isWide16())
3536 setOperand<OpcodeSize::Wide16>(value, func);
3537 else
3538 setOperand<OpcodeSize::Narrow>(value, func);
3539 }
3540
3541 template <OpcodeSize size, typename Functor>
3542 void setOperand(VirtualRegister value, Functor func)
3543 {
3544 if (!Fits<VirtualRegister, size>::check(value))
3545 value = func();
3546 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
3547 *stream = Fits<VirtualRegister, size>::convert(value);
3548 }
3549
3550 template<typename Functor>
3551 void setMessage(unsigned value, Functor func)
3552 {
3553 if (isWide32())
3554 setMessage<OpcodeSize::Wide32>(value, func);
3555 else if (isWide16())
3556 setMessage<OpcodeSize::Wide16>(value, func);
3557 else
3558 setMessage<OpcodeSize::Narrow>(value, func);
3559 }
3560
3561 template <OpcodeSize size, typename Functor>
3562 void setMessage(unsigned value, Functor func)
3563 {
3564 if (!Fits<unsigned, size>::check(value))
3565 value = func();
3566 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
3567 *stream = Fits<unsigned, size>::convert(value);
3568 }
3569
3570 struct Metadata {
3571 WTF_MAKE_NONCOPYABLE(Metadata);
3572
3573 public:
3574 Metadata(const OpToObject&) { }
3575
3576 ValueProfile m_profile;
3577 };
3578
3579 Metadata& metadata(CodeBlock* codeBlock) const
3580 {
3581 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
3582 }
3583
3584 Metadata& metadata(ExecState* exec) const
3585 {
3586 return metadata(exec->codeBlock());
3587 }
3588
3589 VirtualRegister m_dst;
3590 VirtualRegister m_operand;
3591 unsigned m_message;
3592 unsigned m_metadataID;
3593};
3594
3595struct OpToNumber : public Instruction {
3596 static constexpr OpcodeID opcodeID = op_to_number;
3597
3598 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3599 {
3600 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
3601 }
3602
3603 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
3604 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3605 {
3606 auto __metadataID = gen->addMetadataFor(opcodeID);
3607 return emit<size, shouldAssert>(gen, dst, operand, __metadataID);
3608 }
3609
3610 template<OpcodeSize size>
3611 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3612 {
3613 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
3614 return checkImpl<size>(gen, dst, operand, __metadataID);
3615 }
3616
3617 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
3618 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
3619 {
3620 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, __metadataID);
3621 if (shouldAssert == Assert)
3622 ASSERT(didEmit);
3623 return didEmit;
3624 }
3625
3626 template<OpcodeSize size>
3627 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
3628 {
3629
3630 auto __metadataID = gen->addMetadataFor(opcodeID);
3631 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
3632 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, __metadataID))
3633 return;
3634 }
3635 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
3636 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, __metadataID))
3637 return;
3638 }
3639 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, __metadataID);
3640 }
3641
3642private:
3643 template<OpcodeSize size>
3644 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, unsigned __metadataID)
3645 {
3646 UNUSED_PARAM(gen);
3647#if OS(WINDOWS) && ENABLE(C_LOOP)
3648 // FIXME: Disable wide16 optimization for Windows CLoop
3649 // https://bugs.webkit.org/show_bug.cgi?id=198283
3650 if (size == OpcodeSize::Wide16)
3651 return false;
3652#endif
3653 return Fits<OpcodeID, size>::check(opcodeID)
3654 && Fits<VirtualRegister, size>::check(dst)
3655 && Fits<VirtualRegister, size>::check(operand)
3656 && Fits<unsigned, size>::check(__metadataID)
3657 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
3658 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
3659 }
3660
3661 template<OpcodeSize size, bool recordOpcode>
3662 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
3663 {
3664 if (size == OpcodeSize::Wide16)
3665 gen->alignWideOpcode16();
3666 else if (size == OpcodeSize::Wide32)
3667 gen->alignWideOpcode32();
3668 if (checkImpl<size>(gen, dst, operand, __metadataID)) {
3669 if (recordOpcode)
3670 gen->recordOpcode(opcodeID);
3671 if (size == OpcodeSize::Wide16)
3672 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
3673 else if (size == OpcodeSize::Wide32)
3674 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
3675 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
3676 gen->write(Fits<VirtualRegister, size>::convert(dst));
3677 gen->write(Fits<VirtualRegister, size>::convert(operand));
3678 gen->write(Fits<unsigned, size>::convert(__metadataID));
3679 return true;
3680 }
3681 return false;
3682 }
3683
3684public:
3685 template<typename Block>
3686 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
3687 {
3688 dumper->printLocationAndOp(__location, &"**to_number"[2 - __sizeShiftAmount]);
3689 dumper->dumpOperand(m_dst, true);
3690 dumper->dumpOperand(m_operand, false);
3691 }
3692
3693 OpToNumber(const uint8_t* stream)
3694 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
3695 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
3696 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
3697 {
3698 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3699 }
3700
3701 OpToNumber(const uint16_t* stream)
3702 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
3703 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
3704 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
3705 {
3706 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3707 }
3708
3709
3710 OpToNumber(const uint32_t* stream)
3711 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
3712 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
3713 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
3714 {
3715 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3716 }
3717
3718 static OpToNumber decode(const uint8_t* stream)
3719 {
3720 if (*stream == op_wide32)
3721 return { bitwise_cast<const uint32_t*>(stream + 1) };
3722 if (*stream == op_wide16)
3723 return { bitwise_cast<const uint16_t*>(stream + 1) };
3724 return { stream };
3725 }
3726
3727 template<typename Functor>
3728 void setDst(VirtualRegister value, Functor func)
3729 {
3730 if (isWide32())
3731 setDst<OpcodeSize::Wide32>(value, func);
3732 else if (isWide16())
3733 setDst<OpcodeSize::Wide16>(value, func);
3734 else
3735 setDst<OpcodeSize::Narrow>(value, func);
3736 }
3737
3738 template <OpcodeSize size, typename Functor>
3739 void setDst(VirtualRegister value, Functor func)
3740 {
3741 if (!Fits<VirtualRegister, size>::check(value))
3742 value = func();
3743 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
3744 *stream = Fits<VirtualRegister, size>::convert(value);
3745 }
3746
3747 template<typename Functor>
3748 void setOperand(VirtualRegister value, Functor func)
3749 {
3750 if (isWide32())
3751 setOperand<OpcodeSize::Wide32>(value, func);
3752 else if (isWide16())
3753 setOperand<OpcodeSize::Wide16>(value, func);
3754 else
3755 setOperand<OpcodeSize::Narrow>(value, func);
3756 }
3757
3758 template <OpcodeSize size, typename Functor>
3759 void setOperand(VirtualRegister value, Functor func)
3760 {
3761 if (!Fits<VirtualRegister, size>::check(value))
3762 value = func();
3763 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
3764 *stream = Fits<VirtualRegister, size>::convert(value);
3765 }
3766
3767 struct Metadata {
3768 WTF_MAKE_NONCOPYABLE(Metadata);
3769
3770 public:
3771 Metadata(const OpToNumber&) { }
3772
3773 ValueProfile m_profile;
3774 };
3775
3776 Metadata& metadata(CodeBlock* codeBlock) const
3777 {
3778 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
3779 }
3780
3781 Metadata& metadata(ExecState* exec) const
3782 {
3783 return metadata(exec->codeBlock());
3784 }
3785
3786 VirtualRegister m_dst;
3787 VirtualRegister m_operand;
3788 unsigned m_metadataID;
3789};
3790
3791struct OpNegate : public Instruction {
3792 static constexpr OpcodeID opcodeID = op_negate;
3793
3794 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes)
3795 {
3796 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand, operandTypes);
3797 }
3798
3799 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
3800 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes)
3801 {
3802 auto __metadataID = gen->addMetadataFor(opcodeID);
3803 return emit<size, shouldAssert>(gen, dst, operand, operandTypes, __metadataID);
3804 }
3805
3806 template<OpcodeSize size>
3807 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes)
3808 {
3809 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
3810 return checkImpl<size>(gen, dst, operand, operandTypes, __metadataID);
3811 }
3812
3813 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
3814 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes, unsigned __metadataID)
3815 {
3816 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, operandTypes, __metadataID);
3817 if (shouldAssert == Assert)
3818 ASSERT(didEmit);
3819 return didEmit;
3820 }
3821
3822 template<OpcodeSize size>
3823 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes)
3824 {
3825
3826 auto __metadataID = gen->addMetadataFor(opcodeID);
3827 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
3828 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, operandTypes, __metadataID))
3829 return;
3830 }
3831 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
3832 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, operandTypes, __metadataID))
3833 return;
3834 }
3835 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, operandTypes, __metadataID);
3836 }
3837
3838private:
3839 template<OpcodeSize size>
3840 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, OperandTypes& operandTypes, unsigned __metadataID)
3841 {
3842 UNUSED_PARAM(gen);
3843#if OS(WINDOWS) && ENABLE(C_LOOP)
3844 // FIXME: Disable wide16 optimization for Windows CLoop
3845 // https://bugs.webkit.org/show_bug.cgi?id=198283
3846 if (size == OpcodeSize::Wide16)
3847 return false;
3848#endif
3849 return Fits<OpcodeID, size>::check(opcodeID)
3850 && Fits<VirtualRegister, size>::check(dst)
3851 && Fits<VirtualRegister, size>::check(operand)
3852 && Fits<OperandTypes, size>::check(operandTypes)
3853 && Fits<unsigned, size>::check(__metadataID)
3854 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
3855 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
3856 }
3857
3858 template<OpcodeSize size, bool recordOpcode>
3859 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes, unsigned __metadataID)
3860 {
3861 if (size == OpcodeSize::Wide16)
3862 gen->alignWideOpcode16();
3863 else if (size == OpcodeSize::Wide32)
3864 gen->alignWideOpcode32();
3865 if (checkImpl<size>(gen, dst, operand, operandTypes, __metadataID)) {
3866 if (recordOpcode)
3867 gen->recordOpcode(opcodeID);
3868 if (size == OpcodeSize::Wide16)
3869 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
3870 else if (size == OpcodeSize::Wide32)
3871 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
3872 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
3873 gen->write(Fits<VirtualRegister, size>::convert(dst));
3874 gen->write(Fits<VirtualRegister, size>::convert(operand));
3875 gen->write(Fits<OperandTypes, size>::convert(operandTypes));
3876 gen->write(Fits<unsigned, size>::convert(__metadataID));
3877 return true;
3878 }
3879 return false;
3880 }
3881
3882public:
3883 template<typename Block>
3884 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
3885 {
3886 dumper->printLocationAndOp(__location, &"**negate"[2 - __sizeShiftAmount]);
3887 dumper->dumpOperand(m_dst, true);
3888 dumper->dumpOperand(m_operand, false);
3889 dumper->dumpOperand(m_operandTypes, false);
3890 }
3891
3892 OpNegate(const uint8_t* stream)
3893 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
3894 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
3895 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[3]))
3896 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
3897 {
3898 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3899 }
3900
3901 OpNegate(const uint16_t* stream)
3902 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
3903 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
3904 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[3]))
3905 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
3906 {
3907 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3908 }
3909
3910
3911 OpNegate(const uint32_t* stream)
3912 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
3913 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
3914 , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[3]))
3915 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
3916 {
3917 ASSERT_UNUSED(stream, stream[0] == opcodeID);
3918 }
3919
3920 static OpNegate decode(const uint8_t* stream)
3921 {
3922 if (*stream == op_wide32)
3923 return { bitwise_cast<const uint32_t*>(stream + 1) };
3924 if (*stream == op_wide16)
3925 return { bitwise_cast<const uint16_t*>(stream + 1) };
3926 return { stream };
3927 }
3928
3929 template<typename Functor>
3930 void setDst(VirtualRegister value, Functor func)
3931 {
3932 if (isWide32())
3933 setDst<OpcodeSize::Wide32>(value, func);
3934 else if (isWide16())
3935 setDst<OpcodeSize::Wide16>(value, func);
3936 else
3937 setDst<OpcodeSize::Narrow>(value, func);
3938 }
3939
3940 template <OpcodeSize size, typename Functor>
3941 void setDst(VirtualRegister value, Functor func)
3942 {
3943 if (!Fits<VirtualRegister, size>::check(value))
3944 value = func();
3945 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
3946 *stream = Fits<VirtualRegister, size>::convert(value);
3947 }
3948
3949 template<typename Functor>
3950 void setOperand(VirtualRegister value, Functor func)
3951 {
3952 if (isWide32())
3953 setOperand<OpcodeSize::Wide32>(value, func);
3954 else if (isWide16())
3955 setOperand<OpcodeSize::Wide16>(value, func);
3956 else
3957 setOperand<OpcodeSize::Narrow>(value, func);
3958 }
3959
3960 template <OpcodeSize size, typename Functor>
3961 void setOperand(VirtualRegister value, Functor func)
3962 {
3963 if (!Fits<VirtualRegister, size>::check(value))
3964 value = func();
3965 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
3966 *stream = Fits<VirtualRegister, size>::convert(value);
3967 }
3968
3969 template<typename Functor>
3970 void setOperandTypes(OperandTypes value, Functor func)
3971 {
3972 if (isWide32())
3973 setOperandTypes<OpcodeSize::Wide32>(value, func);
3974 else if (isWide16())
3975 setOperandTypes<OpcodeSize::Wide16>(value, func);
3976 else
3977 setOperandTypes<OpcodeSize::Narrow>(value, func);
3978 }
3979
3980 template <OpcodeSize size, typename Functor>
3981 void setOperandTypes(OperandTypes value, Functor func)
3982 {
3983 if (!Fits<OperandTypes, size>::check(value))
3984 value = func();
3985 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
3986 *stream = Fits<OperandTypes, size>::convert(value);
3987 }
3988
3989 struct Metadata {
3990 WTF_MAKE_NONCOPYABLE(Metadata);
3991
3992 public:
3993 Metadata(const OpNegate& __op)
3994 : m_arithProfile(__op.m_operandTypes)
3995 { }
3996
3997 ArithProfile m_arithProfile;
3998 };
3999
4000 Metadata& metadata(CodeBlock* codeBlock) const
4001 {
4002 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
4003 }
4004
4005 Metadata& metadata(ExecState* exec) const
4006 {
4007 return metadata(exec->codeBlock());
4008 }
4009
4010 VirtualRegister m_dst;
4011 VirtualRegister m_operand;
4012 OperandTypes m_operandTypes;
4013 unsigned m_metadataID;
4014};
4015
4016struct OpInByVal : public Instruction {
4017 static constexpr OpcodeID opcodeID = op_in_by_val;
4018
4019 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
4020 {
4021 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
4022 }
4023
4024 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
4025 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
4026 {
4027 auto __metadataID = gen->addMetadataFor(opcodeID);
4028 return emit<size, shouldAssert>(gen, dst, base, property, __metadataID);
4029 }
4030
4031 template<OpcodeSize size>
4032 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
4033 {
4034 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
4035 return checkImpl<size>(gen, dst, base, property, __metadataID);
4036 }
4037
4038 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
4039 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
4040 {
4041 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID);
4042 if (shouldAssert == Assert)
4043 ASSERT(didEmit);
4044 return didEmit;
4045 }
4046
4047 template<OpcodeSize size>
4048 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
4049 {
4050
4051 auto __metadataID = gen->addMetadataFor(opcodeID);
4052 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
4053 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID))
4054 return;
4055 }
4056 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
4057 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
4058 return;
4059 }
4060 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
4061 }
4062
4063private:
4064 template<OpcodeSize size>
4065 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, unsigned __metadataID)
4066 {
4067 UNUSED_PARAM(gen);
4068#if OS(WINDOWS) && ENABLE(C_LOOP)
4069 // FIXME: Disable wide16 optimization for Windows CLoop
4070 // https://bugs.webkit.org/show_bug.cgi?id=198283
4071 if (size == OpcodeSize::Wide16)
4072 return false;
4073#endif
4074 return Fits<OpcodeID, size>::check(opcodeID)
4075 && Fits<VirtualRegister, size>::check(dst)
4076 && Fits<VirtualRegister, size>::check(base)
4077 && Fits<VirtualRegister, size>::check(property)
4078 && Fits<unsigned, size>::check(__metadataID)
4079 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
4080 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
4081 }
4082
4083 template<OpcodeSize size, bool recordOpcode>
4084 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
4085 {
4086 if (size == OpcodeSize::Wide16)
4087 gen->alignWideOpcode16();
4088 else if (size == OpcodeSize::Wide32)
4089 gen->alignWideOpcode32();
4090 if (checkImpl<size>(gen, dst, base, property, __metadataID)) {
4091 if (recordOpcode)
4092 gen->recordOpcode(opcodeID);
4093 if (size == OpcodeSize::Wide16)
4094 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
4095 else if (size == OpcodeSize::Wide32)
4096 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
4097 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
4098 gen->write(Fits<VirtualRegister, size>::convert(dst));
4099 gen->write(Fits<VirtualRegister, size>::convert(base));
4100 gen->write(Fits<VirtualRegister, size>::convert(property));
4101 gen->write(Fits<unsigned, size>::convert(__metadataID));
4102 return true;
4103 }
4104 return false;
4105 }
4106
4107public:
4108 template<typename Block>
4109 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
4110 {
4111 dumper->printLocationAndOp(__location, &"**in_by_val"[2 - __sizeShiftAmount]);
4112 dumper->dumpOperand(m_dst, true);
4113 dumper->dumpOperand(m_base, false);
4114 dumper->dumpOperand(m_property, false);
4115 }
4116
4117 OpInByVal(const uint8_t* stream)
4118 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
4119 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
4120 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
4121 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
4122 {
4123 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4124 }
4125
4126 OpInByVal(const uint16_t* stream)
4127 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
4128 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
4129 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
4130 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
4131 {
4132 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4133 }
4134
4135
4136 OpInByVal(const uint32_t* stream)
4137 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
4138 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
4139 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
4140 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
4141 {
4142 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4143 }
4144
4145 static OpInByVal decode(const uint8_t* stream)
4146 {
4147 if (*stream == op_wide32)
4148 return { bitwise_cast<const uint32_t*>(stream + 1) };
4149 if (*stream == op_wide16)
4150 return { bitwise_cast<const uint16_t*>(stream + 1) };
4151 return { stream };
4152 }
4153
4154 template<typename Functor>
4155 void setDst(VirtualRegister value, Functor func)
4156 {
4157 if (isWide32())
4158 setDst<OpcodeSize::Wide32>(value, func);
4159 else if (isWide16())
4160 setDst<OpcodeSize::Wide16>(value, func);
4161 else
4162 setDst<OpcodeSize::Narrow>(value, func);
4163 }
4164
4165 template <OpcodeSize size, typename Functor>
4166 void setDst(VirtualRegister value, Functor func)
4167 {
4168 if (!Fits<VirtualRegister, size>::check(value))
4169 value = func();
4170 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
4171 *stream = Fits<VirtualRegister, size>::convert(value);
4172 }
4173
4174 template<typename Functor>
4175 void setBase(VirtualRegister value, Functor func)
4176 {
4177 if (isWide32())
4178 setBase<OpcodeSize::Wide32>(value, func);
4179 else if (isWide16())
4180 setBase<OpcodeSize::Wide16>(value, func);
4181 else
4182 setBase<OpcodeSize::Narrow>(value, func);
4183 }
4184
4185 template <OpcodeSize size, typename Functor>
4186 void setBase(VirtualRegister value, Functor func)
4187 {
4188 if (!Fits<VirtualRegister, size>::check(value))
4189 value = func();
4190 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
4191 *stream = Fits<VirtualRegister, size>::convert(value);
4192 }
4193
4194 template<typename Functor>
4195 void setProperty(VirtualRegister value, Functor func)
4196 {
4197 if (isWide32())
4198 setProperty<OpcodeSize::Wide32>(value, func);
4199 else if (isWide16())
4200 setProperty<OpcodeSize::Wide16>(value, func);
4201 else
4202 setProperty<OpcodeSize::Narrow>(value, func);
4203 }
4204
4205 template <OpcodeSize size, typename Functor>
4206 void setProperty(VirtualRegister value, Functor func)
4207 {
4208 if (!Fits<VirtualRegister, size>::check(value))
4209 value = func();
4210 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
4211 *stream = Fits<VirtualRegister, size>::convert(value);
4212 }
4213
4214 struct Metadata {
4215 WTF_MAKE_NONCOPYABLE(Metadata);
4216
4217 public:
4218 Metadata(const OpInByVal&) { }
4219
4220 ArrayProfile m_arrayProfile;
4221 };
4222
4223 Metadata& metadata(CodeBlock* codeBlock) const
4224 {
4225 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
4226 }
4227
4228 Metadata& metadata(ExecState* exec) const
4229 {
4230 return metadata(exec->codeBlock());
4231 }
4232
4233 VirtualRegister m_dst;
4234 VirtualRegister m_base;
4235 VirtualRegister m_property;
4236 unsigned m_metadataID;
4237};
4238
4239struct OpGetById : public Instruction {
4240 static constexpr OpcodeID opcodeID = op_get_by_id;
4241
4242 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4243 {
4244 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
4245 }
4246
4247 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
4248 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4249 {
4250 auto __metadataID = gen->addMetadataFor(opcodeID);
4251 return emit<size, shouldAssert>(gen, dst, base, property, __metadataID);
4252 }
4253
4254 template<OpcodeSize size>
4255 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4256 {
4257 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
4258 return checkImpl<size>(gen, dst, base, property, __metadataID);
4259 }
4260
4261 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
4262 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
4263 {
4264 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID);
4265 if (shouldAssert == Assert)
4266 ASSERT(didEmit);
4267 return didEmit;
4268 }
4269
4270 template<OpcodeSize size>
4271 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4272 {
4273
4274 auto __metadataID = gen->addMetadataFor(opcodeID);
4275 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
4276 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID))
4277 return;
4278 }
4279 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
4280 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
4281 return;
4282 }
4283 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
4284 }
4285
4286private:
4287 template<OpcodeSize size>
4288 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property, unsigned __metadataID)
4289 {
4290 UNUSED_PARAM(gen);
4291#if OS(WINDOWS) && ENABLE(C_LOOP)
4292 // FIXME: Disable wide16 optimization for Windows CLoop
4293 // https://bugs.webkit.org/show_bug.cgi?id=198283
4294 if (size == OpcodeSize::Wide16)
4295 return false;
4296#endif
4297 return Fits<OpcodeID, size>::check(opcodeID)
4298 && Fits<VirtualRegister, size>::check(dst)
4299 && Fits<VirtualRegister, size>::check(base)
4300 && Fits<unsigned, size>::check(property)
4301 && Fits<unsigned, size>::check(__metadataID)
4302 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
4303 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
4304 }
4305
4306 template<OpcodeSize size, bool recordOpcode>
4307 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
4308 {
4309 if (size == OpcodeSize::Wide16)
4310 gen->alignWideOpcode16();
4311 else if (size == OpcodeSize::Wide32)
4312 gen->alignWideOpcode32();
4313 if (checkImpl<size>(gen, dst, base, property, __metadataID)) {
4314 if (recordOpcode)
4315 gen->recordOpcode(opcodeID);
4316 if (size == OpcodeSize::Wide16)
4317 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
4318 else if (size == OpcodeSize::Wide32)
4319 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
4320 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
4321 gen->write(Fits<VirtualRegister, size>::convert(dst));
4322 gen->write(Fits<VirtualRegister, size>::convert(base));
4323 gen->write(Fits<unsigned, size>::convert(property));
4324 gen->write(Fits<unsigned, size>::convert(__metadataID));
4325 return true;
4326 }
4327 return false;
4328 }
4329
4330public:
4331 template<typename Block>
4332 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
4333 {
4334 dumper->printLocationAndOp(__location, &"**get_by_id"[2 - __sizeShiftAmount]);
4335 dumper->dumpOperand(m_dst, true);
4336 dumper->dumpOperand(m_base, false);
4337 dumper->dumpOperand(m_property, false);
4338 }
4339
4340 OpGetById(const uint8_t* stream)
4341 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
4342 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
4343 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
4344 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
4345 {
4346 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4347 }
4348
4349 OpGetById(const uint16_t* stream)
4350 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
4351 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
4352 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
4353 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
4354 {
4355 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4356 }
4357
4358
4359 OpGetById(const uint32_t* stream)
4360 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
4361 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
4362 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
4363 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
4364 {
4365 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4366 }
4367
4368 static OpGetById decode(const uint8_t* stream)
4369 {
4370 if (*stream == op_wide32)
4371 return { bitwise_cast<const uint32_t*>(stream + 1) };
4372 if (*stream == op_wide16)
4373 return { bitwise_cast<const uint16_t*>(stream + 1) };
4374 return { stream };
4375 }
4376
4377 template<typename Functor>
4378 void setDst(VirtualRegister value, Functor func)
4379 {
4380 if (isWide32())
4381 setDst<OpcodeSize::Wide32>(value, func);
4382 else if (isWide16())
4383 setDst<OpcodeSize::Wide16>(value, func);
4384 else
4385 setDst<OpcodeSize::Narrow>(value, func);
4386 }
4387
4388 template <OpcodeSize size, typename Functor>
4389 void setDst(VirtualRegister value, Functor func)
4390 {
4391 if (!Fits<VirtualRegister, size>::check(value))
4392 value = func();
4393 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
4394 *stream = Fits<VirtualRegister, size>::convert(value);
4395 }
4396
4397 template<typename Functor>
4398 void setBase(VirtualRegister value, Functor func)
4399 {
4400 if (isWide32())
4401 setBase<OpcodeSize::Wide32>(value, func);
4402 else if (isWide16())
4403 setBase<OpcodeSize::Wide16>(value, func);
4404 else
4405 setBase<OpcodeSize::Narrow>(value, func);
4406 }
4407
4408 template <OpcodeSize size, typename Functor>
4409 void setBase(VirtualRegister value, Functor func)
4410 {
4411 if (!Fits<VirtualRegister, size>::check(value))
4412 value = func();
4413 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
4414 *stream = Fits<VirtualRegister, size>::convert(value);
4415 }
4416
4417 template<typename Functor>
4418 void setProperty(unsigned value, Functor func)
4419 {
4420 if (isWide32())
4421 setProperty<OpcodeSize::Wide32>(value, func);
4422 else if (isWide16())
4423 setProperty<OpcodeSize::Wide16>(value, func);
4424 else
4425 setProperty<OpcodeSize::Narrow>(value, func);
4426 }
4427
4428 template <OpcodeSize size, typename Functor>
4429 void setProperty(unsigned value, Functor func)
4430 {
4431 if (!Fits<unsigned, size>::check(value))
4432 value = func();
4433 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
4434 *stream = Fits<unsigned, size>::convert(value);
4435 }
4436
4437 struct Metadata {
4438 WTF_MAKE_NONCOPYABLE(Metadata);
4439
4440 public:
4441 Metadata(const OpGetById&) { }
4442
4443 GetByIdModeMetadata m_modeMetadata;
4444 ValueProfile m_profile;
4445 };
4446
4447 Metadata& metadata(CodeBlock* codeBlock) const
4448 {
4449 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
4450 }
4451
4452 Metadata& metadata(ExecState* exec) const
4453 {
4454 return metadata(exec->codeBlock());
4455 }
4456
4457 VirtualRegister m_dst;
4458 VirtualRegister m_base;
4459 unsigned m_property;
4460 unsigned m_metadataID;
4461};
4462
4463struct OpGetByIdWithThis : public Instruction {
4464 static constexpr OpcodeID opcodeID = op_get_by_id_with_this;
4465
4466 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
4467 {
4468 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, thisValue, property);
4469 }
4470
4471 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
4472 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
4473 {
4474 auto __metadataID = gen->addMetadataFor(opcodeID);
4475 return emit<size, shouldAssert>(gen, dst, base, thisValue, property, __metadataID);
4476 }
4477
4478 template<OpcodeSize size>
4479 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
4480 {
4481 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
4482 return checkImpl<size>(gen, dst, base, thisValue, property, __metadataID);
4483 }
4484
4485 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
4486 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property, unsigned __metadataID)
4487 {
4488 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, thisValue, property, __metadataID);
4489 if (shouldAssert == Assert)
4490 ASSERT(didEmit);
4491 return didEmit;
4492 }
4493
4494 template<OpcodeSize size>
4495 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
4496 {
4497
4498 auto __metadataID = gen->addMetadataFor(opcodeID);
4499 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
4500 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
4501 return;
4502 }
4503 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
4504 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
4505 return;
4506 }
4507 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, thisValue, property, __metadataID);
4508 }
4509
4510private:
4511 template<OpcodeSize size>
4512 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& thisValue, unsigned& property, unsigned __metadataID)
4513 {
4514 UNUSED_PARAM(gen);
4515#if OS(WINDOWS) && ENABLE(C_LOOP)
4516 // FIXME: Disable wide16 optimization for Windows CLoop
4517 // https://bugs.webkit.org/show_bug.cgi?id=198283
4518 if (size == OpcodeSize::Wide16)
4519 return false;
4520#endif
4521 return Fits<OpcodeID, size>::check(opcodeID)
4522 && Fits<VirtualRegister, size>::check(dst)
4523 && Fits<VirtualRegister, size>::check(base)
4524 && Fits<VirtualRegister, size>::check(thisValue)
4525 && Fits<unsigned, size>::check(property)
4526 && Fits<unsigned, size>::check(__metadataID)
4527 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
4528 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
4529 }
4530
4531 template<OpcodeSize size, bool recordOpcode>
4532 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property, unsigned __metadataID)
4533 {
4534 if (size == OpcodeSize::Wide16)
4535 gen->alignWideOpcode16();
4536 else if (size == OpcodeSize::Wide32)
4537 gen->alignWideOpcode32();
4538 if (checkImpl<size>(gen, dst, base, thisValue, property, __metadataID)) {
4539 if (recordOpcode)
4540 gen->recordOpcode(opcodeID);
4541 if (size == OpcodeSize::Wide16)
4542 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
4543 else if (size == OpcodeSize::Wide32)
4544 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
4545 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
4546 gen->write(Fits<VirtualRegister, size>::convert(dst));
4547 gen->write(Fits<VirtualRegister, size>::convert(base));
4548 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
4549 gen->write(Fits<unsigned, size>::convert(property));
4550 gen->write(Fits<unsigned, size>::convert(__metadataID));
4551 return true;
4552 }
4553 return false;
4554 }
4555
4556public:
4557 template<typename Block>
4558 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
4559 {
4560 dumper->printLocationAndOp(__location, &"**get_by_id_with_this"[2 - __sizeShiftAmount]);
4561 dumper->dumpOperand(m_dst, true);
4562 dumper->dumpOperand(m_base, false);
4563 dumper->dumpOperand(m_thisValue, false);
4564 dumper->dumpOperand(m_property, false);
4565 }
4566
4567 OpGetByIdWithThis(const uint8_t* stream)
4568 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
4569 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
4570 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
4571 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
4572 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
4573 {
4574 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4575 }
4576
4577 OpGetByIdWithThis(const uint16_t* stream)
4578 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
4579 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
4580 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
4581 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
4582 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
4583 {
4584 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4585 }
4586
4587
4588 OpGetByIdWithThis(const uint32_t* stream)
4589 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
4590 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
4591 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
4592 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
4593 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
4594 {
4595 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4596 }
4597
4598 static OpGetByIdWithThis decode(const uint8_t* stream)
4599 {
4600 if (*stream == op_wide32)
4601 return { bitwise_cast<const uint32_t*>(stream + 1) };
4602 if (*stream == op_wide16)
4603 return { bitwise_cast<const uint16_t*>(stream + 1) };
4604 return { stream };
4605 }
4606
4607 template<typename Functor>
4608 void setDst(VirtualRegister value, Functor func)
4609 {
4610 if (isWide32())
4611 setDst<OpcodeSize::Wide32>(value, func);
4612 else if (isWide16())
4613 setDst<OpcodeSize::Wide16>(value, func);
4614 else
4615 setDst<OpcodeSize::Narrow>(value, func);
4616 }
4617
4618 template <OpcodeSize size, typename Functor>
4619 void setDst(VirtualRegister value, Functor func)
4620 {
4621 if (!Fits<VirtualRegister, size>::check(value))
4622 value = func();
4623 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
4624 *stream = Fits<VirtualRegister, size>::convert(value);
4625 }
4626
4627 template<typename Functor>
4628 void setBase(VirtualRegister value, Functor func)
4629 {
4630 if (isWide32())
4631 setBase<OpcodeSize::Wide32>(value, func);
4632 else if (isWide16())
4633 setBase<OpcodeSize::Wide16>(value, func);
4634 else
4635 setBase<OpcodeSize::Narrow>(value, func);
4636 }
4637
4638 template <OpcodeSize size, typename Functor>
4639 void setBase(VirtualRegister value, Functor func)
4640 {
4641 if (!Fits<VirtualRegister, size>::check(value))
4642 value = func();
4643 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
4644 *stream = Fits<VirtualRegister, size>::convert(value);
4645 }
4646
4647 template<typename Functor>
4648 void setThisValue(VirtualRegister value, Functor func)
4649 {
4650 if (isWide32())
4651 setThisValue<OpcodeSize::Wide32>(value, func);
4652 else if (isWide16())
4653 setThisValue<OpcodeSize::Wide16>(value, func);
4654 else
4655 setThisValue<OpcodeSize::Narrow>(value, func);
4656 }
4657
4658 template <OpcodeSize size, typename Functor>
4659 void setThisValue(VirtualRegister value, Functor func)
4660 {
4661 if (!Fits<VirtualRegister, size>::check(value))
4662 value = func();
4663 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
4664 *stream = Fits<VirtualRegister, size>::convert(value);
4665 }
4666
4667 template<typename Functor>
4668 void setProperty(unsigned value, Functor func)
4669 {
4670 if (isWide32())
4671 setProperty<OpcodeSize::Wide32>(value, func);
4672 else if (isWide16())
4673 setProperty<OpcodeSize::Wide16>(value, func);
4674 else
4675 setProperty<OpcodeSize::Narrow>(value, func);
4676 }
4677
4678 template <OpcodeSize size, typename Functor>
4679 void setProperty(unsigned value, Functor func)
4680 {
4681 if (!Fits<unsigned, size>::check(value))
4682 value = func();
4683 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
4684 *stream = Fits<unsigned, size>::convert(value);
4685 }
4686
4687 struct Metadata {
4688 WTF_MAKE_NONCOPYABLE(Metadata);
4689
4690 public:
4691 Metadata(const OpGetByIdWithThis&) { }
4692
4693 ValueProfile m_profile;
4694 };
4695
4696 Metadata& metadata(CodeBlock* codeBlock) const
4697 {
4698 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
4699 }
4700
4701 Metadata& metadata(ExecState* exec) const
4702 {
4703 return metadata(exec->codeBlock());
4704 }
4705
4706 VirtualRegister m_dst;
4707 VirtualRegister m_base;
4708 VirtualRegister m_thisValue;
4709 unsigned m_property;
4710 unsigned m_metadataID;
4711};
4712
4713struct OpGetByValWithThis : public Instruction {
4714 static constexpr OpcodeID opcodeID = op_get_by_val_with_this;
4715
4716 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
4717 {
4718 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, thisValue, property);
4719 }
4720
4721 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
4722 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
4723 {
4724 auto __metadataID = gen->addMetadataFor(opcodeID);
4725 return emit<size, shouldAssert>(gen, dst, base, thisValue, property, __metadataID);
4726 }
4727
4728 template<OpcodeSize size>
4729 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
4730 {
4731 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
4732 return checkImpl<size>(gen, dst, base, thisValue, property, __metadataID);
4733 }
4734
4735 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
4736 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, unsigned __metadataID)
4737 {
4738 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, thisValue, property, __metadataID);
4739 if (shouldAssert == Assert)
4740 ASSERT(didEmit);
4741 return didEmit;
4742 }
4743
4744 template<OpcodeSize size>
4745 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
4746 {
4747
4748 auto __metadataID = gen->addMetadataFor(opcodeID);
4749 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
4750 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
4751 return;
4752 }
4753 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
4754 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
4755 return;
4756 }
4757 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, thisValue, property, __metadataID);
4758 }
4759
4760private:
4761 template<OpcodeSize size>
4762 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& thisValue, VirtualRegister& property, unsigned __metadataID)
4763 {
4764 UNUSED_PARAM(gen);
4765#if OS(WINDOWS) && ENABLE(C_LOOP)
4766 // FIXME: Disable wide16 optimization for Windows CLoop
4767 // https://bugs.webkit.org/show_bug.cgi?id=198283
4768 if (size == OpcodeSize::Wide16)
4769 return false;
4770#endif
4771 return Fits<OpcodeID, size>::check(opcodeID)
4772 && Fits<VirtualRegister, size>::check(dst)
4773 && Fits<VirtualRegister, size>::check(base)
4774 && Fits<VirtualRegister, size>::check(thisValue)
4775 && Fits<VirtualRegister, size>::check(property)
4776 && Fits<unsigned, size>::check(__metadataID)
4777 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
4778 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
4779 }
4780
4781 template<OpcodeSize size, bool recordOpcode>
4782 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, unsigned __metadataID)
4783 {
4784 if (size == OpcodeSize::Wide16)
4785 gen->alignWideOpcode16();
4786 else if (size == OpcodeSize::Wide32)
4787 gen->alignWideOpcode32();
4788 if (checkImpl<size>(gen, dst, base, thisValue, property, __metadataID)) {
4789 if (recordOpcode)
4790 gen->recordOpcode(opcodeID);
4791 if (size == OpcodeSize::Wide16)
4792 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
4793 else if (size == OpcodeSize::Wide32)
4794 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
4795 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
4796 gen->write(Fits<VirtualRegister, size>::convert(dst));
4797 gen->write(Fits<VirtualRegister, size>::convert(base));
4798 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
4799 gen->write(Fits<VirtualRegister, size>::convert(property));
4800 gen->write(Fits<unsigned, size>::convert(__metadataID));
4801 return true;
4802 }
4803 return false;
4804 }
4805
4806public:
4807 template<typename Block>
4808 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
4809 {
4810 dumper->printLocationAndOp(__location, &"**get_by_val_with_this"[2 - __sizeShiftAmount]);
4811 dumper->dumpOperand(m_dst, true);
4812 dumper->dumpOperand(m_base, false);
4813 dumper->dumpOperand(m_thisValue, false);
4814 dumper->dumpOperand(m_property, false);
4815 }
4816
4817 OpGetByValWithThis(const uint8_t* stream)
4818 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
4819 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
4820 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
4821 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
4822 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
4823 {
4824 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4825 }
4826
4827 OpGetByValWithThis(const uint16_t* stream)
4828 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
4829 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
4830 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
4831 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
4832 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
4833 {
4834 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4835 }
4836
4837
4838 OpGetByValWithThis(const uint32_t* stream)
4839 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
4840 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
4841 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
4842 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
4843 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
4844 {
4845 ASSERT_UNUSED(stream, stream[0] == opcodeID);
4846 }
4847
4848 static OpGetByValWithThis decode(const uint8_t* stream)
4849 {
4850 if (*stream == op_wide32)
4851 return { bitwise_cast<const uint32_t*>(stream + 1) };
4852 if (*stream == op_wide16)
4853 return { bitwise_cast<const uint16_t*>(stream + 1) };
4854 return { stream };
4855 }
4856
4857 template<typename Functor>
4858 void setDst(VirtualRegister value, Functor func)
4859 {
4860 if (isWide32())
4861 setDst<OpcodeSize::Wide32>(value, func);
4862 else if (isWide16())
4863 setDst<OpcodeSize::Wide16>(value, func);
4864 else
4865 setDst<OpcodeSize::Narrow>(value, func);
4866 }
4867
4868 template <OpcodeSize size, typename Functor>
4869 void setDst(VirtualRegister value, Functor func)
4870 {
4871 if (!Fits<VirtualRegister, size>::check(value))
4872 value = func();
4873 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
4874 *stream = Fits<VirtualRegister, size>::convert(value);
4875 }
4876
4877 template<typename Functor>
4878 void setBase(VirtualRegister value, Functor func)
4879 {
4880 if (isWide32())
4881 setBase<OpcodeSize::Wide32>(value, func);
4882 else if (isWide16())
4883 setBase<OpcodeSize::Wide16>(value, func);
4884 else
4885 setBase<OpcodeSize::Narrow>(value, func);
4886 }
4887
4888 template <OpcodeSize size, typename Functor>
4889 void setBase(VirtualRegister value, Functor func)
4890 {
4891 if (!Fits<VirtualRegister, size>::check(value))
4892 value = func();
4893 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
4894 *stream = Fits<VirtualRegister, size>::convert(value);
4895 }
4896
4897 template<typename Functor>
4898 void setThisValue(VirtualRegister value, Functor func)
4899 {
4900 if (isWide32())
4901 setThisValue<OpcodeSize::Wide32>(value, func);
4902 else if (isWide16())
4903 setThisValue<OpcodeSize::Wide16>(value, func);
4904 else
4905 setThisValue<OpcodeSize::Narrow>(value, func);
4906 }
4907
4908 template <OpcodeSize size, typename Functor>
4909 void setThisValue(VirtualRegister value, Functor func)
4910 {
4911 if (!Fits<VirtualRegister, size>::check(value))
4912 value = func();
4913 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
4914 *stream = Fits<VirtualRegister, size>::convert(value);
4915 }
4916
4917 template<typename Functor>
4918 void setProperty(VirtualRegister value, Functor func)
4919 {
4920 if (isWide32())
4921 setProperty<OpcodeSize::Wide32>(value, func);
4922 else if (isWide16())
4923 setProperty<OpcodeSize::Wide16>(value, func);
4924 else
4925 setProperty<OpcodeSize::Narrow>(value, func);
4926 }
4927
4928 template <OpcodeSize size, typename Functor>
4929 void setProperty(VirtualRegister value, Functor func)
4930 {
4931 if (!Fits<VirtualRegister, size>::check(value))
4932 value = func();
4933 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
4934 *stream = Fits<VirtualRegister, size>::convert(value);
4935 }
4936
4937 struct Metadata {
4938 WTF_MAKE_NONCOPYABLE(Metadata);
4939
4940 public:
4941 Metadata(const OpGetByValWithThis&) { }
4942
4943 ValueProfile m_profile;
4944 };
4945
4946 Metadata& metadata(CodeBlock* codeBlock) const
4947 {
4948 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
4949 }
4950
4951 Metadata& metadata(ExecState* exec) const
4952 {
4953 return metadata(exec->codeBlock());
4954 }
4955
4956 VirtualRegister m_dst;
4957 VirtualRegister m_base;
4958 VirtualRegister m_thisValue;
4959 VirtualRegister m_property;
4960 unsigned m_metadataID;
4961};
4962
4963struct OpGetByIdDirect : public Instruction {
4964 static constexpr OpcodeID opcodeID = op_get_by_id_direct;
4965
4966 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4967 {
4968 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
4969 }
4970
4971 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
4972 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4973 {
4974 auto __metadataID = gen->addMetadataFor(opcodeID);
4975 return emit<size, shouldAssert>(gen, dst, base, property, __metadataID);
4976 }
4977
4978 template<OpcodeSize size>
4979 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4980 {
4981 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
4982 return checkImpl<size>(gen, dst, base, property, __metadataID);
4983 }
4984
4985 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
4986 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
4987 {
4988 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID);
4989 if (shouldAssert == Assert)
4990 ASSERT(didEmit);
4991 return didEmit;
4992 }
4993
4994 template<OpcodeSize size>
4995 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
4996 {
4997
4998 auto __metadataID = gen->addMetadataFor(opcodeID);
4999 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
5000 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID))
5001 return;
5002 }
5003 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
5004 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
5005 return;
5006 }
5007 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
5008 }
5009
5010private:
5011 template<OpcodeSize size>
5012 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property, unsigned __metadataID)
5013 {
5014 UNUSED_PARAM(gen);
5015#if OS(WINDOWS) && ENABLE(C_LOOP)
5016 // FIXME: Disable wide16 optimization for Windows CLoop
5017 // https://bugs.webkit.org/show_bug.cgi?id=198283
5018 if (size == OpcodeSize::Wide16)
5019 return false;
5020#endif
5021 return Fits<OpcodeID, size>::check(opcodeID)
5022 && Fits<VirtualRegister, size>::check(dst)
5023 && Fits<VirtualRegister, size>::check(base)
5024 && Fits<unsigned, size>::check(property)
5025 && Fits<unsigned, size>::check(__metadataID)
5026 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
5027 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
5028 }
5029
5030 template<OpcodeSize size, bool recordOpcode>
5031 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
5032 {
5033 if (size == OpcodeSize::Wide16)
5034 gen->alignWideOpcode16();
5035 else if (size == OpcodeSize::Wide32)
5036 gen->alignWideOpcode32();
5037 if (checkImpl<size>(gen, dst, base, property, __metadataID)) {
5038 if (recordOpcode)
5039 gen->recordOpcode(opcodeID);
5040 if (size == OpcodeSize::Wide16)
5041 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
5042 else if (size == OpcodeSize::Wide32)
5043 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
5044 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
5045 gen->write(Fits<VirtualRegister, size>::convert(dst));
5046 gen->write(Fits<VirtualRegister, size>::convert(base));
5047 gen->write(Fits<unsigned, size>::convert(property));
5048 gen->write(Fits<unsigned, size>::convert(__metadataID));
5049 return true;
5050 }
5051 return false;
5052 }
5053
5054public:
5055 template<typename Block>
5056 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
5057 {
5058 dumper->printLocationAndOp(__location, &"**get_by_id_direct"[2 - __sizeShiftAmount]);
5059 dumper->dumpOperand(m_dst, true);
5060 dumper->dumpOperand(m_base, false);
5061 dumper->dumpOperand(m_property, false);
5062 }
5063
5064 OpGetByIdDirect(const uint8_t* stream)
5065 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
5066 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
5067 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
5068 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
5069 {
5070 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5071 }
5072
5073 OpGetByIdDirect(const uint16_t* stream)
5074 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
5075 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
5076 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
5077 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
5078 {
5079 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5080 }
5081
5082
5083 OpGetByIdDirect(const uint32_t* stream)
5084 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
5085 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
5086 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
5087 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
5088 {
5089 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5090 }
5091
5092 static OpGetByIdDirect decode(const uint8_t* stream)
5093 {
5094 if (*stream == op_wide32)
5095 return { bitwise_cast<const uint32_t*>(stream + 1) };
5096 if (*stream == op_wide16)
5097 return { bitwise_cast<const uint16_t*>(stream + 1) };
5098 return { stream };
5099 }
5100
5101 template<typename Functor>
5102 void setDst(VirtualRegister value, Functor func)
5103 {
5104 if (isWide32())
5105 setDst<OpcodeSize::Wide32>(value, func);
5106 else if (isWide16())
5107 setDst<OpcodeSize::Wide16>(value, func);
5108 else
5109 setDst<OpcodeSize::Narrow>(value, func);
5110 }
5111
5112 template <OpcodeSize size, typename Functor>
5113 void setDst(VirtualRegister value, Functor func)
5114 {
5115 if (!Fits<VirtualRegister, size>::check(value))
5116 value = func();
5117 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
5118 *stream = Fits<VirtualRegister, size>::convert(value);
5119 }
5120
5121 template<typename Functor>
5122 void setBase(VirtualRegister value, Functor func)
5123 {
5124 if (isWide32())
5125 setBase<OpcodeSize::Wide32>(value, func);
5126 else if (isWide16())
5127 setBase<OpcodeSize::Wide16>(value, func);
5128 else
5129 setBase<OpcodeSize::Narrow>(value, func);
5130 }
5131
5132 template <OpcodeSize size, typename Functor>
5133 void setBase(VirtualRegister value, Functor func)
5134 {
5135 if (!Fits<VirtualRegister, size>::check(value))
5136 value = func();
5137 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
5138 *stream = Fits<VirtualRegister, size>::convert(value);
5139 }
5140
5141 template<typename Functor>
5142 void setProperty(unsigned value, Functor func)
5143 {
5144 if (isWide32())
5145 setProperty<OpcodeSize::Wide32>(value, func);
5146 else if (isWide16())
5147 setProperty<OpcodeSize::Wide16>(value, func);
5148 else
5149 setProperty<OpcodeSize::Narrow>(value, func);
5150 }
5151
5152 template <OpcodeSize size, typename Functor>
5153 void setProperty(unsigned value, Functor func)
5154 {
5155 if (!Fits<unsigned, size>::check(value))
5156 value = func();
5157 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
5158 *stream = Fits<unsigned, size>::convert(value);
5159 }
5160
5161 struct Metadata {
5162 WTF_MAKE_NONCOPYABLE(Metadata);
5163
5164 public:
5165 Metadata(const OpGetByIdDirect&) { }
5166
5167 ValueProfile m_profile;
5168 StructureID m_structureID;
5169 unsigned m_offset;
5170 };
5171
5172 Metadata& metadata(CodeBlock* codeBlock) const
5173 {
5174 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
5175 }
5176
5177 Metadata& metadata(ExecState* exec) const
5178 {
5179 return metadata(exec->codeBlock());
5180 }
5181
5182 VirtualRegister m_dst;
5183 VirtualRegister m_base;
5184 unsigned m_property;
5185 unsigned m_metadataID;
5186};
5187
5188struct OpTryGetById : public Instruction {
5189 static constexpr OpcodeID opcodeID = op_try_get_by_id;
5190
5191 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
5192 {
5193 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
5194 }
5195
5196 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
5197 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
5198 {
5199 auto __metadataID = gen->addMetadataFor(opcodeID);
5200 return emit<size, shouldAssert>(gen, dst, base, property, __metadataID);
5201 }
5202
5203 template<OpcodeSize size>
5204 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
5205 {
5206 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
5207 return checkImpl<size>(gen, dst, base, property, __metadataID);
5208 }
5209
5210 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
5211 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
5212 {
5213 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID);
5214 if (shouldAssert == Assert)
5215 ASSERT(didEmit);
5216 return didEmit;
5217 }
5218
5219 template<OpcodeSize size>
5220 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
5221 {
5222
5223 auto __metadataID = gen->addMetadataFor(opcodeID);
5224 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
5225 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID))
5226 return;
5227 }
5228 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
5229 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
5230 return;
5231 }
5232 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
5233 }
5234
5235private:
5236 template<OpcodeSize size>
5237 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property, unsigned __metadataID)
5238 {
5239 UNUSED_PARAM(gen);
5240#if OS(WINDOWS) && ENABLE(C_LOOP)
5241 // FIXME: Disable wide16 optimization for Windows CLoop
5242 // https://bugs.webkit.org/show_bug.cgi?id=198283
5243 if (size == OpcodeSize::Wide16)
5244 return false;
5245#endif
5246 return Fits<OpcodeID, size>::check(opcodeID)
5247 && Fits<VirtualRegister, size>::check(dst)
5248 && Fits<VirtualRegister, size>::check(base)
5249 && Fits<unsigned, size>::check(property)
5250 && Fits<unsigned, size>::check(__metadataID)
5251 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
5252 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
5253 }
5254
5255 template<OpcodeSize size, bool recordOpcode>
5256 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
5257 {
5258 if (size == OpcodeSize::Wide16)
5259 gen->alignWideOpcode16();
5260 else if (size == OpcodeSize::Wide32)
5261 gen->alignWideOpcode32();
5262 if (checkImpl<size>(gen, dst, base, property, __metadataID)) {
5263 if (recordOpcode)
5264 gen->recordOpcode(opcodeID);
5265 if (size == OpcodeSize::Wide16)
5266 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
5267 else if (size == OpcodeSize::Wide32)
5268 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
5269 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
5270 gen->write(Fits<VirtualRegister, size>::convert(dst));
5271 gen->write(Fits<VirtualRegister, size>::convert(base));
5272 gen->write(Fits<unsigned, size>::convert(property));
5273 gen->write(Fits<unsigned, size>::convert(__metadataID));
5274 return true;
5275 }
5276 return false;
5277 }
5278
5279public:
5280 template<typename Block>
5281 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
5282 {
5283 dumper->printLocationAndOp(__location, &"**try_get_by_id"[2 - __sizeShiftAmount]);
5284 dumper->dumpOperand(m_dst, true);
5285 dumper->dumpOperand(m_base, false);
5286 dumper->dumpOperand(m_property, false);
5287 }
5288
5289 OpTryGetById(const uint8_t* stream)
5290 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
5291 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
5292 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
5293 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
5294 {
5295 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5296 }
5297
5298 OpTryGetById(const uint16_t* stream)
5299 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
5300 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
5301 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
5302 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
5303 {
5304 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5305 }
5306
5307
5308 OpTryGetById(const uint32_t* stream)
5309 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
5310 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
5311 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
5312 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
5313 {
5314 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5315 }
5316
5317 static OpTryGetById decode(const uint8_t* stream)
5318 {
5319 if (*stream == op_wide32)
5320 return { bitwise_cast<const uint32_t*>(stream + 1) };
5321 if (*stream == op_wide16)
5322 return { bitwise_cast<const uint16_t*>(stream + 1) };
5323 return { stream };
5324 }
5325
5326 template<typename Functor>
5327 void setDst(VirtualRegister value, Functor func)
5328 {
5329 if (isWide32())
5330 setDst<OpcodeSize::Wide32>(value, func);
5331 else if (isWide16())
5332 setDst<OpcodeSize::Wide16>(value, func);
5333 else
5334 setDst<OpcodeSize::Narrow>(value, func);
5335 }
5336
5337 template <OpcodeSize size, typename Functor>
5338 void setDst(VirtualRegister value, Functor func)
5339 {
5340 if (!Fits<VirtualRegister, size>::check(value))
5341 value = func();
5342 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
5343 *stream = Fits<VirtualRegister, size>::convert(value);
5344 }
5345
5346 template<typename Functor>
5347 void setBase(VirtualRegister value, Functor func)
5348 {
5349 if (isWide32())
5350 setBase<OpcodeSize::Wide32>(value, func);
5351 else if (isWide16())
5352 setBase<OpcodeSize::Wide16>(value, func);
5353 else
5354 setBase<OpcodeSize::Narrow>(value, func);
5355 }
5356
5357 template <OpcodeSize size, typename Functor>
5358 void setBase(VirtualRegister value, Functor func)
5359 {
5360 if (!Fits<VirtualRegister, size>::check(value))
5361 value = func();
5362 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
5363 *stream = Fits<VirtualRegister, size>::convert(value);
5364 }
5365
5366 template<typename Functor>
5367 void setProperty(unsigned value, Functor func)
5368 {
5369 if (isWide32())
5370 setProperty<OpcodeSize::Wide32>(value, func);
5371 else if (isWide16())
5372 setProperty<OpcodeSize::Wide16>(value, func);
5373 else
5374 setProperty<OpcodeSize::Narrow>(value, func);
5375 }
5376
5377 template <OpcodeSize size, typename Functor>
5378 void setProperty(unsigned value, Functor func)
5379 {
5380 if (!Fits<unsigned, size>::check(value))
5381 value = func();
5382 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
5383 *stream = Fits<unsigned, size>::convert(value);
5384 }
5385
5386 struct Metadata {
5387 WTF_MAKE_NONCOPYABLE(Metadata);
5388
5389 public:
5390 Metadata(const OpTryGetById&) { }
5391
5392 ValueProfile m_profile;
5393 };
5394
5395 Metadata& metadata(CodeBlock* codeBlock) const
5396 {
5397 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
5398 }
5399
5400 Metadata& metadata(ExecState* exec) const
5401 {
5402 return metadata(exec->codeBlock());
5403 }
5404
5405 VirtualRegister m_dst;
5406 VirtualRegister m_base;
5407 unsigned m_property;
5408 unsigned m_metadataID;
5409};
5410
5411struct OpPutById : public Instruction {
5412 static constexpr OpcodeID opcodeID = op_put_by_id;
5413
5414 static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
5415 {
5416 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, value, flags);
5417 }
5418
5419 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
5420 static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
5421 {
5422 auto __metadataID = gen->addMetadataFor(opcodeID);
5423 return emit<size, shouldAssert>(gen, base, property, value, flags, __metadataID);
5424 }
5425
5426 template<OpcodeSize size>
5427 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
5428 {
5429 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
5430 return checkImpl<size>(gen, base, property, value, flags, __metadataID);
5431 }
5432
5433 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
5434 static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags, unsigned __metadataID)
5435 {
5436 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, flags, __metadataID);
5437 if (shouldAssert == Assert)
5438 ASSERT(didEmit);
5439 return didEmit;
5440 }
5441
5442 template<OpcodeSize size>
5443 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
5444 {
5445
5446 auto __metadataID = gen->addMetadataFor(opcodeID);
5447 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
5448 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, flags, __metadataID))
5449 return;
5450 }
5451 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
5452 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, value, flags, __metadataID))
5453 return;
5454 }
5455 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, value, flags, __metadataID);
5456 }
5457
5458private:
5459 template<OpcodeSize size>
5460 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, VirtualRegister& value, PutByIdFlags& flags, unsigned __metadataID)
5461 {
5462 UNUSED_PARAM(gen);
5463#if OS(WINDOWS) && ENABLE(C_LOOP)
5464 // FIXME: Disable wide16 optimization for Windows CLoop
5465 // https://bugs.webkit.org/show_bug.cgi?id=198283
5466 if (size == OpcodeSize::Wide16)
5467 return false;
5468#endif
5469 return Fits<OpcodeID, size>::check(opcodeID)
5470 && Fits<VirtualRegister, size>::check(base)
5471 && Fits<unsigned, size>::check(property)
5472 && Fits<VirtualRegister, size>::check(value)
5473 && Fits<PutByIdFlags, size>::check(flags)
5474 && Fits<unsigned, size>::check(__metadataID)
5475 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
5476 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
5477 }
5478
5479 template<OpcodeSize size, bool recordOpcode>
5480 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags, unsigned __metadataID)
5481 {
5482 if (size == OpcodeSize::Wide16)
5483 gen->alignWideOpcode16();
5484 else if (size == OpcodeSize::Wide32)
5485 gen->alignWideOpcode32();
5486 if (checkImpl<size>(gen, base, property, value, flags, __metadataID)) {
5487 if (recordOpcode)
5488 gen->recordOpcode(opcodeID);
5489 if (size == OpcodeSize::Wide16)
5490 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
5491 else if (size == OpcodeSize::Wide32)
5492 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
5493 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
5494 gen->write(Fits<VirtualRegister, size>::convert(base));
5495 gen->write(Fits<unsigned, size>::convert(property));
5496 gen->write(Fits<VirtualRegister, size>::convert(value));
5497 gen->write(Fits<PutByIdFlags, size>::convert(flags));
5498 gen->write(Fits<unsigned, size>::convert(__metadataID));
5499 return true;
5500 }
5501 return false;
5502 }
5503
5504public:
5505 template<typename Block>
5506 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
5507 {
5508 dumper->printLocationAndOp(__location, &"**put_by_id"[2 - __sizeShiftAmount]);
5509 dumper->dumpOperand(m_base, true);
5510 dumper->dumpOperand(m_property, false);
5511 dumper->dumpOperand(m_value, false);
5512 dumper->dumpOperand(m_flags, false);
5513 }
5514
5515 OpPutById(const uint8_t* stream)
5516 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
5517 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
5518 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
5519 , m_flags(Fits<PutByIdFlags, OpcodeSize::Narrow>::convert(stream[4]))
5520 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
5521 {
5522 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5523 }
5524
5525 OpPutById(const uint16_t* stream)
5526 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
5527 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
5528 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
5529 , m_flags(Fits<PutByIdFlags, OpcodeSize::Wide16>::convert(stream[4]))
5530 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
5531 {
5532 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5533 }
5534
5535
5536 OpPutById(const uint32_t* stream)
5537 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
5538 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
5539 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
5540 , m_flags(Fits<PutByIdFlags, OpcodeSize::Wide32>::convert(stream[4]))
5541 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
5542 {
5543 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5544 }
5545
5546 static OpPutById decode(const uint8_t* stream)
5547 {
5548 if (*stream == op_wide32)
5549 return { bitwise_cast<const uint32_t*>(stream + 1) };
5550 if (*stream == op_wide16)
5551 return { bitwise_cast<const uint16_t*>(stream + 1) };
5552 return { stream };
5553 }
5554
5555 template<typename Functor>
5556 void setBase(VirtualRegister value, Functor func)
5557 {
5558 if (isWide32())
5559 setBase<OpcodeSize::Wide32>(value, func);
5560 else if (isWide16())
5561 setBase<OpcodeSize::Wide16>(value, func);
5562 else
5563 setBase<OpcodeSize::Narrow>(value, func);
5564 }
5565
5566 template <OpcodeSize size, typename Functor>
5567 void setBase(VirtualRegister value, Functor func)
5568 {
5569 if (!Fits<VirtualRegister, size>::check(value))
5570 value = func();
5571 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
5572 *stream = Fits<VirtualRegister, size>::convert(value);
5573 }
5574
5575 template<typename Functor>
5576 void setProperty(unsigned value, Functor func)
5577 {
5578 if (isWide32())
5579 setProperty<OpcodeSize::Wide32>(value, func);
5580 else if (isWide16())
5581 setProperty<OpcodeSize::Wide16>(value, func);
5582 else
5583 setProperty<OpcodeSize::Narrow>(value, func);
5584 }
5585
5586 template <OpcodeSize size, typename Functor>
5587 void setProperty(unsigned value, Functor func)
5588 {
5589 if (!Fits<unsigned, size>::check(value))
5590 value = func();
5591 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
5592 *stream = Fits<unsigned, size>::convert(value);
5593 }
5594
5595 template<typename Functor>
5596 void setValue(VirtualRegister value, Functor func)
5597 {
5598 if (isWide32())
5599 setValue<OpcodeSize::Wide32>(value, func);
5600 else if (isWide16())
5601 setValue<OpcodeSize::Wide16>(value, func);
5602 else
5603 setValue<OpcodeSize::Narrow>(value, func);
5604 }
5605
5606 template <OpcodeSize size, typename Functor>
5607 void setValue(VirtualRegister value, Functor func)
5608 {
5609 if (!Fits<VirtualRegister, size>::check(value))
5610 value = func();
5611 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
5612 *stream = Fits<VirtualRegister, size>::convert(value);
5613 }
5614
5615 template<typename Functor>
5616 void setFlags(PutByIdFlags value, Functor func)
5617 {
5618 if (isWide32())
5619 setFlags<OpcodeSize::Wide32>(value, func);
5620 else if (isWide16())
5621 setFlags<OpcodeSize::Wide16>(value, func);
5622 else
5623 setFlags<OpcodeSize::Narrow>(value, func);
5624 }
5625
5626 template <OpcodeSize size, typename Functor>
5627 void setFlags(PutByIdFlags value, Functor func)
5628 {
5629 if (!Fits<PutByIdFlags, size>::check(value))
5630 value = func();
5631 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
5632 *stream = Fits<PutByIdFlags, size>::convert(value);
5633 }
5634
5635 struct Metadata {
5636 WTF_MAKE_NONCOPYABLE(Metadata);
5637
5638 public:
5639 Metadata(const OpPutById&) { }
5640
5641 StructureID m_oldStructureID;
5642 unsigned m_offset;
5643 StructureID m_newStructureID;
5644 WriteBarrierBase<StructureChain> m_structureChain;
5645 };
5646
5647 Metadata& metadata(CodeBlock* codeBlock) const
5648 {
5649 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
5650 }
5651
5652 Metadata& metadata(ExecState* exec) const
5653 {
5654 return metadata(exec->codeBlock());
5655 }
5656
5657 VirtualRegister m_base;
5658 unsigned m_property;
5659 VirtualRegister m_value;
5660 PutByIdFlags m_flags;
5661 unsigned m_metadataID;
5662};
5663
5664struct OpGetByVal : public Instruction {
5665 static constexpr OpcodeID opcodeID = op_get_by_val;
5666
5667 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
5668 {
5669 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
5670 }
5671
5672 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
5673 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
5674 {
5675 auto __metadataID = gen->addMetadataFor(opcodeID);
5676 return emit<size, shouldAssert>(gen, dst, base, property, __metadataID);
5677 }
5678
5679 template<OpcodeSize size>
5680 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
5681 {
5682 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
5683 return checkImpl<size>(gen, dst, base, property, __metadataID);
5684 }
5685
5686 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
5687 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
5688 {
5689 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID);
5690 if (shouldAssert == Assert)
5691 ASSERT(didEmit);
5692 return didEmit;
5693 }
5694
5695 template<OpcodeSize size>
5696 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
5697 {
5698
5699 auto __metadataID = gen->addMetadataFor(opcodeID);
5700 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
5701 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID))
5702 return;
5703 }
5704 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
5705 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
5706 return;
5707 }
5708 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
5709 }
5710
5711private:
5712 template<OpcodeSize size>
5713 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, unsigned __metadataID)
5714 {
5715 UNUSED_PARAM(gen);
5716#if OS(WINDOWS) && ENABLE(C_LOOP)
5717 // FIXME: Disable wide16 optimization for Windows CLoop
5718 // https://bugs.webkit.org/show_bug.cgi?id=198283
5719 if (size == OpcodeSize::Wide16)
5720 return false;
5721#endif
5722 return Fits<OpcodeID, size>::check(opcodeID)
5723 && Fits<VirtualRegister, size>::check(dst)
5724 && Fits<VirtualRegister, size>::check(base)
5725 && Fits<VirtualRegister, size>::check(property)
5726 && Fits<unsigned, size>::check(__metadataID)
5727 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
5728 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
5729 }
5730
5731 template<OpcodeSize size, bool recordOpcode>
5732 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
5733 {
5734 if (size == OpcodeSize::Wide16)
5735 gen->alignWideOpcode16();
5736 else if (size == OpcodeSize::Wide32)
5737 gen->alignWideOpcode32();
5738 if (checkImpl<size>(gen, dst, base, property, __metadataID)) {
5739 if (recordOpcode)
5740 gen->recordOpcode(opcodeID);
5741 if (size == OpcodeSize::Wide16)
5742 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
5743 else if (size == OpcodeSize::Wide32)
5744 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
5745 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
5746 gen->write(Fits<VirtualRegister, size>::convert(dst));
5747 gen->write(Fits<VirtualRegister, size>::convert(base));
5748 gen->write(Fits<VirtualRegister, size>::convert(property));
5749 gen->write(Fits<unsigned, size>::convert(__metadataID));
5750 return true;
5751 }
5752 return false;
5753 }
5754
5755public:
5756 template<typename Block>
5757 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
5758 {
5759 dumper->printLocationAndOp(__location, &"**get_by_val"[2 - __sizeShiftAmount]);
5760 dumper->dumpOperand(m_dst, true);
5761 dumper->dumpOperand(m_base, false);
5762 dumper->dumpOperand(m_property, false);
5763 }
5764
5765 OpGetByVal(const uint8_t* stream)
5766 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
5767 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
5768 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
5769 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
5770 {
5771 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5772 }
5773
5774 OpGetByVal(const uint16_t* stream)
5775 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
5776 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
5777 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
5778 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
5779 {
5780 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5781 }
5782
5783
5784 OpGetByVal(const uint32_t* stream)
5785 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
5786 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
5787 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
5788 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
5789 {
5790 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5791 }
5792
5793 static OpGetByVal decode(const uint8_t* stream)
5794 {
5795 if (*stream == op_wide32)
5796 return { bitwise_cast<const uint32_t*>(stream + 1) };
5797 if (*stream == op_wide16)
5798 return { bitwise_cast<const uint16_t*>(stream + 1) };
5799 return { stream };
5800 }
5801
5802 template<typename Functor>
5803 void setDst(VirtualRegister value, Functor func)
5804 {
5805 if (isWide32())
5806 setDst<OpcodeSize::Wide32>(value, func);
5807 else if (isWide16())
5808 setDst<OpcodeSize::Wide16>(value, func);
5809 else
5810 setDst<OpcodeSize::Narrow>(value, func);
5811 }
5812
5813 template <OpcodeSize size, typename Functor>
5814 void setDst(VirtualRegister value, Functor func)
5815 {
5816 if (!Fits<VirtualRegister, size>::check(value))
5817 value = func();
5818 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
5819 *stream = Fits<VirtualRegister, size>::convert(value);
5820 }
5821
5822 template<typename Functor>
5823 void setBase(VirtualRegister value, Functor func)
5824 {
5825 if (isWide32())
5826 setBase<OpcodeSize::Wide32>(value, func);
5827 else if (isWide16())
5828 setBase<OpcodeSize::Wide16>(value, func);
5829 else
5830 setBase<OpcodeSize::Narrow>(value, func);
5831 }
5832
5833 template <OpcodeSize size, typename Functor>
5834 void setBase(VirtualRegister value, Functor func)
5835 {
5836 if (!Fits<VirtualRegister, size>::check(value))
5837 value = func();
5838 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
5839 *stream = Fits<VirtualRegister, size>::convert(value);
5840 }
5841
5842 template<typename Functor>
5843 void setProperty(VirtualRegister value, Functor func)
5844 {
5845 if (isWide32())
5846 setProperty<OpcodeSize::Wide32>(value, func);
5847 else if (isWide16())
5848 setProperty<OpcodeSize::Wide16>(value, func);
5849 else
5850 setProperty<OpcodeSize::Narrow>(value, func);
5851 }
5852
5853 template <OpcodeSize size, typename Functor>
5854 void setProperty(VirtualRegister value, Functor func)
5855 {
5856 if (!Fits<VirtualRegister, size>::check(value))
5857 value = func();
5858 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
5859 *stream = Fits<VirtualRegister, size>::convert(value);
5860 }
5861
5862 struct Metadata {
5863 WTF_MAKE_NONCOPYABLE(Metadata);
5864
5865 public:
5866 Metadata(const OpGetByVal&) { }
5867
5868 ValueProfile m_profile;
5869 ArrayProfile m_arrayProfile;
5870 };
5871
5872 Metadata& metadata(CodeBlock* codeBlock) const
5873 {
5874 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
5875 }
5876
5877 Metadata& metadata(ExecState* exec) const
5878 {
5879 return metadata(exec->codeBlock());
5880 }
5881
5882 VirtualRegister m_dst;
5883 VirtualRegister m_base;
5884 VirtualRegister m_property;
5885 unsigned m_metadataID;
5886};
5887
5888struct OpPutByVal : public Instruction {
5889 static constexpr OpcodeID opcodeID = op_put_by_val;
5890
5891 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
5892 {
5893 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, value);
5894 }
5895
5896 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
5897 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
5898 {
5899 auto __metadataID = gen->addMetadataFor(opcodeID);
5900 return emit<size, shouldAssert>(gen, base, property, value, __metadataID);
5901 }
5902
5903 template<OpcodeSize size>
5904 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
5905 {
5906 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
5907 return checkImpl<size>(gen, base, property, value, __metadataID);
5908 }
5909
5910 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
5911 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID)
5912 {
5913 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, __metadataID);
5914 if (shouldAssert == Assert)
5915 ASSERT(didEmit);
5916 return didEmit;
5917 }
5918
5919 template<OpcodeSize size>
5920 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
5921 {
5922
5923 auto __metadataID = gen->addMetadataFor(opcodeID);
5924 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
5925 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, __metadataID))
5926 return;
5927 }
5928 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
5929 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, value, __metadataID))
5930 return;
5931 }
5932 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, value, __metadataID);
5933 }
5934
5935private:
5936 template<OpcodeSize size>
5937 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& value, unsigned __metadataID)
5938 {
5939 UNUSED_PARAM(gen);
5940#if OS(WINDOWS) && ENABLE(C_LOOP)
5941 // FIXME: Disable wide16 optimization for Windows CLoop
5942 // https://bugs.webkit.org/show_bug.cgi?id=198283
5943 if (size == OpcodeSize::Wide16)
5944 return false;
5945#endif
5946 return Fits<OpcodeID, size>::check(opcodeID)
5947 && Fits<VirtualRegister, size>::check(base)
5948 && Fits<VirtualRegister, size>::check(property)
5949 && Fits<VirtualRegister, size>::check(value)
5950 && Fits<unsigned, size>::check(__metadataID)
5951 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
5952 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
5953 }
5954
5955 template<OpcodeSize size, bool recordOpcode>
5956 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID)
5957 {
5958 if (size == OpcodeSize::Wide16)
5959 gen->alignWideOpcode16();
5960 else if (size == OpcodeSize::Wide32)
5961 gen->alignWideOpcode32();
5962 if (checkImpl<size>(gen, base, property, value, __metadataID)) {
5963 if (recordOpcode)
5964 gen->recordOpcode(opcodeID);
5965 if (size == OpcodeSize::Wide16)
5966 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
5967 else if (size == OpcodeSize::Wide32)
5968 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
5969 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
5970 gen->write(Fits<VirtualRegister, size>::convert(base));
5971 gen->write(Fits<VirtualRegister, size>::convert(property));
5972 gen->write(Fits<VirtualRegister, size>::convert(value));
5973 gen->write(Fits<unsigned, size>::convert(__metadataID));
5974 return true;
5975 }
5976 return false;
5977 }
5978
5979public:
5980 template<typename Block>
5981 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
5982 {
5983 dumper->printLocationAndOp(__location, &"**put_by_val"[2 - __sizeShiftAmount]);
5984 dumper->dumpOperand(m_base, true);
5985 dumper->dumpOperand(m_property, false);
5986 dumper->dumpOperand(m_value, false);
5987 }
5988
5989 OpPutByVal(const uint8_t* stream)
5990 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
5991 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
5992 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
5993 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
5994 {
5995 ASSERT_UNUSED(stream, stream[0] == opcodeID);
5996 }
5997
5998 OpPutByVal(const uint16_t* stream)
5999 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
6000 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
6001 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
6002 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
6003 {
6004 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6005 }
6006
6007
6008 OpPutByVal(const uint32_t* stream)
6009 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
6010 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
6011 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
6012 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
6013 {
6014 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6015 }
6016
6017 static OpPutByVal decode(const uint8_t* stream)
6018 {
6019 if (*stream == op_wide32)
6020 return { bitwise_cast<const uint32_t*>(stream + 1) };
6021 if (*stream == op_wide16)
6022 return { bitwise_cast<const uint16_t*>(stream + 1) };
6023 return { stream };
6024 }
6025
6026 template<typename Functor>
6027 void setBase(VirtualRegister value, Functor func)
6028 {
6029 if (isWide32())
6030 setBase<OpcodeSize::Wide32>(value, func);
6031 else if (isWide16())
6032 setBase<OpcodeSize::Wide16>(value, func);
6033 else
6034 setBase<OpcodeSize::Narrow>(value, func);
6035 }
6036
6037 template <OpcodeSize size, typename Functor>
6038 void setBase(VirtualRegister value, Functor func)
6039 {
6040 if (!Fits<VirtualRegister, size>::check(value))
6041 value = func();
6042 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
6043 *stream = Fits<VirtualRegister, size>::convert(value);
6044 }
6045
6046 template<typename Functor>
6047 void setProperty(VirtualRegister value, Functor func)
6048 {
6049 if (isWide32())
6050 setProperty<OpcodeSize::Wide32>(value, func);
6051 else if (isWide16())
6052 setProperty<OpcodeSize::Wide16>(value, func);
6053 else
6054 setProperty<OpcodeSize::Narrow>(value, func);
6055 }
6056
6057 template <OpcodeSize size, typename Functor>
6058 void setProperty(VirtualRegister value, Functor func)
6059 {
6060 if (!Fits<VirtualRegister, size>::check(value))
6061 value = func();
6062 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
6063 *stream = Fits<VirtualRegister, size>::convert(value);
6064 }
6065
6066 template<typename Functor>
6067 void setValue(VirtualRegister value, Functor func)
6068 {
6069 if (isWide32())
6070 setValue<OpcodeSize::Wide32>(value, func);
6071 else if (isWide16())
6072 setValue<OpcodeSize::Wide16>(value, func);
6073 else
6074 setValue<OpcodeSize::Narrow>(value, func);
6075 }
6076
6077 template <OpcodeSize size, typename Functor>
6078 void setValue(VirtualRegister value, Functor func)
6079 {
6080 if (!Fits<VirtualRegister, size>::check(value))
6081 value = func();
6082 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
6083 *stream = Fits<VirtualRegister, size>::convert(value);
6084 }
6085
6086 struct Metadata {
6087 WTF_MAKE_NONCOPYABLE(Metadata);
6088
6089 public:
6090 Metadata(const OpPutByVal&) { }
6091
6092 ArrayProfile m_arrayProfile;
6093 };
6094
6095 Metadata& metadata(CodeBlock* codeBlock) const
6096 {
6097 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
6098 }
6099
6100 Metadata& metadata(ExecState* exec) const
6101 {
6102 return metadata(exec->codeBlock());
6103 }
6104
6105 VirtualRegister m_base;
6106 VirtualRegister m_property;
6107 VirtualRegister m_value;
6108 unsigned m_metadataID;
6109};
6110
6111struct OpPutByValDirect : public Instruction {
6112 static constexpr OpcodeID opcodeID = op_put_by_val_direct;
6113
6114 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
6115 {
6116 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, value);
6117 }
6118
6119 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
6120 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
6121 {
6122 auto __metadataID = gen->addMetadataFor(opcodeID);
6123 return emit<size, shouldAssert>(gen, base, property, value, __metadataID);
6124 }
6125
6126 template<OpcodeSize size>
6127 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
6128 {
6129 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
6130 return checkImpl<size>(gen, base, property, value, __metadataID);
6131 }
6132
6133 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
6134 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID)
6135 {
6136 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, __metadataID);
6137 if (shouldAssert == Assert)
6138 ASSERT(didEmit);
6139 return didEmit;
6140 }
6141
6142 template<OpcodeSize size>
6143 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value)
6144 {
6145
6146 auto __metadataID = gen->addMetadataFor(opcodeID);
6147 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
6148 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, __metadataID))
6149 return;
6150 }
6151 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
6152 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, value, __metadataID))
6153 return;
6154 }
6155 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, value, __metadataID);
6156 }
6157
6158private:
6159 template<OpcodeSize size>
6160 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& value, unsigned __metadataID)
6161 {
6162 UNUSED_PARAM(gen);
6163#if OS(WINDOWS) && ENABLE(C_LOOP)
6164 // FIXME: Disable wide16 optimization for Windows CLoop
6165 // https://bugs.webkit.org/show_bug.cgi?id=198283
6166 if (size == OpcodeSize::Wide16)
6167 return false;
6168#endif
6169 return Fits<OpcodeID, size>::check(opcodeID)
6170 && Fits<VirtualRegister, size>::check(base)
6171 && Fits<VirtualRegister, size>::check(property)
6172 && Fits<VirtualRegister, size>::check(value)
6173 && Fits<unsigned, size>::check(__metadataID)
6174 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
6175 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
6176 }
6177
6178 template<OpcodeSize size, bool recordOpcode>
6179 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID)
6180 {
6181 if (size == OpcodeSize::Wide16)
6182 gen->alignWideOpcode16();
6183 else if (size == OpcodeSize::Wide32)
6184 gen->alignWideOpcode32();
6185 if (checkImpl<size>(gen, base, property, value, __metadataID)) {
6186 if (recordOpcode)
6187 gen->recordOpcode(opcodeID);
6188 if (size == OpcodeSize::Wide16)
6189 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
6190 else if (size == OpcodeSize::Wide32)
6191 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
6192 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
6193 gen->write(Fits<VirtualRegister, size>::convert(base));
6194 gen->write(Fits<VirtualRegister, size>::convert(property));
6195 gen->write(Fits<VirtualRegister, size>::convert(value));
6196 gen->write(Fits<unsigned, size>::convert(__metadataID));
6197 return true;
6198 }
6199 return false;
6200 }
6201
6202public:
6203 template<typename Block>
6204 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
6205 {
6206 dumper->printLocationAndOp(__location, &"**put_by_val_direct"[2 - __sizeShiftAmount]);
6207 dumper->dumpOperand(m_base, true);
6208 dumper->dumpOperand(m_property, false);
6209 dumper->dumpOperand(m_value, false);
6210 }
6211
6212 OpPutByValDirect(const uint8_t* stream)
6213 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
6214 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
6215 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
6216 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
6217 {
6218 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6219 }
6220
6221 OpPutByValDirect(const uint16_t* stream)
6222 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
6223 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
6224 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
6225 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
6226 {
6227 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6228 }
6229
6230
6231 OpPutByValDirect(const uint32_t* stream)
6232 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
6233 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
6234 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
6235 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
6236 {
6237 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6238 }
6239
6240 static OpPutByValDirect decode(const uint8_t* stream)
6241 {
6242 if (*stream == op_wide32)
6243 return { bitwise_cast<const uint32_t*>(stream + 1) };
6244 if (*stream == op_wide16)
6245 return { bitwise_cast<const uint16_t*>(stream + 1) };
6246 return { stream };
6247 }
6248
6249 template<typename Functor>
6250 void setBase(VirtualRegister value, Functor func)
6251 {
6252 if (isWide32())
6253 setBase<OpcodeSize::Wide32>(value, func);
6254 else if (isWide16())
6255 setBase<OpcodeSize::Wide16>(value, func);
6256 else
6257 setBase<OpcodeSize::Narrow>(value, func);
6258 }
6259
6260 template <OpcodeSize size, typename Functor>
6261 void setBase(VirtualRegister value, Functor func)
6262 {
6263 if (!Fits<VirtualRegister, size>::check(value))
6264 value = func();
6265 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
6266 *stream = Fits<VirtualRegister, size>::convert(value);
6267 }
6268
6269 template<typename Functor>
6270 void setProperty(VirtualRegister value, Functor func)
6271 {
6272 if (isWide32())
6273 setProperty<OpcodeSize::Wide32>(value, func);
6274 else if (isWide16())
6275 setProperty<OpcodeSize::Wide16>(value, func);
6276 else
6277 setProperty<OpcodeSize::Narrow>(value, func);
6278 }
6279
6280 template <OpcodeSize size, typename Functor>
6281 void setProperty(VirtualRegister value, Functor func)
6282 {
6283 if (!Fits<VirtualRegister, size>::check(value))
6284 value = func();
6285 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
6286 *stream = Fits<VirtualRegister, size>::convert(value);
6287 }
6288
6289 template<typename Functor>
6290 void setValue(VirtualRegister value, Functor func)
6291 {
6292 if (isWide32())
6293 setValue<OpcodeSize::Wide32>(value, func);
6294 else if (isWide16())
6295 setValue<OpcodeSize::Wide16>(value, func);
6296 else
6297 setValue<OpcodeSize::Narrow>(value, func);
6298 }
6299
6300 template <OpcodeSize size, typename Functor>
6301 void setValue(VirtualRegister value, Functor func)
6302 {
6303 if (!Fits<VirtualRegister, size>::check(value))
6304 value = func();
6305 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
6306 *stream = Fits<VirtualRegister, size>::convert(value);
6307 }
6308
6309 struct Metadata {
6310 WTF_MAKE_NONCOPYABLE(Metadata);
6311
6312 public:
6313 Metadata(const OpPutByValDirect&) { }
6314
6315 ArrayProfile m_arrayProfile;
6316 };
6317
6318 Metadata& metadata(CodeBlock* codeBlock) const
6319 {
6320 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
6321 }
6322
6323 Metadata& metadata(ExecState* exec) const
6324 {
6325 return metadata(exec->codeBlock());
6326 }
6327
6328 VirtualRegister m_base;
6329 VirtualRegister m_property;
6330 VirtualRegister m_value;
6331 unsigned m_metadataID;
6332};
6333
6334struct OpJneqPtr : public Instruction {
6335 static constexpr OpcodeID opcodeID = op_jneq_ptr;
6336
6337 static void emit(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel)
6338 {
6339 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, value, specialPointer, targetLabel);
6340 }
6341
6342 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
6343 static bool emit(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel)
6344 {
6345 auto __metadataID = gen->addMetadataFor(opcodeID);
6346 return emit<size, shouldAssert>(gen, value, specialPointer, targetLabel, __metadataID);
6347 }
6348
6349 template<OpcodeSize size>
6350 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel)
6351 {
6352 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
6353 return checkImpl<size>(gen, value, specialPointer, targetLabel, __metadataID);
6354 }
6355
6356 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
6357 static bool emit(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel, unsigned __metadataID)
6358 {
6359 bool didEmit = emitImpl<size, recordOpcode>(gen, value, specialPointer, targetLabel, __metadataID);
6360 if (shouldAssert == Assert)
6361 ASSERT(didEmit);
6362 return didEmit;
6363 }
6364
6365 template<OpcodeSize size>
6366 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel)
6367 {
6368
6369 auto __metadataID = gen->addMetadataFor(opcodeID);
6370 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
6371 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, specialPointer, targetLabel, __metadataID))
6372 return;
6373 }
6374 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
6375 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value, specialPointer, targetLabel, __metadataID))
6376 return;
6377 }
6378 emit<OpcodeSize::Wide32, Assert, true>(gen, value, specialPointer, targetLabel, __metadataID);
6379 }
6380
6381private:
6382 template<OpcodeSize size>
6383 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, Special::Pointer& specialPointer, BoundLabel& targetLabel, unsigned __metadataID)
6384 {
6385 UNUSED_PARAM(gen);
6386#if OS(WINDOWS) && ENABLE(C_LOOP)
6387 // FIXME: Disable wide16 optimization for Windows CLoop
6388 // https://bugs.webkit.org/show_bug.cgi?id=198283
6389 if (size == OpcodeSize::Wide16)
6390 return false;
6391#endif
6392 return Fits<OpcodeID, size>::check(opcodeID)
6393 && Fits<VirtualRegister, size>::check(value)
6394 && Fits<Special::Pointer, size>::check(specialPointer)
6395 && Fits<BoundLabel, size>::check(targetLabel)
6396 && Fits<unsigned, size>::check(__metadataID)
6397 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
6398 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
6399 }
6400
6401 template<OpcodeSize size, bool recordOpcode>
6402 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer specialPointer, BoundLabel targetLabel, unsigned __metadataID)
6403 {
6404 if (size == OpcodeSize::Wide16)
6405 gen->alignWideOpcode16();
6406 else if (size == OpcodeSize::Wide32)
6407 gen->alignWideOpcode32();
6408 if (checkImpl<size>(gen, value, specialPointer, targetLabel, __metadataID)) {
6409 if (recordOpcode)
6410 gen->recordOpcode(opcodeID);
6411 if (size == OpcodeSize::Wide16)
6412 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
6413 else if (size == OpcodeSize::Wide32)
6414 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
6415 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
6416 gen->write(Fits<VirtualRegister, size>::convert(value));
6417 gen->write(Fits<Special::Pointer, size>::convert(specialPointer));
6418 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
6419 gen->write(Fits<unsigned, size>::convert(__metadataID));
6420 return true;
6421 }
6422 return false;
6423 }
6424
6425public:
6426 template<typename Block>
6427 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
6428 {
6429 dumper->printLocationAndOp(__location, &"**jneq_ptr"[2 - __sizeShiftAmount]);
6430 dumper->dumpOperand(m_value, true);
6431 dumper->dumpOperand(m_specialPointer, false);
6432 dumper->dumpOperand(m_targetLabel, false);
6433 }
6434
6435 OpJneqPtr(const uint8_t* stream)
6436 : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
6437 , m_specialPointer(Fits<Special::Pointer, OpcodeSize::Narrow>::convert(stream[2]))
6438 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
6439 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
6440 {
6441 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6442 }
6443
6444 OpJneqPtr(const uint16_t* stream)
6445 : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
6446 , m_specialPointer(Fits<Special::Pointer, OpcodeSize::Wide16>::convert(stream[2]))
6447 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
6448 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
6449 {
6450 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6451 }
6452
6453
6454 OpJneqPtr(const uint32_t* stream)
6455 : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
6456 , m_specialPointer(Fits<Special::Pointer, OpcodeSize::Wide32>::convert(stream[2]))
6457 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
6458 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
6459 {
6460 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6461 }
6462
6463 static OpJneqPtr decode(const uint8_t* stream)
6464 {
6465 if (*stream == op_wide32)
6466 return { bitwise_cast<const uint32_t*>(stream + 1) };
6467 if (*stream == op_wide16)
6468 return { bitwise_cast<const uint16_t*>(stream + 1) };
6469 return { stream };
6470 }
6471
6472 template<typename Functor>
6473 void setValue(VirtualRegister value, Functor func)
6474 {
6475 if (isWide32())
6476 setValue<OpcodeSize::Wide32>(value, func);
6477 else if (isWide16())
6478 setValue<OpcodeSize::Wide16>(value, func);
6479 else
6480 setValue<OpcodeSize::Narrow>(value, func);
6481 }
6482
6483 template <OpcodeSize size, typename Functor>
6484 void setValue(VirtualRegister value, Functor func)
6485 {
6486 if (!Fits<VirtualRegister, size>::check(value))
6487 value = func();
6488 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
6489 *stream = Fits<VirtualRegister, size>::convert(value);
6490 }
6491
6492 template<typename Functor>
6493 void setSpecialPointer(Special::Pointer value, Functor func)
6494 {
6495 if (isWide32())
6496 setSpecialPointer<OpcodeSize::Wide32>(value, func);
6497 else if (isWide16())
6498 setSpecialPointer<OpcodeSize::Wide16>(value, func);
6499 else
6500 setSpecialPointer<OpcodeSize::Narrow>(value, func);
6501 }
6502
6503 template <OpcodeSize size, typename Functor>
6504 void setSpecialPointer(Special::Pointer value, Functor func)
6505 {
6506 if (!Fits<Special::Pointer, size>::check(value))
6507 value = func();
6508 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
6509 *stream = Fits<Special::Pointer, size>::convert(value);
6510 }
6511
6512 template<typename Functor>
6513 void setTargetLabel(BoundLabel value, Functor func)
6514 {
6515 if (isWide32())
6516 setTargetLabel<OpcodeSize::Wide32>(value, func);
6517 else if (isWide16())
6518 setTargetLabel<OpcodeSize::Wide16>(value, func);
6519 else
6520 setTargetLabel<OpcodeSize::Narrow>(value, func);
6521 }
6522
6523 template <OpcodeSize size, typename Functor>
6524 void setTargetLabel(BoundLabel value, Functor func)
6525 {
6526 if (!Fits<BoundLabel, size>::check(value))
6527 value = func();
6528 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
6529 *stream = Fits<BoundLabel, size>::convert(value);
6530 }
6531
6532 struct Metadata {
6533 WTF_MAKE_NONCOPYABLE(Metadata);
6534
6535 public:
6536 Metadata(const OpJneqPtr&) { }
6537
6538 bool m_hasJumped;
6539 };
6540
6541 Metadata& metadata(CodeBlock* codeBlock) const
6542 {
6543 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
6544 }
6545
6546 Metadata& metadata(ExecState* exec) const
6547 {
6548 return metadata(exec->codeBlock());
6549 }
6550
6551 VirtualRegister m_value;
6552 Special::Pointer m_specialPointer;
6553 BoundLabel m_targetLabel;
6554 unsigned m_metadataID;
6555};
6556
6557struct OpCall : public Instruction {
6558 static constexpr OpcodeID opcodeID = op_call;
6559
6560 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6561 {
6562 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, argc, argv);
6563 }
6564
6565 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
6566 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6567 {
6568 auto __metadataID = gen->addMetadataFor(opcodeID);
6569 return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID);
6570 }
6571
6572 template<OpcodeSize size>
6573 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6574 {
6575 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
6576 return checkImpl<size>(gen, dst, callee, argc, argv, __metadataID);
6577 }
6578
6579 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
6580 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
6581 {
6582 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID);
6583 if (shouldAssert == Assert)
6584 ASSERT(didEmit);
6585 return didEmit;
6586 }
6587
6588 template<OpcodeSize size>
6589 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6590 {
6591
6592 auto __metadataID = gen->addMetadataFor(opcodeID);
6593 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
6594 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
6595 return;
6596 }
6597 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
6598 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
6599 return;
6600 }
6601 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
6602 }
6603
6604private:
6605 template<OpcodeSize size>
6606 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, unsigned __metadataID)
6607 {
6608 UNUSED_PARAM(gen);
6609#if OS(WINDOWS) && ENABLE(C_LOOP)
6610 // FIXME: Disable wide16 optimization for Windows CLoop
6611 // https://bugs.webkit.org/show_bug.cgi?id=198283
6612 if (size == OpcodeSize::Wide16)
6613 return false;
6614#endif
6615 return Fits<OpcodeID, size>::check(opcodeID)
6616 && Fits<VirtualRegister, size>::check(dst)
6617 && Fits<VirtualRegister, size>::check(callee)
6618 && Fits<unsigned, size>::check(argc)
6619 && Fits<unsigned, size>::check(argv)
6620 && Fits<unsigned, size>::check(__metadataID)
6621 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
6622 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
6623 }
6624
6625 template<OpcodeSize size, bool recordOpcode>
6626 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
6627 {
6628 if (size == OpcodeSize::Wide16)
6629 gen->alignWideOpcode16();
6630 else if (size == OpcodeSize::Wide32)
6631 gen->alignWideOpcode32();
6632 if (checkImpl<size>(gen, dst, callee, argc, argv, __metadataID)) {
6633 if (recordOpcode)
6634 gen->recordOpcode(opcodeID);
6635 if (size == OpcodeSize::Wide16)
6636 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
6637 else if (size == OpcodeSize::Wide32)
6638 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
6639 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
6640 gen->write(Fits<VirtualRegister, size>::convert(dst));
6641 gen->write(Fits<VirtualRegister, size>::convert(callee));
6642 gen->write(Fits<unsigned, size>::convert(argc));
6643 gen->write(Fits<unsigned, size>::convert(argv));
6644 gen->write(Fits<unsigned, size>::convert(__metadataID));
6645 return true;
6646 }
6647 return false;
6648 }
6649
6650public:
6651 template<typename Block>
6652 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
6653 {
6654 dumper->printLocationAndOp(__location, &"**call"[2 - __sizeShiftAmount]);
6655 dumper->dumpOperand(m_dst, true);
6656 dumper->dumpOperand(m_callee, false);
6657 dumper->dumpOperand(m_argc, false);
6658 dumper->dumpOperand(m_argv, false);
6659 }
6660
6661 OpCall(const uint8_t* stream)
6662 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
6663 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
6664 , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
6665 , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
6666 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
6667 {
6668 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6669 }
6670
6671 OpCall(const uint16_t* stream)
6672 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
6673 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
6674 , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
6675 , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
6676 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
6677 {
6678 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6679 }
6680
6681
6682 OpCall(const uint32_t* stream)
6683 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
6684 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
6685 , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
6686 , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
6687 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
6688 {
6689 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6690 }
6691
6692 static OpCall decode(const uint8_t* stream)
6693 {
6694 if (*stream == op_wide32)
6695 return { bitwise_cast<const uint32_t*>(stream + 1) };
6696 if (*stream == op_wide16)
6697 return { bitwise_cast<const uint16_t*>(stream + 1) };
6698 return { stream };
6699 }
6700
6701 template<typename Functor>
6702 void setDst(VirtualRegister value, Functor func)
6703 {
6704 if (isWide32())
6705 setDst<OpcodeSize::Wide32>(value, func);
6706 else if (isWide16())
6707 setDst<OpcodeSize::Wide16>(value, func);
6708 else
6709 setDst<OpcodeSize::Narrow>(value, func);
6710 }
6711
6712 template <OpcodeSize size, typename Functor>
6713 void setDst(VirtualRegister value, Functor func)
6714 {
6715 if (!Fits<VirtualRegister, size>::check(value))
6716 value = func();
6717 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
6718 *stream = Fits<VirtualRegister, size>::convert(value);
6719 }
6720
6721 template<typename Functor>
6722 void setCallee(VirtualRegister value, Functor func)
6723 {
6724 if (isWide32())
6725 setCallee<OpcodeSize::Wide32>(value, func);
6726 else if (isWide16())
6727 setCallee<OpcodeSize::Wide16>(value, func);
6728 else
6729 setCallee<OpcodeSize::Narrow>(value, func);
6730 }
6731
6732 template <OpcodeSize size, typename Functor>
6733 void setCallee(VirtualRegister value, Functor func)
6734 {
6735 if (!Fits<VirtualRegister, size>::check(value))
6736 value = func();
6737 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
6738 *stream = Fits<VirtualRegister, size>::convert(value);
6739 }
6740
6741 template<typename Functor>
6742 void setArgc(unsigned value, Functor func)
6743 {
6744 if (isWide32())
6745 setArgc<OpcodeSize::Wide32>(value, func);
6746 else if (isWide16())
6747 setArgc<OpcodeSize::Wide16>(value, func);
6748 else
6749 setArgc<OpcodeSize::Narrow>(value, func);
6750 }
6751
6752 template <OpcodeSize size, typename Functor>
6753 void setArgc(unsigned value, Functor func)
6754 {
6755 if (!Fits<unsigned, size>::check(value))
6756 value = func();
6757 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
6758 *stream = Fits<unsigned, size>::convert(value);
6759 }
6760
6761 template<typename Functor>
6762 void setArgv(unsigned value, Functor func)
6763 {
6764 if (isWide32())
6765 setArgv<OpcodeSize::Wide32>(value, func);
6766 else if (isWide16())
6767 setArgv<OpcodeSize::Wide16>(value, func);
6768 else
6769 setArgv<OpcodeSize::Narrow>(value, func);
6770 }
6771
6772 template <OpcodeSize size, typename Functor>
6773 void setArgv(unsigned value, Functor func)
6774 {
6775 if (!Fits<unsigned, size>::check(value))
6776 value = func();
6777 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
6778 *stream = Fits<unsigned, size>::convert(value);
6779 }
6780
6781 struct Metadata {
6782 WTF_MAKE_NONCOPYABLE(Metadata);
6783
6784 public:
6785 Metadata(const OpCall&) { }
6786
6787 LLIntCallLinkInfo m_callLinkInfo;
6788 ValueProfile m_profile;
6789 };
6790
6791 Metadata& metadata(CodeBlock* codeBlock) const
6792 {
6793 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
6794 }
6795
6796 Metadata& metadata(ExecState* exec) const
6797 {
6798 return metadata(exec->codeBlock());
6799 }
6800
6801 VirtualRegister m_dst;
6802 VirtualRegister m_callee;
6803 unsigned m_argc;
6804 unsigned m_argv;
6805 unsigned m_metadataID;
6806};
6807
6808struct OpTailCall : public Instruction {
6809 static constexpr OpcodeID opcodeID = op_tail_call;
6810
6811 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6812 {
6813 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, argc, argv);
6814 }
6815
6816 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
6817 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6818 {
6819 auto __metadataID = gen->addMetadataFor(opcodeID);
6820 return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID);
6821 }
6822
6823 template<OpcodeSize size>
6824 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6825 {
6826 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
6827 return checkImpl<size>(gen, dst, callee, argc, argv, __metadataID);
6828 }
6829
6830 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
6831 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
6832 {
6833 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID);
6834 if (shouldAssert == Assert)
6835 ASSERT(didEmit);
6836 return didEmit;
6837 }
6838
6839 template<OpcodeSize size>
6840 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
6841 {
6842
6843 auto __metadataID = gen->addMetadataFor(opcodeID);
6844 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
6845 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
6846 return;
6847 }
6848 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
6849 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
6850 return;
6851 }
6852 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
6853 }
6854
6855private:
6856 template<OpcodeSize size>
6857 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, unsigned __metadataID)
6858 {
6859 UNUSED_PARAM(gen);
6860#if OS(WINDOWS) && ENABLE(C_LOOP)
6861 // FIXME: Disable wide16 optimization for Windows CLoop
6862 // https://bugs.webkit.org/show_bug.cgi?id=198283
6863 if (size == OpcodeSize::Wide16)
6864 return false;
6865#endif
6866 return Fits<OpcodeID, size>::check(opcodeID)
6867 && Fits<VirtualRegister, size>::check(dst)
6868 && Fits<VirtualRegister, size>::check(callee)
6869 && Fits<unsigned, size>::check(argc)
6870 && Fits<unsigned, size>::check(argv)
6871 && Fits<unsigned, size>::check(__metadataID)
6872 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
6873 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
6874 }
6875
6876 template<OpcodeSize size, bool recordOpcode>
6877 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
6878 {
6879 if (size == OpcodeSize::Wide16)
6880 gen->alignWideOpcode16();
6881 else if (size == OpcodeSize::Wide32)
6882 gen->alignWideOpcode32();
6883 if (checkImpl<size>(gen, dst, callee, argc, argv, __metadataID)) {
6884 if (recordOpcode)
6885 gen->recordOpcode(opcodeID);
6886 if (size == OpcodeSize::Wide16)
6887 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
6888 else if (size == OpcodeSize::Wide32)
6889 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
6890 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
6891 gen->write(Fits<VirtualRegister, size>::convert(dst));
6892 gen->write(Fits<VirtualRegister, size>::convert(callee));
6893 gen->write(Fits<unsigned, size>::convert(argc));
6894 gen->write(Fits<unsigned, size>::convert(argv));
6895 gen->write(Fits<unsigned, size>::convert(__metadataID));
6896 return true;
6897 }
6898 return false;
6899 }
6900
6901public:
6902 template<typename Block>
6903 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
6904 {
6905 dumper->printLocationAndOp(__location, &"**tail_call"[2 - __sizeShiftAmount]);
6906 dumper->dumpOperand(m_dst, true);
6907 dumper->dumpOperand(m_callee, false);
6908 dumper->dumpOperand(m_argc, false);
6909 dumper->dumpOperand(m_argv, false);
6910 }
6911
6912 OpTailCall(const uint8_t* stream)
6913 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
6914 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
6915 , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
6916 , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
6917 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
6918 {
6919 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6920 }
6921
6922 OpTailCall(const uint16_t* stream)
6923 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
6924 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
6925 , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
6926 , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
6927 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
6928 {
6929 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6930 }
6931
6932
6933 OpTailCall(const uint32_t* stream)
6934 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
6935 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
6936 , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
6937 , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
6938 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
6939 {
6940 ASSERT_UNUSED(stream, stream[0] == opcodeID);
6941 }
6942
6943 static OpTailCall decode(const uint8_t* stream)
6944 {
6945 if (*stream == op_wide32)
6946 return { bitwise_cast<const uint32_t*>(stream + 1) };
6947 if (*stream == op_wide16)
6948 return { bitwise_cast<const uint16_t*>(stream + 1) };
6949 return { stream };
6950 }
6951
6952 template<typename Functor>
6953 void setDst(VirtualRegister value, Functor func)
6954 {
6955 if (isWide32())
6956 setDst<OpcodeSize::Wide32>(value, func);
6957 else if (isWide16())
6958 setDst<OpcodeSize::Wide16>(value, func);
6959 else
6960 setDst<OpcodeSize::Narrow>(value, func);
6961 }
6962
6963 template <OpcodeSize size, typename Functor>
6964 void setDst(VirtualRegister value, Functor func)
6965 {
6966 if (!Fits<VirtualRegister, size>::check(value))
6967 value = func();
6968 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
6969 *stream = Fits<VirtualRegister, size>::convert(value);
6970 }
6971
6972 template<typename Functor>
6973 void setCallee(VirtualRegister value, Functor func)
6974 {
6975 if (isWide32())
6976 setCallee<OpcodeSize::Wide32>(value, func);
6977 else if (isWide16())
6978 setCallee<OpcodeSize::Wide16>(value, func);
6979 else
6980 setCallee<OpcodeSize::Narrow>(value, func);
6981 }
6982
6983 template <OpcodeSize size, typename Functor>
6984 void setCallee(VirtualRegister value, Functor func)
6985 {
6986 if (!Fits<VirtualRegister, size>::check(value))
6987 value = func();
6988 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
6989 *stream = Fits<VirtualRegister, size>::convert(value);
6990 }
6991
6992 template<typename Functor>
6993 void setArgc(unsigned value, Functor func)
6994 {
6995 if (isWide32())
6996 setArgc<OpcodeSize::Wide32>(value, func);
6997 else if (isWide16())
6998 setArgc<OpcodeSize::Wide16>(value, func);
6999 else
7000 setArgc<OpcodeSize::Narrow>(value, func);
7001 }
7002
7003 template <OpcodeSize size, typename Functor>
7004 void setArgc(unsigned value, Functor func)
7005 {
7006 if (!Fits<unsigned, size>::check(value))
7007 value = func();
7008 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
7009 *stream = Fits<unsigned, size>::convert(value);
7010 }
7011
7012 template<typename Functor>
7013 void setArgv(unsigned value, Functor func)
7014 {
7015 if (isWide32())
7016 setArgv<OpcodeSize::Wide32>(value, func);
7017 else if (isWide16())
7018 setArgv<OpcodeSize::Wide16>(value, func);
7019 else
7020 setArgv<OpcodeSize::Narrow>(value, func);
7021 }
7022
7023 template <OpcodeSize size, typename Functor>
7024 void setArgv(unsigned value, Functor func)
7025 {
7026 if (!Fits<unsigned, size>::check(value))
7027 value = func();
7028 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
7029 *stream = Fits<unsigned, size>::convert(value);
7030 }
7031
7032 struct Metadata {
7033 WTF_MAKE_NONCOPYABLE(Metadata);
7034
7035 public:
7036 Metadata(const OpTailCall&) { }
7037
7038 LLIntCallLinkInfo m_callLinkInfo;
7039 ValueProfile m_profile;
7040 };
7041
7042 Metadata& metadata(CodeBlock* codeBlock) const
7043 {
7044 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
7045 }
7046
7047 Metadata& metadata(ExecState* exec) const
7048 {
7049 return metadata(exec->codeBlock());
7050 }
7051
7052 VirtualRegister m_dst;
7053 VirtualRegister m_callee;
7054 unsigned m_argc;
7055 unsigned m_argv;
7056 unsigned m_metadataID;
7057};
7058
7059struct OpCallEval : public Instruction {
7060 static constexpr OpcodeID opcodeID = op_call_eval;
7061
7062 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
7063 {
7064 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, argc, argv);
7065 }
7066
7067 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
7068 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
7069 {
7070 auto __metadataID = gen->addMetadataFor(opcodeID);
7071 return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID);
7072 }
7073
7074 template<OpcodeSize size>
7075 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
7076 {
7077 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
7078 return checkImpl<size>(gen, dst, callee, argc, argv, __metadataID);
7079 }
7080
7081 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
7082 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
7083 {
7084 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID);
7085 if (shouldAssert == Assert)
7086 ASSERT(didEmit);
7087 return didEmit;
7088 }
7089
7090 template<OpcodeSize size>
7091 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
7092 {
7093
7094 auto __metadataID = gen->addMetadataFor(opcodeID);
7095 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
7096 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
7097 return;
7098 }
7099 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
7100 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
7101 return;
7102 }
7103 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
7104 }
7105
7106private:
7107 template<OpcodeSize size>
7108 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, unsigned __metadataID)
7109 {
7110 UNUSED_PARAM(gen);
7111#if OS(WINDOWS) && ENABLE(C_LOOP)
7112 // FIXME: Disable wide16 optimization for Windows CLoop
7113 // https://bugs.webkit.org/show_bug.cgi?id=198283
7114 if (size == OpcodeSize::Wide16)
7115 return false;
7116#endif
7117 return Fits<OpcodeID, size>::check(opcodeID)
7118 && Fits<VirtualRegister, size>::check(dst)
7119 && Fits<VirtualRegister, size>::check(callee)
7120 && Fits<unsigned, size>::check(argc)
7121 && Fits<unsigned, size>::check(argv)
7122 && Fits<unsigned, size>::check(__metadataID)
7123 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
7124 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
7125 }
7126
7127 template<OpcodeSize size, bool recordOpcode>
7128 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
7129 {
7130 if (size == OpcodeSize::Wide16)
7131 gen->alignWideOpcode16();
7132 else if (size == OpcodeSize::Wide32)
7133 gen->alignWideOpcode32();
7134 if (checkImpl<size>(gen, dst, callee, argc, argv, __metadataID)) {
7135 if (recordOpcode)
7136 gen->recordOpcode(opcodeID);
7137 if (size == OpcodeSize::Wide16)
7138 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
7139 else if (size == OpcodeSize::Wide32)
7140 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
7141 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
7142 gen->write(Fits<VirtualRegister, size>::convert(dst));
7143 gen->write(Fits<VirtualRegister, size>::convert(callee));
7144 gen->write(Fits<unsigned, size>::convert(argc));
7145 gen->write(Fits<unsigned, size>::convert(argv));
7146 gen->write(Fits<unsigned, size>::convert(__metadataID));
7147 return true;
7148 }
7149 return false;
7150 }
7151
7152public:
7153 template<typename Block>
7154 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
7155 {
7156 dumper->printLocationAndOp(__location, &"**call_eval"[2 - __sizeShiftAmount]);
7157 dumper->dumpOperand(m_dst, true);
7158 dumper->dumpOperand(m_callee, false);
7159 dumper->dumpOperand(m_argc, false);
7160 dumper->dumpOperand(m_argv, false);
7161 }
7162
7163 OpCallEval(const uint8_t* stream)
7164 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
7165 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
7166 , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
7167 , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
7168 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
7169 {
7170 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7171 }
7172
7173 OpCallEval(const uint16_t* stream)
7174 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
7175 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
7176 , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
7177 , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
7178 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
7179 {
7180 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7181 }
7182
7183
7184 OpCallEval(const uint32_t* stream)
7185 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
7186 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
7187 , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
7188 , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
7189 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
7190 {
7191 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7192 }
7193
7194 static OpCallEval decode(const uint8_t* stream)
7195 {
7196 if (*stream == op_wide32)
7197 return { bitwise_cast<const uint32_t*>(stream + 1) };
7198 if (*stream == op_wide16)
7199 return { bitwise_cast<const uint16_t*>(stream + 1) };
7200 return { stream };
7201 }
7202
7203 template<typename Functor>
7204 void setDst(VirtualRegister value, Functor func)
7205 {
7206 if (isWide32())
7207 setDst<OpcodeSize::Wide32>(value, func);
7208 else if (isWide16())
7209 setDst<OpcodeSize::Wide16>(value, func);
7210 else
7211 setDst<OpcodeSize::Narrow>(value, func);
7212 }
7213
7214 template <OpcodeSize size, typename Functor>
7215 void setDst(VirtualRegister value, Functor func)
7216 {
7217 if (!Fits<VirtualRegister, size>::check(value))
7218 value = func();
7219 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
7220 *stream = Fits<VirtualRegister, size>::convert(value);
7221 }
7222
7223 template<typename Functor>
7224 void setCallee(VirtualRegister value, Functor func)
7225 {
7226 if (isWide32())
7227 setCallee<OpcodeSize::Wide32>(value, func);
7228 else if (isWide16())
7229 setCallee<OpcodeSize::Wide16>(value, func);
7230 else
7231 setCallee<OpcodeSize::Narrow>(value, func);
7232 }
7233
7234 template <OpcodeSize size, typename Functor>
7235 void setCallee(VirtualRegister value, Functor func)
7236 {
7237 if (!Fits<VirtualRegister, size>::check(value))
7238 value = func();
7239 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
7240 *stream = Fits<VirtualRegister, size>::convert(value);
7241 }
7242
7243 template<typename Functor>
7244 void setArgc(unsigned value, Functor func)
7245 {
7246 if (isWide32())
7247 setArgc<OpcodeSize::Wide32>(value, func);
7248 else if (isWide16())
7249 setArgc<OpcodeSize::Wide16>(value, func);
7250 else
7251 setArgc<OpcodeSize::Narrow>(value, func);
7252 }
7253
7254 template <OpcodeSize size, typename Functor>
7255 void setArgc(unsigned value, Functor func)
7256 {
7257 if (!Fits<unsigned, size>::check(value))
7258 value = func();
7259 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
7260 *stream = Fits<unsigned, size>::convert(value);
7261 }
7262
7263 template<typename Functor>
7264 void setArgv(unsigned value, Functor func)
7265 {
7266 if (isWide32())
7267 setArgv<OpcodeSize::Wide32>(value, func);
7268 else if (isWide16())
7269 setArgv<OpcodeSize::Wide16>(value, func);
7270 else
7271 setArgv<OpcodeSize::Narrow>(value, func);
7272 }
7273
7274 template <OpcodeSize size, typename Functor>
7275 void setArgv(unsigned value, Functor func)
7276 {
7277 if (!Fits<unsigned, size>::check(value))
7278 value = func();
7279 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
7280 *stream = Fits<unsigned, size>::convert(value);
7281 }
7282
7283 struct Metadata {
7284 WTF_MAKE_NONCOPYABLE(Metadata);
7285
7286 public:
7287 Metadata(const OpCallEval&) { }
7288
7289 LLIntCallLinkInfo m_callLinkInfo;
7290 ValueProfile m_profile;
7291 };
7292
7293 Metadata& metadata(CodeBlock* codeBlock) const
7294 {
7295 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
7296 }
7297
7298 Metadata& metadata(ExecState* exec) const
7299 {
7300 return metadata(exec->codeBlock());
7301 }
7302
7303 VirtualRegister m_dst;
7304 VirtualRegister m_callee;
7305 unsigned m_argc;
7306 unsigned m_argv;
7307 unsigned m_metadataID;
7308};
7309
7310struct OpCallVarargs : public Instruction {
7311 static constexpr OpcodeID opcodeID = op_call_varargs;
7312
7313 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7314 {
7315 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
7316 }
7317
7318 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
7319 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7320 {
7321 auto __metadataID = gen->addMetadataFor(opcodeID);
7322 return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7323 }
7324
7325 template<OpcodeSize size>
7326 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7327 {
7328 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
7329 return checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7330 }
7331
7332 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
7333 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
7334 {
7335 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7336 if (shouldAssert == Assert)
7337 ASSERT(didEmit);
7338 return didEmit;
7339 }
7340
7341 template<OpcodeSize size>
7342 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7343 {
7344
7345 auto __metadataID = gen->addMetadataFor(opcodeID);
7346 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
7347 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
7348 return;
7349 }
7350 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
7351 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
7352 return;
7353 }
7354 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7355 }
7356
7357private:
7358 template<OpcodeSize size>
7359 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
7360 {
7361 UNUSED_PARAM(gen);
7362#if OS(WINDOWS) && ENABLE(C_LOOP)
7363 // FIXME: Disable wide16 optimization for Windows CLoop
7364 // https://bugs.webkit.org/show_bug.cgi?id=198283
7365 if (size == OpcodeSize::Wide16)
7366 return false;
7367#endif
7368 return Fits<OpcodeID, size>::check(opcodeID)
7369 && Fits<VirtualRegister, size>::check(dst)
7370 && Fits<VirtualRegister, size>::check(callee)
7371 && Fits<VirtualRegister, size>::check(thisValue)
7372 && Fits<VirtualRegister, size>::check(arguments)
7373 && Fits<VirtualRegister, size>::check(firstFree)
7374 && Fits<int, size>::check(firstVarArg)
7375 && Fits<unsigned, size>::check(__metadataID)
7376 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
7377 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
7378 }
7379
7380 template<OpcodeSize size, bool recordOpcode>
7381 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
7382 {
7383 if (size == OpcodeSize::Wide16)
7384 gen->alignWideOpcode16();
7385 else if (size == OpcodeSize::Wide32)
7386 gen->alignWideOpcode32();
7387 if (checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
7388 if (recordOpcode)
7389 gen->recordOpcode(opcodeID);
7390 if (size == OpcodeSize::Wide16)
7391 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
7392 else if (size == OpcodeSize::Wide32)
7393 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
7394 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
7395 gen->write(Fits<VirtualRegister, size>::convert(dst));
7396 gen->write(Fits<VirtualRegister, size>::convert(callee));
7397 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
7398 gen->write(Fits<VirtualRegister, size>::convert(arguments));
7399 gen->write(Fits<VirtualRegister, size>::convert(firstFree));
7400 gen->write(Fits<int, size>::convert(firstVarArg));
7401 gen->write(Fits<unsigned, size>::convert(__metadataID));
7402 return true;
7403 }
7404 return false;
7405 }
7406
7407public:
7408 template<typename Block>
7409 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
7410 {
7411 dumper->printLocationAndOp(__location, &"**call_varargs"[2 - __sizeShiftAmount]);
7412 dumper->dumpOperand(m_dst, true);
7413 dumper->dumpOperand(m_callee, false);
7414 dumper->dumpOperand(m_thisValue, false);
7415 dumper->dumpOperand(m_arguments, false);
7416 dumper->dumpOperand(m_firstFree, false);
7417 dumper->dumpOperand(m_firstVarArg, false);
7418 }
7419
7420 OpCallVarargs(const uint8_t* stream)
7421 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
7422 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
7423 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
7424 , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
7425 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
7426 , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6]))
7427 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
7428 {
7429 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7430 }
7431
7432 OpCallVarargs(const uint16_t* stream)
7433 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
7434 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
7435 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
7436 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
7437 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
7438 , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[6]))
7439 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
7440 {
7441 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7442 }
7443
7444
7445 OpCallVarargs(const uint32_t* stream)
7446 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
7447 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
7448 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
7449 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
7450 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
7451 , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[6]))
7452 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
7453 {
7454 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7455 }
7456
7457 static OpCallVarargs decode(const uint8_t* stream)
7458 {
7459 if (*stream == op_wide32)
7460 return { bitwise_cast<const uint32_t*>(stream + 1) };
7461 if (*stream == op_wide16)
7462 return { bitwise_cast<const uint16_t*>(stream + 1) };
7463 return { stream };
7464 }
7465
7466 template<typename Functor>
7467 void setDst(VirtualRegister value, Functor func)
7468 {
7469 if (isWide32())
7470 setDst<OpcodeSize::Wide32>(value, func);
7471 else if (isWide16())
7472 setDst<OpcodeSize::Wide16>(value, func);
7473 else
7474 setDst<OpcodeSize::Narrow>(value, func);
7475 }
7476
7477 template <OpcodeSize size, typename Functor>
7478 void setDst(VirtualRegister value, Functor func)
7479 {
7480 if (!Fits<VirtualRegister, size>::check(value))
7481 value = func();
7482 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
7483 *stream = Fits<VirtualRegister, size>::convert(value);
7484 }
7485
7486 template<typename Functor>
7487 void setCallee(VirtualRegister value, Functor func)
7488 {
7489 if (isWide32())
7490 setCallee<OpcodeSize::Wide32>(value, func);
7491 else if (isWide16())
7492 setCallee<OpcodeSize::Wide16>(value, func);
7493 else
7494 setCallee<OpcodeSize::Narrow>(value, func);
7495 }
7496
7497 template <OpcodeSize size, typename Functor>
7498 void setCallee(VirtualRegister value, Functor func)
7499 {
7500 if (!Fits<VirtualRegister, size>::check(value))
7501 value = func();
7502 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
7503 *stream = Fits<VirtualRegister, size>::convert(value);
7504 }
7505
7506 template<typename Functor>
7507 void setThisValue(VirtualRegister value, Functor func)
7508 {
7509 if (isWide32())
7510 setThisValue<OpcodeSize::Wide32>(value, func);
7511 else if (isWide16())
7512 setThisValue<OpcodeSize::Wide16>(value, func);
7513 else
7514 setThisValue<OpcodeSize::Narrow>(value, func);
7515 }
7516
7517 template <OpcodeSize size, typename Functor>
7518 void setThisValue(VirtualRegister value, Functor func)
7519 {
7520 if (!Fits<VirtualRegister, size>::check(value))
7521 value = func();
7522 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
7523 *stream = Fits<VirtualRegister, size>::convert(value);
7524 }
7525
7526 template<typename Functor>
7527 void setArguments(VirtualRegister value, Functor func)
7528 {
7529 if (isWide32())
7530 setArguments<OpcodeSize::Wide32>(value, func);
7531 else if (isWide16())
7532 setArguments<OpcodeSize::Wide16>(value, func);
7533 else
7534 setArguments<OpcodeSize::Narrow>(value, func);
7535 }
7536
7537 template <OpcodeSize size, typename Functor>
7538 void setArguments(VirtualRegister value, Functor func)
7539 {
7540 if (!Fits<VirtualRegister, size>::check(value))
7541 value = func();
7542 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
7543 *stream = Fits<VirtualRegister, size>::convert(value);
7544 }
7545
7546 template<typename Functor>
7547 void setFirstFree(VirtualRegister value, Functor func)
7548 {
7549 if (isWide32())
7550 setFirstFree<OpcodeSize::Wide32>(value, func);
7551 else if (isWide16())
7552 setFirstFree<OpcodeSize::Wide16>(value, func);
7553 else
7554 setFirstFree<OpcodeSize::Narrow>(value, func);
7555 }
7556
7557 template <OpcodeSize size, typename Functor>
7558 void setFirstFree(VirtualRegister value, Functor func)
7559 {
7560 if (!Fits<VirtualRegister, size>::check(value))
7561 value = func();
7562 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
7563 *stream = Fits<VirtualRegister, size>::convert(value);
7564 }
7565
7566 template<typename Functor>
7567 void setFirstVarArg(int value, Functor func)
7568 {
7569 if (isWide32())
7570 setFirstVarArg<OpcodeSize::Wide32>(value, func);
7571 else if (isWide16())
7572 setFirstVarArg<OpcodeSize::Wide16>(value, func);
7573 else
7574 setFirstVarArg<OpcodeSize::Narrow>(value, func);
7575 }
7576
7577 template <OpcodeSize size, typename Functor>
7578 void setFirstVarArg(int value, Functor func)
7579 {
7580 if (!Fits<int, size>::check(value))
7581 value = func();
7582 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value);
7583 *stream = Fits<int, size>::convert(value);
7584 }
7585
7586 struct Metadata {
7587 WTF_MAKE_NONCOPYABLE(Metadata);
7588
7589 public:
7590 Metadata(const OpCallVarargs&) { }
7591
7592 ArrayProfile m_arrayProfile;
7593 ValueProfile m_profile;
7594 };
7595
7596 Metadata& metadata(CodeBlock* codeBlock) const
7597 {
7598 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
7599 }
7600
7601 Metadata& metadata(ExecState* exec) const
7602 {
7603 return metadata(exec->codeBlock());
7604 }
7605
7606 VirtualRegister m_dst;
7607 VirtualRegister m_callee;
7608 VirtualRegister m_thisValue;
7609 VirtualRegister m_arguments;
7610 VirtualRegister m_firstFree;
7611 int m_firstVarArg;
7612 unsigned m_metadataID;
7613};
7614
7615struct OpTailCallVarargs : public Instruction {
7616 static constexpr OpcodeID opcodeID = op_tail_call_varargs;
7617
7618 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7619 {
7620 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
7621 }
7622
7623 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
7624 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7625 {
7626 auto __metadataID = gen->addMetadataFor(opcodeID);
7627 return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7628 }
7629
7630 template<OpcodeSize size>
7631 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7632 {
7633 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
7634 return checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7635 }
7636
7637 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
7638 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
7639 {
7640 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7641 if (shouldAssert == Assert)
7642 ASSERT(didEmit);
7643 return didEmit;
7644 }
7645
7646 template<OpcodeSize size>
7647 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7648 {
7649
7650 auto __metadataID = gen->addMetadataFor(opcodeID);
7651 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
7652 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
7653 return;
7654 }
7655 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
7656 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
7657 return;
7658 }
7659 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7660 }
7661
7662private:
7663 template<OpcodeSize size>
7664 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
7665 {
7666 UNUSED_PARAM(gen);
7667#if OS(WINDOWS) && ENABLE(C_LOOP)
7668 // FIXME: Disable wide16 optimization for Windows CLoop
7669 // https://bugs.webkit.org/show_bug.cgi?id=198283
7670 if (size == OpcodeSize::Wide16)
7671 return false;
7672#endif
7673 return Fits<OpcodeID, size>::check(opcodeID)
7674 && Fits<VirtualRegister, size>::check(dst)
7675 && Fits<VirtualRegister, size>::check(callee)
7676 && Fits<VirtualRegister, size>::check(thisValue)
7677 && Fits<VirtualRegister, size>::check(arguments)
7678 && Fits<VirtualRegister, size>::check(firstFree)
7679 && Fits<int, size>::check(firstVarArg)
7680 && Fits<unsigned, size>::check(__metadataID)
7681 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
7682 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
7683 }
7684
7685 template<OpcodeSize size, bool recordOpcode>
7686 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
7687 {
7688 if (size == OpcodeSize::Wide16)
7689 gen->alignWideOpcode16();
7690 else if (size == OpcodeSize::Wide32)
7691 gen->alignWideOpcode32();
7692 if (checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
7693 if (recordOpcode)
7694 gen->recordOpcode(opcodeID);
7695 if (size == OpcodeSize::Wide16)
7696 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
7697 else if (size == OpcodeSize::Wide32)
7698 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
7699 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
7700 gen->write(Fits<VirtualRegister, size>::convert(dst));
7701 gen->write(Fits<VirtualRegister, size>::convert(callee));
7702 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
7703 gen->write(Fits<VirtualRegister, size>::convert(arguments));
7704 gen->write(Fits<VirtualRegister, size>::convert(firstFree));
7705 gen->write(Fits<int, size>::convert(firstVarArg));
7706 gen->write(Fits<unsigned, size>::convert(__metadataID));
7707 return true;
7708 }
7709 return false;
7710 }
7711
7712public:
7713 template<typename Block>
7714 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
7715 {
7716 dumper->printLocationAndOp(__location, &"**tail_call_varargs"[2 - __sizeShiftAmount]);
7717 dumper->dumpOperand(m_dst, true);
7718 dumper->dumpOperand(m_callee, false);
7719 dumper->dumpOperand(m_thisValue, false);
7720 dumper->dumpOperand(m_arguments, false);
7721 dumper->dumpOperand(m_firstFree, false);
7722 dumper->dumpOperand(m_firstVarArg, false);
7723 }
7724
7725 OpTailCallVarargs(const uint8_t* stream)
7726 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
7727 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
7728 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
7729 , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
7730 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
7731 , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6]))
7732 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
7733 {
7734 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7735 }
7736
7737 OpTailCallVarargs(const uint16_t* stream)
7738 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
7739 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
7740 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
7741 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
7742 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
7743 , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[6]))
7744 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
7745 {
7746 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7747 }
7748
7749
7750 OpTailCallVarargs(const uint32_t* stream)
7751 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
7752 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
7753 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
7754 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
7755 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
7756 , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[6]))
7757 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
7758 {
7759 ASSERT_UNUSED(stream, stream[0] == opcodeID);
7760 }
7761
7762 static OpTailCallVarargs decode(const uint8_t* stream)
7763 {
7764 if (*stream == op_wide32)
7765 return { bitwise_cast<const uint32_t*>(stream + 1) };
7766 if (*stream == op_wide16)
7767 return { bitwise_cast<const uint16_t*>(stream + 1) };
7768 return { stream };
7769 }
7770
7771 template<typename Functor>
7772 void setDst(VirtualRegister value, Functor func)
7773 {
7774 if (isWide32())
7775 setDst<OpcodeSize::Wide32>(value, func);
7776 else if (isWide16())
7777 setDst<OpcodeSize::Wide16>(value, func);
7778 else
7779 setDst<OpcodeSize::Narrow>(value, func);
7780 }
7781
7782 template <OpcodeSize size, typename Functor>
7783 void setDst(VirtualRegister value, Functor func)
7784 {
7785 if (!Fits<VirtualRegister, size>::check(value))
7786 value = func();
7787 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
7788 *stream = Fits<VirtualRegister, size>::convert(value);
7789 }
7790
7791 template<typename Functor>
7792 void setCallee(VirtualRegister value, Functor func)
7793 {
7794 if (isWide32())
7795 setCallee<OpcodeSize::Wide32>(value, func);
7796 else if (isWide16())
7797 setCallee<OpcodeSize::Wide16>(value, func);
7798 else
7799 setCallee<OpcodeSize::Narrow>(value, func);
7800 }
7801
7802 template <OpcodeSize size, typename Functor>
7803 void setCallee(VirtualRegister value, Functor func)
7804 {
7805 if (!Fits<VirtualRegister, size>::check(value))
7806 value = func();
7807 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
7808 *stream = Fits<VirtualRegister, size>::convert(value);
7809 }
7810
7811 template<typename Functor>
7812 void setThisValue(VirtualRegister value, Functor func)
7813 {
7814 if (isWide32())
7815 setThisValue<OpcodeSize::Wide32>(value, func);
7816 else if (isWide16())
7817 setThisValue<OpcodeSize::Wide16>(value, func);
7818 else
7819 setThisValue<OpcodeSize::Narrow>(value, func);
7820 }
7821
7822 template <OpcodeSize size, typename Functor>
7823 void setThisValue(VirtualRegister value, Functor func)
7824 {
7825 if (!Fits<VirtualRegister, size>::check(value))
7826 value = func();
7827 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
7828 *stream = Fits<VirtualRegister, size>::convert(value);
7829 }
7830
7831 template<typename Functor>
7832 void setArguments(VirtualRegister value, Functor func)
7833 {
7834 if (isWide32())
7835 setArguments<OpcodeSize::Wide32>(value, func);
7836 else if (isWide16())
7837 setArguments<OpcodeSize::Wide16>(value, func);
7838 else
7839 setArguments<OpcodeSize::Narrow>(value, func);
7840 }
7841
7842 template <OpcodeSize size, typename Functor>
7843 void setArguments(VirtualRegister value, Functor func)
7844 {
7845 if (!Fits<VirtualRegister, size>::check(value))
7846 value = func();
7847 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
7848 *stream = Fits<VirtualRegister, size>::convert(value);
7849 }
7850
7851 template<typename Functor>
7852 void setFirstFree(VirtualRegister value, Functor func)
7853 {
7854 if (isWide32())
7855 setFirstFree<OpcodeSize::Wide32>(value, func);
7856 else if (isWide16())
7857 setFirstFree<OpcodeSize::Wide16>(value, func);
7858 else
7859 setFirstFree<OpcodeSize::Narrow>(value, func);
7860 }
7861
7862 template <OpcodeSize size, typename Functor>
7863 void setFirstFree(VirtualRegister value, Functor func)
7864 {
7865 if (!Fits<VirtualRegister, size>::check(value))
7866 value = func();
7867 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
7868 *stream = Fits<VirtualRegister, size>::convert(value);
7869 }
7870
7871 template<typename Functor>
7872 void setFirstVarArg(int value, Functor func)
7873 {
7874 if (isWide32())
7875 setFirstVarArg<OpcodeSize::Wide32>(value, func);
7876 else if (isWide16())
7877 setFirstVarArg<OpcodeSize::Wide16>(value, func);
7878 else
7879 setFirstVarArg<OpcodeSize::Narrow>(value, func);
7880 }
7881
7882 template <OpcodeSize size, typename Functor>
7883 void setFirstVarArg(int value, Functor func)
7884 {
7885 if (!Fits<int, size>::check(value))
7886 value = func();
7887 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value);
7888 *stream = Fits<int, size>::convert(value);
7889 }
7890
7891 struct Metadata {
7892 WTF_MAKE_NONCOPYABLE(Metadata);
7893
7894 public:
7895 Metadata(const OpTailCallVarargs&) { }
7896
7897 ArrayProfile m_arrayProfile;
7898 ValueProfile m_profile;
7899 };
7900
7901 Metadata& metadata(CodeBlock* codeBlock) const
7902 {
7903 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
7904 }
7905
7906 Metadata& metadata(ExecState* exec) const
7907 {
7908 return metadata(exec->codeBlock());
7909 }
7910
7911 VirtualRegister m_dst;
7912 VirtualRegister m_callee;
7913 VirtualRegister m_thisValue;
7914 VirtualRegister m_arguments;
7915 VirtualRegister m_firstFree;
7916 int m_firstVarArg;
7917 unsigned m_metadataID;
7918};
7919
7920struct OpTailCallForwardArguments : public Instruction {
7921 static constexpr OpcodeID opcodeID = op_tail_call_forward_arguments;
7922
7923 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7924 {
7925 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
7926 }
7927
7928 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
7929 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7930 {
7931 auto __metadataID = gen->addMetadataFor(opcodeID);
7932 return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7933 }
7934
7935 template<OpcodeSize size>
7936 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7937 {
7938 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
7939 return checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7940 }
7941
7942 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
7943 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
7944 {
7945 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7946 if (shouldAssert == Assert)
7947 ASSERT(didEmit);
7948 return didEmit;
7949 }
7950
7951 template<OpcodeSize size>
7952 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
7953 {
7954
7955 auto __metadataID = gen->addMetadataFor(opcodeID);
7956 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
7957 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
7958 return;
7959 }
7960 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
7961 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
7962 return;
7963 }
7964 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
7965 }
7966
7967private:
7968 template<OpcodeSize size>
7969 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
7970 {
7971 UNUSED_PARAM(gen);
7972#if OS(WINDOWS) && ENABLE(C_LOOP)
7973 // FIXME: Disable wide16 optimization for Windows CLoop
7974 // https://bugs.webkit.org/show_bug.cgi?id=198283
7975 if (size == OpcodeSize::Wide16)
7976 return false;
7977#endif
7978 return Fits<OpcodeID, size>::check(opcodeID)
7979 && Fits<VirtualRegister, size>::check(dst)
7980 && Fits<VirtualRegister, size>::check(callee)
7981 && Fits<VirtualRegister, size>::check(thisValue)
7982 && Fits<VirtualRegister, size>::check(arguments)
7983 && Fits<VirtualRegister, size>::check(firstFree)
7984 && Fits<int, size>::check(firstVarArg)
7985 && Fits<unsigned, size>::check(__metadataID)
7986 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
7987 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
7988 }
7989
7990 template<OpcodeSize size, bool recordOpcode>
7991 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
7992 {
7993 if (size == OpcodeSize::Wide16)
7994 gen->alignWideOpcode16();
7995 else if (size == OpcodeSize::Wide32)
7996 gen->alignWideOpcode32();
7997 if (checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
7998 if (recordOpcode)
7999 gen->recordOpcode(opcodeID);
8000 if (size == OpcodeSize::Wide16)
8001 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
8002 else if (size == OpcodeSize::Wide32)
8003 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
8004 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
8005 gen->write(Fits<VirtualRegister, size>::convert(dst));
8006 gen->write(Fits<VirtualRegister, size>::convert(callee));
8007 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
8008 gen->write(Fits<VirtualRegister, size>::convert(arguments));
8009 gen->write(Fits<VirtualRegister, size>::convert(firstFree));
8010 gen->write(Fits<int, size>::convert(firstVarArg));
8011 gen->write(Fits<unsigned, size>::convert(__metadataID));
8012 return true;
8013 }
8014 return false;
8015 }
8016
8017public:
8018 template<typename Block>
8019 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
8020 {
8021 dumper->printLocationAndOp(__location, &"**tail_call_forward_arguments"[2 - __sizeShiftAmount]);
8022 dumper->dumpOperand(m_dst, true);
8023 dumper->dumpOperand(m_callee, false);
8024 dumper->dumpOperand(m_thisValue, false);
8025 dumper->dumpOperand(m_arguments, false);
8026 dumper->dumpOperand(m_firstFree, false);
8027 dumper->dumpOperand(m_firstVarArg, false);
8028 }
8029
8030 OpTailCallForwardArguments(const uint8_t* stream)
8031 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
8032 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
8033 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
8034 , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
8035 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
8036 , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6]))
8037 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
8038 {
8039 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8040 }
8041
8042 OpTailCallForwardArguments(const uint16_t* stream)
8043 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
8044 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
8045 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
8046 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
8047 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
8048 , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[6]))
8049 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
8050 {
8051 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8052 }
8053
8054
8055 OpTailCallForwardArguments(const uint32_t* stream)
8056 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
8057 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
8058 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
8059 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
8060 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
8061 , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[6]))
8062 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
8063 {
8064 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8065 }
8066
8067 static OpTailCallForwardArguments decode(const uint8_t* stream)
8068 {
8069 if (*stream == op_wide32)
8070 return { bitwise_cast<const uint32_t*>(stream + 1) };
8071 if (*stream == op_wide16)
8072 return { bitwise_cast<const uint16_t*>(stream + 1) };
8073 return { stream };
8074 }
8075
8076 template<typename Functor>
8077 void setDst(VirtualRegister value, Functor func)
8078 {
8079 if (isWide32())
8080 setDst<OpcodeSize::Wide32>(value, func);
8081 else if (isWide16())
8082 setDst<OpcodeSize::Wide16>(value, func);
8083 else
8084 setDst<OpcodeSize::Narrow>(value, func);
8085 }
8086
8087 template <OpcodeSize size, typename Functor>
8088 void setDst(VirtualRegister value, Functor func)
8089 {
8090 if (!Fits<VirtualRegister, size>::check(value))
8091 value = func();
8092 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
8093 *stream = Fits<VirtualRegister, size>::convert(value);
8094 }
8095
8096 template<typename Functor>
8097 void setCallee(VirtualRegister value, Functor func)
8098 {
8099 if (isWide32())
8100 setCallee<OpcodeSize::Wide32>(value, func);
8101 else if (isWide16())
8102 setCallee<OpcodeSize::Wide16>(value, func);
8103 else
8104 setCallee<OpcodeSize::Narrow>(value, func);
8105 }
8106
8107 template <OpcodeSize size, typename Functor>
8108 void setCallee(VirtualRegister value, Functor func)
8109 {
8110 if (!Fits<VirtualRegister, size>::check(value))
8111 value = func();
8112 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
8113 *stream = Fits<VirtualRegister, size>::convert(value);
8114 }
8115
8116 template<typename Functor>
8117 void setThisValue(VirtualRegister value, Functor func)
8118 {
8119 if (isWide32())
8120 setThisValue<OpcodeSize::Wide32>(value, func);
8121 else if (isWide16())
8122 setThisValue<OpcodeSize::Wide16>(value, func);
8123 else
8124 setThisValue<OpcodeSize::Narrow>(value, func);
8125 }
8126
8127 template <OpcodeSize size, typename Functor>
8128 void setThisValue(VirtualRegister value, Functor func)
8129 {
8130 if (!Fits<VirtualRegister, size>::check(value))
8131 value = func();
8132 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
8133 *stream = Fits<VirtualRegister, size>::convert(value);
8134 }
8135
8136 template<typename Functor>
8137 void setArguments(VirtualRegister value, Functor func)
8138 {
8139 if (isWide32())
8140 setArguments<OpcodeSize::Wide32>(value, func);
8141 else if (isWide16())
8142 setArguments<OpcodeSize::Wide16>(value, func);
8143 else
8144 setArguments<OpcodeSize::Narrow>(value, func);
8145 }
8146
8147 template <OpcodeSize size, typename Functor>
8148 void setArguments(VirtualRegister value, Functor func)
8149 {
8150 if (!Fits<VirtualRegister, size>::check(value))
8151 value = func();
8152 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
8153 *stream = Fits<VirtualRegister, size>::convert(value);
8154 }
8155
8156 template<typename Functor>
8157 void setFirstFree(VirtualRegister value, Functor func)
8158 {
8159 if (isWide32())
8160 setFirstFree<OpcodeSize::Wide32>(value, func);
8161 else if (isWide16())
8162 setFirstFree<OpcodeSize::Wide16>(value, func);
8163 else
8164 setFirstFree<OpcodeSize::Narrow>(value, func);
8165 }
8166
8167 template <OpcodeSize size, typename Functor>
8168 void setFirstFree(VirtualRegister value, Functor func)
8169 {
8170 if (!Fits<VirtualRegister, size>::check(value))
8171 value = func();
8172 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
8173 *stream = Fits<VirtualRegister, size>::convert(value);
8174 }
8175
8176 template<typename Functor>
8177 void setFirstVarArg(int value, Functor func)
8178 {
8179 if (isWide32())
8180 setFirstVarArg<OpcodeSize::Wide32>(value, func);
8181 else if (isWide16())
8182 setFirstVarArg<OpcodeSize::Wide16>(value, func);
8183 else
8184 setFirstVarArg<OpcodeSize::Narrow>(value, func);
8185 }
8186
8187 template <OpcodeSize size, typename Functor>
8188 void setFirstVarArg(int value, Functor func)
8189 {
8190 if (!Fits<int, size>::check(value))
8191 value = func();
8192 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value);
8193 *stream = Fits<int, size>::convert(value);
8194 }
8195
8196 struct Metadata {
8197 WTF_MAKE_NONCOPYABLE(Metadata);
8198
8199 public:
8200 Metadata(const OpTailCallForwardArguments&) { }
8201
8202 ArrayProfile m_arrayProfile;
8203 ValueProfile m_profile;
8204 };
8205
8206 Metadata& metadata(CodeBlock* codeBlock) const
8207 {
8208 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
8209 }
8210
8211 Metadata& metadata(ExecState* exec) const
8212 {
8213 return metadata(exec->codeBlock());
8214 }
8215
8216 VirtualRegister m_dst;
8217 VirtualRegister m_callee;
8218 VirtualRegister m_thisValue;
8219 VirtualRegister m_arguments;
8220 VirtualRegister m_firstFree;
8221 int m_firstVarArg;
8222 unsigned m_metadataID;
8223};
8224
8225struct OpConstruct : public Instruction {
8226 static constexpr OpcodeID opcodeID = op_construct;
8227
8228 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
8229 {
8230 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, argc, argv);
8231 }
8232
8233 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
8234 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
8235 {
8236 auto __metadataID = gen->addMetadataFor(opcodeID);
8237 return emit<size, shouldAssert>(gen, dst, callee, argc, argv, __metadataID);
8238 }
8239
8240 template<OpcodeSize size>
8241 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
8242 {
8243 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
8244 return checkImpl<size>(gen, dst, callee, argc, argv, __metadataID);
8245 }
8246
8247 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
8248 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
8249 {
8250 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, argc, argv, __metadataID);
8251 if (shouldAssert == Assert)
8252 ASSERT(didEmit);
8253 return didEmit;
8254 }
8255
8256 template<OpcodeSize size>
8257 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
8258 {
8259
8260 auto __metadataID = gen->addMetadataFor(opcodeID);
8261 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
8262 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
8263 return;
8264 }
8265 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
8266 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
8267 return;
8268 }
8269 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
8270 }
8271
8272private:
8273 template<OpcodeSize size>
8274 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, unsigned __metadataID)
8275 {
8276 UNUSED_PARAM(gen);
8277#if OS(WINDOWS) && ENABLE(C_LOOP)
8278 // FIXME: Disable wide16 optimization for Windows CLoop
8279 // https://bugs.webkit.org/show_bug.cgi?id=198283
8280 if (size == OpcodeSize::Wide16)
8281 return false;
8282#endif
8283 return Fits<OpcodeID, size>::check(opcodeID)
8284 && Fits<VirtualRegister, size>::check(dst)
8285 && Fits<VirtualRegister, size>::check(callee)
8286 && Fits<unsigned, size>::check(argc)
8287 && Fits<unsigned, size>::check(argv)
8288 && Fits<unsigned, size>::check(__metadataID)
8289 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
8290 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
8291 }
8292
8293 template<OpcodeSize size, bool recordOpcode>
8294 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
8295 {
8296 if (size == OpcodeSize::Wide16)
8297 gen->alignWideOpcode16();
8298 else if (size == OpcodeSize::Wide32)
8299 gen->alignWideOpcode32();
8300 if (checkImpl<size>(gen, dst, callee, argc, argv, __metadataID)) {
8301 if (recordOpcode)
8302 gen->recordOpcode(opcodeID);
8303 if (size == OpcodeSize::Wide16)
8304 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
8305 else if (size == OpcodeSize::Wide32)
8306 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
8307 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
8308 gen->write(Fits<VirtualRegister, size>::convert(dst));
8309 gen->write(Fits<VirtualRegister, size>::convert(callee));
8310 gen->write(Fits<unsigned, size>::convert(argc));
8311 gen->write(Fits<unsigned, size>::convert(argv));
8312 gen->write(Fits<unsigned, size>::convert(__metadataID));
8313 return true;
8314 }
8315 return false;
8316 }
8317
8318public:
8319 template<typename Block>
8320 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
8321 {
8322 dumper->printLocationAndOp(__location, &"**construct"[2 - __sizeShiftAmount]);
8323 dumper->dumpOperand(m_dst, true);
8324 dumper->dumpOperand(m_callee, false);
8325 dumper->dumpOperand(m_argc, false);
8326 dumper->dumpOperand(m_argv, false);
8327 }
8328
8329 OpConstruct(const uint8_t* stream)
8330 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
8331 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
8332 , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
8333 , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
8334 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
8335 {
8336 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8337 }
8338
8339 OpConstruct(const uint16_t* stream)
8340 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
8341 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
8342 , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
8343 , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
8344 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
8345 {
8346 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8347 }
8348
8349
8350 OpConstruct(const uint32_t* stream)
8351 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
8352 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
8353 , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
8354 , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
8355 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
8356 {
8357 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8358 }
8359
8360 static OpConstruct decode(const uint8_t* stream)
8361 {
8362 if (*stream == op_wide32)
8363 return { bitwise_cast<const uint32_t*>(stream + 1) };
8364 if (*stream == op_wide16)
8365 return { bitwise_cast<const uint16_t*>(stream + 1) };
8366 return { stream };
8367 }
8368
8369 template<typename Functor>
8370 void setDst(VirtualRegister value, Functor func)
8371 {
8372 if (isWide32())
8373 setDst<OpcodeSize::Wide32>(value, func);
8374 else if (isWide16())
8375 setDst<OpcodeSize::Wide16>(value, func);
8376 else
8377 setDst<OpcodeSize::Narrow>(value, func);
8378 }
8379
8380 template <OpcodeSize size, typename Functor>
8381 void setDst(VirtualRegister value, Functor func)
8382 {
8383 if (!Fits<VirtualRegister, size>::check(value))
8384 value = func();
8385 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
8386 *stream = Fits<VirtualRegister, size>::convert(value);
8387 }
8388
8389 template<typename Functor>
8390 void setCallee(VirtualRegister value, Functor func)
8391 {
8392 if (isWide32())
8393 setCallee<OpcodeSize::Wide32>(value, func);
8394 else if (isWide16())
8395 setCallee<OpcodeSize::Wide16>(value, func);
8396 else
8397 setCallee<OpcodeSize::Narrow>(value, func);
8398 }
8399
8400 template <OpcodeSize size, typename Functor>
8401 void setCallee(VirtualRegister value, Functor func)
8402 {
8403 if (!Fits<VirtualRegister, size>::check(value))
8404 value = func();
8405 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
8406 *stream = Fits<VirtualRegister, size>::convert(value);
8407 }
8408
8409 template<typename Functor>
8410 void setArgc(unsigned value, Functor func)
8411 {
8412 if (isWide32())
8413 setArgc<OpcodeSize::Wide32>(value, func);
8414 else if (isWide16())
8415 setArgc<OpcodeSize::Wide16>(value, func);
8416 else
8417 setArgc<OpcodeSize::Narrow>(value, func);
8418 }
8419
8420 template <OpcodeSize size, typename Functor>
8421 void setArgc(unsigned value, Functor func)
8422 {
8423 if (!Fits<unsigned, size>::check(value))
8424 value = func();
8425 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
8426 *stream = Fits<unsigned, size>::convert(value);
8427 }
8428
8429 template<typename Functor>
8430 void setArgv(unsigned value, Functor func)
8431 {
8432 if (isWide32())
8433 setArgv<OpcodeSize::Wide32>(value, func);
8434 else if (isWide16())
8435 setArgv<OpcodeSize::Wide16>(value, func);
8436 else
8437 setArgv<OpcodeSize::Narrow>(value, func);
8438 }
8439
8440 template <OpcodeSize size, typename Functor>
8441 void setArgv(unsigned value, Functor func)
8442 {
8443 if (!Fits<unsigned, size>::check(value))
8444 value = func();
8445 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
8446 *stream = Fits<unsigned, size>::convert(value);
8447 }
8448
8449 struct Metadata {
8450 WTF_MAKE_NONCOPYABLE(Metadata);
8451
8452 public:
8453 Metadata(const OpConstruct&) { }
8454
8455 LLIntCallLinkInfo m_callLinkInfo;
8456 ValueProfile m_profile;
8457 };
8458
8459 Metadata& metadata(CodeBlock* codeBlock) const
8460 {
8461 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
8462 }
8463
8464 Metadata& metadata(ExecState* exec) const
8465 {
8466 return metadata(exec->codeBlock());
8467 }
8468
8469 VirtualRegister m_dst;
8470 VirtualRegister m_callee;
8471 unsigned m_argc;
8472 unsigned m_argv;
8473 unsigned m_metadataID;
8474};
8475
8476struct OpConstructVarargs : public Instruction {
8477 static constexpr OpcodeID opcodeID = op_construct_varargs;
8478
8479 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
8480 {
8481 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
8482 }
8483
8484 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
8485 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
8486 {
8487 auto __metadataID = gen->addMetadataFor(opcodeID);
8488 return emit<size, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
8489 }
8490
8491 template<OpcodeSize size>
8492 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
8493 {
8494 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
8495 return checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
8496 }
8497
8498 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
8499 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
8500 {
8501 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
8502 if (shouldAssert == Assert)
8503 ASSERT(didEmit);
8504 return didEmit;
8505 }
8506
8507 template<OpcodeSize size>
8508 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
8509 {
8510
8511 auto __metadataID = gen->addMetadataFor(opcodeID);
8512 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
8513 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
8514 return;
8515 }
8516 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
8517 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
8518 return;
8519 }
8520 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
8521 }
8522
8523private:
8524 template<OpcodeSize size>
8525 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
8526 {
8527 UNUSED_PARAM(gen);
8528#if OS(WINDOWS) && ENABLE(C_LOOP)
8529 // FIXME: Disable wide16 optimization for Windows CLoop
8530 // https://bugs.webkit.org/show_bug.cgi?id=198283
8531 if (size == OpcodeSize::Wide16)
8532 return false;
8533#endif
8534 return Fits<OpcodeID, size>::check(opcodeID)
8535 && Fits<VirtualRegister, size>::check(dst)
8536 && Fits<VirtualRegister, size>::check(callee)
8537 && Fits<VirtualRegister, size>::check(thisValue)
8538 && Fits<VirtualRegister, size>::check(arguments)
8539 && Fits<VirtualRegister, size>::check(firstFree)
8540 && Fits<int, size>::check(firstVarArg)
8541 && Fits<unsigned, size>::check(__metadataID)
8542 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
8543 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
8544 }
8545
8546 template<OpcodeSize size, bool recordOpcode>
8547 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
8548 {
8549 if (size == OpcodeSize::Wide16)
8550 gen->alignWideOpcode16();
8551 else if (size == OpcodeSize::Wide32)
8552 gen->alignWideOpcode32();
8553 if (checkImpl<size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
8554 if (recordOpcode)
8555 gen->recordOpcode(opcodeID);
8556 if (size == OpcodeSize::Wide16)
8557 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
8558 else if (size == OpcodeSize::Wide32)
8559 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
8560 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
8561 gen->write(Fits<VirtualRegister, size>::convert(dst));
8562 gen->write(Fits<VirtualRegister, size>::convert(callee));
8563 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
8564 gen->write(Fits<VirtualRegister, size>::convert(arguments));
8565 gen->write(Fits<VirtualRegister, size>::convert(firstFree));
8566 gen->write(Fits<int, size>::convert(firstVarArg));
8567 gen->write(Fits<unsigned, size>::convert(__metadataID));
8568 return true;
8569 }
8570 return false;
8571 }
8572
8573public:
8574 template<typename Block>
8575 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
8576 {
8577 dumper->printLocationAndOp(__location, &"**construct_varargs"[2 - __sizeShiftAmount]);
8578 dumper->dumpOperand(m_dst, true);
8579 dumper->dumpOperand(m_callee, false);
8580 dumper->dumpOperand(m_thisValue, false);
8581 dumper->dumpOperand(m_arguments, false);
8582 dumper->dumpOperand(m_firstFree, false);
8583 dumper->dumpOperand(m_firstVarArg, false);
8584 }
8585
8586 OpConstructVarargs(const uint8_t* stream)
8587 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
8588 , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
8589 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
8590 , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
8591 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
8592 , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[6]))
8593 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
8594 {
8595 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8596 }
8597
8598 OpConstructVarargs(const uint16_t* stream)
8599 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
8600 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
8601 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
8602 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
8603 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
8604 , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[6]))
8605 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
8606 {
8607 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8608 }
8609
8610
8611 OpConstructVarargs(const uint32_t* stream)
8612 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
8613 , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
8614 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
8615 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
8616 , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
8617 , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[6]))
8618 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
8619 {
8620 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8621 }
8622
8623 static OpConstructVarargs decode(const uint8_t* stream)
8624 {
8625 if (*stream == op_wide32)
8626 return { bitwise_cast<const uint32_t*>(stream + 1) };
8627 if (*stream == op_wide16)
8628 return { bitwise_cast<const uint16_t*>(stream + 1) };
8629 return { stream };
8630 }
8631
8632 template<typename Functor>
8633 void setDst(VirtualRegister value, Functor func)
8634 {
8635 if (isWide32())
8636 setDst<OpcodeSize::Wide32>(value, func);
8637 else if (isWide16())
8638 setDst<OpcodeSize::Wide16>(value, func);
8639 else
8640 setDst<OpcodeSize::Narrow>(value, func);
8641 }
8642
8643 template <OpcodeSize size, typename Functor>
8644 void setDst(VirtualRegister value, Functor func)
8645 {
8646 if (!Fits<VirtualRegister, size>::check(value))
8647 value = func();
8648 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
8649 *stream = Fits<VirtualRegister, size>::convert(value);
8650 }
8651
8652 template<typename Functor>
8653 void setCallee(VirtualRegister value, Functor func)
8654 {
8655 if (isWide32())
8656 setCallee<OpcodeSize::Wide32>(value, func);
8657 else if (isWide16())
8658 setCallee<OpcodeSize::Wide16>(value, func);
8659 else
8660 setCallee<OpcodeSize::Narrow>(value, func);
8661 }
8662
8663 template <OpcodeSize size, typename Functor>
8664 void setCallee(VirtualRegister value, Functor func)
8665 {
8666 if (!Fits<VirtualRegister, size>::check(value))
8667 value = func();
8668 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
8669 *stream = Fits<VirtualRegister, size>::convert(value);
8670 }
8671
8672 template<typename Functor>
8673 void setThisValue(VirtualRegister value, Functor func)
8674 {
8675 if (isWide32())
8676 setThisValue<OpcodeSize::Wide32>(value, func);
8677 else if (isWide16())
8678 setThisValue<OpcodeSize::Wide16>(value, func);
8679 else
8680 setThisValue<OpcodeSize::Narrow>(value, func);
8681 }
8682
8683 template <OpcodeSize size, typename Functor>
8684 void setThisValue(VirtualRegister value, Functor func)
8685 {
8686 if (!Fits<VirtualRegister, size>::check(value))
8687 value = func();
8688 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
8689 *stream = Fits<VirtualRegister, size>::convert(value);
8690 }
8691
8692 template<typename Functor>
8693 void setArguments(VirtualRegister value, Functor func)
8694 {
8695 if (isWide32())
8696 setArguments<OpcodeSize::Wide32>(value, func);
8697 else if (isWide16())
8698 setArguments<OpcodeSize::Wide16>(value, func);
8699 else
8700 setArguments<OpcodeSize::Narrow>(value, func);
8701 }
8702
8703 template <OpcodeSize size, typename Functor>
8704 void setArguments(VirtualRegister value, Functor func)
8705 {
8706 if (!Fits<VirtualRegister, size>::check(value))
8707 value = func();
8708 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
8709 *stream = Fits<VirtualRegister, size>::convert(value);
8710 }
8711
8712 template<typename Functor>
8713 void setFirstFree(VirtualRegister value, Functor func)
8714 {
8715 if (isWide32())
8716 setFirstFree<OpcodeSize::Wide32>(value, func);
8717 else if (isWide16())
8718 setFirstFree<OpcodeSize::Wide16>(value, func);
8719 else
8720 setFirstFree<OpcodeSize::Narrow>(value, func);
8721 }
8722
8723 template <OpcodeSize size, typename Functor>
8724 void setFirstFree(VirtualRegister value, Functor func)
8725 {
8726 if (!Fits<VirtualRegister, size>::check(value))
8727 value = func();
8728 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
8729 *stream = Fits<VirtualRegister, size>::convert(value);
8730 }
8731
8732 template<typename Functor>
8733 void setFirstVarArg(int value, Functor func)
8734 {
8735 if (isWide32())
8736 setFirstVarArg<OpcodeSize::Wide32>(value, func);
8737 else if (isWide16())
8738 setFirstVarArg<OpcodeSize::Wide16>(value, func);
8739 else
8740 setFirstVarArg<OpcodeSize::Narrow>(value, func);
8741 }
8742
8743 template <OpcodeSize size, typename Functor>
8744 void setFirstVarArg(int value, Functor func)
8745 {
8746 if (!Fits<int, size>::check(value))
8747 value = func();
8748 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value);
8749 *stream = Fits<int, size>::convert(value);
8750 }
8751
8752 struct Metadata {
8753 WTF_MAKE_NONCOPYABLE(Metadata);
8754
8755 public:
8756 Metadata(const OpConstructVarargs&) { }
8757
8758 ArrayProfile m_arrayProfile;
8759 ValueProfile m_profile;
8760 };
8761
8762 Metadata& metadata(CodeBlock* codeBlock) const
8763 {
8764 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
8765 }
8766
8767 Metadata& metadata(ExecState* exec) const
8768 {
8769 return metadata(exec->codeBlock());
8770 }
8771
8772 VirtualRegister m_dst;
8773 VirtualRegister m_callee;
8774 VirtualRegister m_thisValue;
8775 VirtualRegister m_arguments;
8776 VirtualRegister m_firstFree;
8777 int m_firstVarArg;
8778 unsigned m_metadataID;
8779};
8780
8781struct OpResolveScope : public Instruction {
8782 static constexpr OpcodeID opcodeID = op_resolve_scope;
8783
8784 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
8785 {
8786 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, var, resolveType, localScopeDepth);
8787 }
8788
8789 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
8790 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
8791 {
8792 auto __metadataID = gen->addMetadataFor(opcodeID);
8793 return emit<size, shouldAssert>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
8794 }
8795
8796 template<OpcodeSize size>
8797 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
8798 {
8799 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
8800 return checkImpl<size>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
8801 }
8802
8803 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
8804 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth, unsigned __metadataID)
8805 {
8806 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
8807 if (shouldAssert == Assert)
8808 ASSERT(didEmit);
8809 return didEmit;
8810 }
8811
8812 template<OpcodeSize size>
8813 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
8814 {
8815
8816 auto __metadataID = gen->addMetadataFor(opcodeID);
8817 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
8818 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID))
8819 return;
8820 }
8821 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
8822 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID))
8823 return;
8824 }
8825 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
8826 }
8827
8828private:
8829 template<OpcodeSize size>
8830 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& var, ResolveType& resolveType, unsigned& localScopeDepth, unsigned __metadataID)
8831 {
8832 UNUSED_PARAM(gen);
8833#if OS(WINDOWS) && ENABLE(C_LOOP)
8834 // FIXME: Disable wide16 optimization for Windows CLoop
8835 // https://bugs.webkit.org/show_bug.cgi?id=198283
8836 if (size == OpcodeSize::Wide16)
8837 return false;
8838#endif
8839 return Fits<OpcodeID, size>::check(opcodeID)
8840 && Fits<VirtualRegister, size>::check(dst)
8841 && Fits<VirtualRegister, size>::check(scope)
8842 && Fits<unsigned, size>::check(var)
8843 && Fits<ResolveType, size>::check(resolveType)
8844 && Fits<unsigned, size>::check(localScopeDepth)
8845 && Fits<unsigned, size>::check(__metadataID)
8846 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
8847 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
8848 }
8849
8850 template<OpcodeSize size, bool recordOpcode>
8851 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth, unsigned __metadataID)
8852 {
8853 if (size == OpcodeSize::Wide16)
8854 gen->alignWideOpcode16();
8855 else if (size == OpcodeSize::Wide32)
8856 gen->alignWideOpcode32();
8857 if (checkImpl<size>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID)) {
8858 if (recordOpcode)
8859 gen->recordOpcode(opcodeID);
8860 if (size == OpcodeSize::Wide16)
8861 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
8862 else if (size == OpcodeSize::Wide32)
8863 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
8864 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
8865 gen->write(Fits<VirtualRegister, size>::convert(dst));
8866 gen->write(Fits<VirtualRegister, size>::convert(scope));
8867 gen->write(Fits<unsigned, size>::convert(var));
8868 gen->write(Fits<ResolveType, size>::convert(resolveType));
8869 gen->write(Fits<unsigned, size>::convert(localScopeDepth));
8870 gen->write(Fits<unsigned, size>::convert(__metadataID));
8871 return true;
8872 }
8873 return false;
8874 }
8875
8876public:
8877 template<typename Block>
8878 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
8879 {
8880 dumper->printLocationAndOp(__location, &"**resolve_scope"[2 - __sizeShiftAmount]);
8881 dumper->dumpOperand(m_dst, true);
8882 dumper->dumpOperand(m_scope, false);
8883 dumper->dumpOperand(m_var, false);
8884 dumper->dumpOperand(m_resolveType, false);
8885 dumper->dumpOperand(m_localScopeDepth, false);
8886 }
8887
8888 OpResolveScope(const uint8_t* stream)
8889 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
8890 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
8891 , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
8892 , m_resolveType(Fits<ResolveType, OpcodeSize::Narrow>::convert(stream[4]))
8893 , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
8894 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
8895 {
8896 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8897 }
8898
8899 OpResolveScope(const uint16_t* stream)
8900 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
8901 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
8902 , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
8903 , m_resolveType(Fits<ResolveType, OpcodeSize::Wide16>::convert(stream[4]))
8904 , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
8905 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
8906 {
8907 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8908 }
8909
8910
8911 OpResolveScope(const uint32_t* stream)
8912 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
8913 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
8914 , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
8915 , m_resolveType(Fits<ResolveType, OpcodeSize::Wide32>::convert(stream[4]))
8916 , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
8917 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
8918 {
8919 ASSERT_UNUSED(stream, stream[0] == opcodeID);
8920 }
8921
8922 static OpResolveScope decode(const uint8_t* stream)
8923 {
8924 if (*stream == op_wide32)
8925 return { bitwise_cast<const uint32_t*>(stream + 1) };
8926 if (*stream == op_wide16)
8927 return { bitwise_cast<const uint16_t*>(stream + 1) };
8928 return { stream };
8929 }
8930
8931 template<typename Functor>
8932 void setDst(VirtualRegister value, Functor func)
8933 {
8934 if (isWide32())
8935 setDst<OpcodeSize::Wide32>(value, func);
8936 else if (isWide16())
8937 setDst<OpcodeSize::Wide16>(value, func);
8938 else
8939 setDst<OpcodeSize::Narrow>(value, func);
8940 }
8941
8942 template <OpcodeSize size, typename Functor>
8943 void setDst(VirtualRegister value, Functor func)
8944 {
8945 if (!Fits<VirtualRegister, size>::check(value))
8946 value = func();
8947 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
8948 *stream = Fits<VirtualRegister, size>::convert(value);
8949 }
8950
8951 template<typename Functor>
8952 void setScope(VirtualRegister value, Functor func)
8953 {
8954 if (isWide32())
8955 setScope<OpcodeSize::Wide32>(value, func);
8956 else if (isWide16())
8957 setScope<OpcodeSize::Wide16>(value, func);
8958 else
8959 setScope<OpcodeSize::Narrow>(value, func);
8960 }
8961
8962 template <OpcodeSize size, typename Functor>
8963 void setScope(VirtualRegister value, Functor func)
8964 {
8965 if (!Fits<VirtualRegister, size>::check(value))
8966 value = func();
8967 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
8968 *stream = Fits<VirtualRegister, size>::convert(value);
8969 }
8970
8971 template<typename Functor>
8972 void setVar(unsigned value, Functor func)
8973 {
8974 if (isWide32())
8975 setVar<OpcodeSize::Wide32>(value, func);
8976 else if (isWide16())
8977 setVar<OpcodeSize::Wide16>(value, func);
8978 else
8979 setVar<OpcodeSize::Narrow>(value, func);
8980 }
8981
8982 template <OpcodeSize size, typename Functor>
8983 void setVar(unsigned value, Functor func)
8984 {
8985 if (!Fits<unsigned, size>::check(value))
8986 value = func();
8987 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
8988 *stream = Fits<unsigned, size>::convert(value);
8989 }
8990
8991 template<typename Functor>
8992 void setResolveType(ResolveType value, Functor func)
8993 {
8994 if (isWide32())
8995 setResolveType<OpcodeSize::Wide32>(value, func);
8996 else if (isWide16())
8997 setResolveType<OpcodeSize::Wide16>(value, func);
8998 else
8999 setResolveType<OpcodeSize::Narrow>(value, func);
9000 }
9001
9002 template <OpcodeSize size, typename Functor>
9003 void setResolveType(ResolveType value, Functor func)
9004 {
9005 if (!Fits<ResolveType, size>::check(value))
9006 value = func();
9007 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
9008 *stream = Fits<ResolveType, size>::convert(value);
9009 }
9010
9011 template<typename Functor>
9012 void setLocalScopeDepth(unsigned value, Functor func)
9013 {
9014 if (isWide32())
9015 setLocalScopeDepth<OpcodeSize::Wide32>(value, func);
9016 else if (isWide16())
9017 setLocalScopeDepth<OpcodeSize::Wide16>(value, func);
9018 else
9019 setLocalScopeDepth<OpcodeSize::Narrow>(value, func);
9020 }
9021
9022 template <OpcodeSize size, typename Functor>
9023 void setLocalScopeDepth(unsigned value, Functor func)
9024 {
9025 if (!Fits<unsigned, size>::check(value))
9026 value = func();
9027 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
9028 *stream = Fits<unsigned, size>::convert(value);
9029 }
9030
9031 struct Metadata {
9032 WTF_MAKE_NONCOPYABLE(Metadata);
9033
9034 public:
9035 Metadata(const OpResolveScope&) { }
9036
9037 ResolveType m_resolveType;
9038 union {
9039 unsigned m_localScopeDepth;
9040 unsigned m_globalLexicalBindingEpoch;
9041 };
9042 union {
9043 WriteBarrierBase<JSCell> m_lexicalEnvironment;
9044 WriteBarrierBase<SymbolTable> m_symbolTable;
9045 WriteBarrierBase<JSScope> m_constantScope;
9046 JSGlobalLexicalEnvironment* m_globalLexicalEnvironment;
9047 JSGlobalObject* m_globalObject;
9048 };
9049 };
9050
9051 Metadata& metadata(CodeBlock* codeBlock) const
9052 {
9053 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
9054 }
9055
9056 Metadata& metadata(ExecState* exec) const
9057 {
9058 return metadata(exec->codeBlock());
9059 }
9060
9061 VirtualRegister m_dst;
9062 VirtualRegister m_scope;
9063 unsigned m_var;
9064 ResolveType m_resolveType;
9065 unsigned m_localScopeDepth;
9066 unsigned m_metadataID;
9067};
9068
9069struct OpGetFromScope : public Instruction {
9070 static constexpr OpcodeID opcodeID = op_get_from_scope;
9071
9072 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
9073 {
9074 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset);
9075 }
9076
9077 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
9078 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
9079 {
9080 auto __metadataID = gen->addMetadataFor(opcodeID);
9081 return emit<size, shouldAssert>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
9082 }
9083
9084 template<OpcodeSize size>
9085 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
9086 {
9087 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
9088 return checkImpl<size>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
9089 }
9090
9091 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
9092 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset, unsigned __metadataID)
9093 {
9094 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
9095 if (shouldAssert == Assert)
9096 ASSERT(didEmit);
9097 return didEmit;
9098 }
9099
9100 template<OpcodeSize size>
9101 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
9102 {
9103
9104 auto __metadataID = gen->addMetadataFor(opcodeID);
9105 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
9106 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID))
9107 return;
9108 }
9109 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
9110 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID))
9111 return;
9112 }
9113 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
9114 }
9115
9116private:
9117 template<OpcodeSize size>
9118 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& var, GetPutInfo& getPutInfo, unsigned& localScopeDepth, unsigned& offset, unsigned __metadataID)
9119 {
9120 UNUSED_PARAM(gen);
9121#if OS(WINDOWS) && ENABLE(C_LOOP)
9122 // FIXME: Disable wide16 optimization for Windows CLoop
9123 // https://bugs.webkit.org/show_bug.cgi?id=198283
9124 if (size == OpcodeSize::Wide16)
9125 return false;
9126#endif
9127 return Fits<OpcodeID, size>::check(opcodeID)
9128 && Fits<VirtualRegister, size>::check(dst)
9129 && Fits<VirtualRegister, size>::check(scope)
9130 && Fits<unsigned, size>::check(var)
9131 && Fits<GetPutInfo, size>::check(getPutInfo)
9132 && Fits<unsigned, size>::check(localScopeDepth)
9133 && Fits<unsigned, size>::check(offset)
9134 && Fits<unsigned, size>::check(__metadataID)
9135 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
9136 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
9137 }
9138
9139 template<OpcodeSize size, bool recordOpcode>
9140 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset, unsigned __metadataID)
9141 {
9142 if (size == OpcodeSize::Wide16)
9143 gen->alignWideOpcode16();
9144 else if (size == OpcodeSize::Wide32)
9145 gen->alignWideOpcode32();
9146 if (checkImpl<size>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID)) {
9147 if (recordOpcode)
9148 gen->recordOpcode(opcodeID);
9149 if (size == OpcodeSize::Wide16)
9150 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
9151 else if (size == OpcodeSize::Wide32)
9152 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
9153 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
9154 gen->write(Fits<VirtualRegister, size>::convert(dst));
9155 gen->write(Fits<VirtualRegister, size>::convert(scope));
9156 gen->write(Fits<unsigned, size>::convert(var));
9157 gen->write(Fits<GetPutInfo, size>::convert(getPutInfo));
9158 gen->write(Fits<unsigned, size>::convert(localScopeDepth));
9159 gen->write(Fits<unsigned, size>::convert(offset));
9160 gen->write(Fits<unsigned, size>::convert(__metadataID));
9161 return true;
9162 }
9163 return false;
9164 }
9165
9166public:
9167 template<typename Block>
9168 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
9169 {
9170 dumper->printLocationAndOp(__location, &"**get_from_scope"[2 - __sizeShiftAmount]);
9171 dumper->dumpOperand(m_dst, true);
9172 dumper->dumpOperand(m_scope, false);
9173 dumper->dumpOperand(m_var, false);
9174 dumper->dumpOperand(m_getPutInfo, false);
9175 dumper->dumpOperand(m_localScopeDepth, false);
9176 dumper->dumpOperand(m_offset, false);
9177 }
9178
9179 OpGetFromScope(const uint8_t* stream)
9180 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
9181 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
9182 , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
9183 , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[4]))
9184 , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
9185 , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
9186 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
9187 {
9188 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9189 }
9190
9191 OpGetFromScope(const uint16_t* stream)
9192 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
9193 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
9194 , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
9195 , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide16>::convert(stream[4]))
9196 , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
9197 , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
9198 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
9199 {
9200 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9201 }
9202
9203
9204 OpGetFromScope(const uint32_t* stream)
9205 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
9206 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
9207 , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
9208 , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide32>::convert(stream[4]))
9209 , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
9210 , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
9211 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
9212 {
9213 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9214 }
9215
9216 static OpGetFromScope decode(const uint8_t* stream)
9217 {
9218 if (*stream == op_wide32)
9219 return { bitwise_cast<const uint32_t*>(stream + 1) };
9220 if (*stream == op_wide16)
9221 return { bitwise_cast<const uint16_t*>(stream + 1) };
9222 return { stream };
9223 }
9224
9225 template<typename Functor>
9226 void setDst(VirtualRegister value, Functor func)
9227 {
9228 if (isWide32())
9229 setDst<OpcodeSize::Wide32>(value, func);
9230 else if (isWide16())
9231 setDst<OpcodeSize::Wide16>(value, func);
9232 else
9233 setDst<OpcodeSize::Narrow>(value, func);
9234 }
9235
9236 template <OpcodeSize size, typename Functor>
9237 void setDst(VirtualRegister value, Functor func)
9238 {
9239 if (!Fits<VirtualRegister, size>::check(value))
9240 value = func();
9241 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
9242 *stream = Fits<VirtualRegister, size>::convert(value);
9243 }
9244
9245 template<typename Functor>
9246 void setScope(VirtualRegister value, Functor func)
9247 {
9248 if (isWide32())
9249 setScope<OpcodeSize::Wide32>(value, func);
9250 else if (isWide16())
9251 setScope<OpcodeSize::Wide16>(value, func);
9252 else
9253 setScope<OpcodeSize::Narrow>(value, func);
9254 }
9255
9256 template <OpcodeSize size, typename Functor>
9257 void setScope(VirtualRegister value, Functor func)
9258 {
9259 if (!Fits<VirtualRegister, size>::check(value))
9260 value = func();
9261 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
9262 *stream = Fits<VirtualRegister, size>::convert(value);
9263 }
9264
9265 template<typename Functor>
9266 void setVar(unsigned value, Functor func)
9267 {
9268 if (isWide32())
9269 setVar<OpcodeSize::Wide32>(value, func);
9270 else if (isWide16())
9271 setVar<OpcodeSize::Wide16>(value, func);
9272 else
9273 setVar<OpcodeSize::Narrow>(value, func);
9274 }
9275
9276 template <OpcodeSize size, typename Functor>
9277 void setVar(unsigned value, Functor func)
9278 {
9279 if (!Fits<unsigned, size>::check(value))
9280 value = func();
9281 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
9282 *stream = Fits<unsigned, size>::convert(value);
9283 }
9284
9285 template<typename Functor>
9286 void setGetPutInfo(GetPutInfo value, Functor func)
9287 {
9288 if (isWide32())
9289 setGetPutInfo<OpcodeSize::Wide32>(value, func);
9290 else if (isWide16())
9291 setGetPutInfo<OpcodeSize::Wide16>(value, func);
9292 else
9293 setGetPutInfo<OpcodeSize::Narrow>(value, func);
9294 }
9295
9296 template <OpcodeSize size, typename Functor>
9297 void setGetPutInfo(GetPutInfo value, Functor func)
9298 {
9299 if (!Fits<GetPutInfo, size>::check(value))
9300 value = func();
9301 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
9302 *stream = Fits<GetPutInfo, size>::convert(value);
9303 }
9304
9305 template<typename Functor>
9306 void setLocalScopeDepth(unsigned value, Functor func)
9307 {
9308 if (isWide32())
9309 setLocalScopeDepth<OpcodeSize::Wide32>(value, func);
9310 else if (isWide16())
9311 setLocalScopeDepth<OpcodeSize::Wide16>(value, func);
9312 else
9313 setLocalScopeDepth<OpcodeSize::Narrow>(value, func);
9314 }
9315
9316 template <OpcodeSize size, typename Functor>
9317 void setLocalScopeDepth(unsigned value, Functor func)
9318 {
9319 if (!Fits<unsigned, size>::check(value))
9320 value = func();
9321 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
9322 *stream = Fits<unsigned, size>::convert(value);
9323 }
9324
9325 template<typename Functor>
9326 void setOffset(unsigned value, Functor func)
9327 {
9328 if (isWide32())
9329 setOffset<OpcodeSize::Wide32>(value, func);
9330 else if (isWide16())
9331 setOffset<OpcodeSize::Wide16>(value, func);
9332 else
9333 setOffset<OpcodeSize::Narrow>(value, func);
9334 }
9335
9336 template <OpcodeSize size, typename Functor>
9337 void setOffset(unsigned value, Functor func)
9338 {
9339 if (!Fits<unsigned, size>::check(value))
9340 value = func();
9341 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value);
9342 *stream = Fits<unsigned, size>::convert(value);
9343 }
9344
9345 struct Metadata {
9346 WTF_MAKE_NONCOPYABLE(Metadata);
9347
9348 public:
9349 Metadata(const OpGetFromScope& __op)
9350 : m_getPutInfo(__op.m_getPutInfo)
9351 , m_operand(__op.m_offset)
9352 { }
9353
9354 GetPutInfo m_getPutInfo;
9355 union {
9356 WatchpointSet* m_watchpointSet;
9357 WriteBarrierBase<Structure> m_structure;
9358 };
9359 uintptr_t m_operand;
9360 ValueProfile m_profile;
9361 };
9362
9363 Metadata& metadata(CodeBlock* codeBlock) const
9364 {
9365 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
9366 }
9367
9368 Metadata& metadata(ExecState* exec) const
9369 {
9370 return metadata(exec->codeBlock());
9371 }
9372
9373 VirtualRegister m_dst;
9374 VirtualRegister m_scope;
9375 unsigned m_var;
9376 GetPutInfo m_getPutInfo;
9377 unsigned m_localScopeDepth;
9378 unsigned m_offset;
9379 unsigned m_metadataID;
9380};
9381
9382struct OpPutToScope : public Instruction {
9383 static constexpr OpcodeID opcodeID = op_put_to_scope;
9384
9385 static void emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
9386 {
9387 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset);
9388 }
9389
9390 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
9391 static bool emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
9392 {
9393 auto __metadataID = gen->addMetadataFor(opcodeID);
9394 return emit<size, shouldAssert>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
9395 }
9396
9397 template<OpcodeSize size>
9398 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
9399 {
9400 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
9401 return checkImpl<size>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
9402 }
9403
9404 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
9405 static bool emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset, unsigned __metadataID)
9406 {
9407 bool didEmit = emitImpl<size, recordOpcode>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
9408 if (shouldAssert == Assert)
9409 ASSERT(didEmit);
9410 return didEmit;
9411 }
9412
9413 template<OpcodeSize size>
9414 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
9415 {
9416
9417 auto __metadataID = gen->addMetadataFor(opcodeID);
9418 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
9419 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID))
9420 return;
9421 }
9422 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
9423 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID))
9424 return;
9425 }
9426 emit<OpcodeSize::Wide32, Assert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
9427 }
9428
9429private:
9430 template<OpcodeSize size>
9431 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& scope, unsigned& var, VirtualRegister& value, GetPutInfo& getPutInfo, SymbolTableOrScopeDepth& symbolTableOrScopeDepth, unsigned& offset, unsigned __metadataID)
9432 {
9433 UNUSED_PARAM(gen);
9434#if OS(WINDOWS) && ENABLE(C_LOOP)
9435 // FIXME: Disable wide16 optimization for Windows CLoop
9436 // https://bugs.webkit.org/show_bug.cgi?id=198283
9437 if (size == OpcodeSize::Wide16)
9438 return false;
9439#endif
9440 return Fits<OpcodeID, size>::check(opcodeID)
9441 && Fits<VirtualRegister, size>::check(scope)
9442 && Fits<unsigned, size>::check(var)
9443 && Fits<VirtualRegister, size>::check(value)
9444 && Fits<GetPutInfo, size>::check(getPutInfo)
9445 && Fits<SymbolTableOrScopeDepth, size>::check(symbolTableOrScopeDepth)
9446 && Fits<unsigned, size>::check(offset)
9447 && Fits<unsigned, size>::check(__metadataID)
9448 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
9449 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
9450 }
9451
9452 template<OpcodeSize size, bool recordOpcode>
9453 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset, unsigned __metadataID)
9454 {
9455 if (size == OpcodeSize::Wide16)
9456 gen->alignWideOpcode16();
9457 else if (size == OpcodeSize::Wide32)
9458 gen->alignWideOpcode32();
9459 if (checkImpl<size>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID)) {
9460 if (recordOpcode)
9461 gen->recordOpcode(opcodeID);
9462 if (size == OpcodeSize::Wide16)
9463 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
9464 else if (size == OpcodeSize::Wide32)
9465 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
9466 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
9467 gen->write(Fits<VirtualRegister, size>::convert(scope));
9468 gen->write(Fits<unsigned, size>::convert(var));
9469 gen->write(Fits<VirtualRegister, size>::convert(value));
9470 gen->write(Fits<GetPutInfo, size>::convert(getPutInfo));
9471 gen->write(Fits<SymbolTableOrScopeDepth, size>::convert(symbolTableOrScopeDepth));
9472 gen->write(Fits<unsigned, size>::convert(offset));
9473 gen->write(Fits<unsigned, size>::convert(__metadataID));
9474 return true;
9475 }
9476 return false;
9477 }
9478
9479public:
9480 template<typename Block>
9481 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
9482 {
9483 dumper->printLocationAndOp(__location, &"**put_to_scope"[2 - __sizeShiftAmount]);
9484 dumper->dumpOperand(m_scope, true);
9485 dumper->dumpOperand(m_var, false);
9486 dumper->dumpOperand(m_value, false);
9487 dumper->dumpOperand(m_getPutInfo, false);
9488 dumper->dumpOperand(m_symbolTableOrScopeDepth, false);
9489 dumper->dumpOperand(m_offset, false);
9490 }
9491
9492 OpPutToScope(const uint8_t* stream)
9493 : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
9494 , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
9495 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
9496 , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[4]))
9497 , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Narrow>::convert(stream[5]))
9498 , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
9499 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
9500 {
9501 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9502 }
9503
9504 OpPutToScope(const uint16_t* stream)
9505 : m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
9506 , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
9507 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
9508 , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide16>::convert(stream[4]))
9509 , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide16>::convert(stream[5]))
9510 , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
9511 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
9512 {
9513 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9514 }
9515
9516
9517 OpPutToScope(const uint32_t* stream)
9518 : m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
9519 , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
9520 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
9521 , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide32>::convert(stream[4]))
9522 , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide32>::convert(stream[5]))
9523 , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
9524 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
9525 {
9526 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9527 }
9528
9529 static OpPutToScope decode(const uint8_t* stream)
9530 {
9531 if (*stream == op_wide32)
9532 return { bitwise_cast<const uint32_t*>(stream + 1) };
9533 if (*stream == op_wide16)
9534 return { bitwise_cast<const uint16_t*>(stream + 1) };
9535 return { stream };
9536 }
9537
9538 template<typename Functor>
9539 void setScope(VirtualRegister value, Functor func)
9540 {
9541 if (isWide32())
9542 setScope<OpcodeSize::Wide32>(value, func);
9543 else if (isWide16())
9544 setScope<OpcodeSize::Wide16>(value, func);
9545 else
9546 setScope<OpcodeSize::Narrow>(value, func);
9547 }
9548
9549 template <OpcodeSize size, typename Functor>
9550 void setScope(VirtualRegister value, Functor func)
9551 {
9552 if (!Fits<VirtualRegister, size>::check(value))
9553 value = func();
9554 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
9555 *stream = Fits<VirtualRegister, size>::convert(value);
9556 }
9557
9558 template<typename Functor>
9559 void setVar(unsigned value, Functor func)
9560 {
9561 if (isWide32())
9562 setVar<OpcodeSize::Wide32>(value, func);
9563 else if (isWide16())
9564 setVar<OpcodeSize::Wide16>(value, func);
9565 else
9566 setVar<OpcodeSize::Narrow>(value, func);
9567 }
9568
9569 template <OpcodeSize size, typename Functor>
9570 void setVar(unsigned value, Functor func)
9571 {
9572 if (!Fits<unsigned, size>::check(value))
9573 value = func();
9574 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
9575 *stream = Fits<unsigned, size>::convert(value);
9576 }
9577
9578 template<typename Functor>
9579 void setValue(VirtualRegister value, Functor func)
9580 {
9581 if (isWide32())
9582 setValue<OpcodeSize::Wide32>(value, func);
9583 else if (isWide16())
9584 setValue<OpcodeSize::Wide16>(value, func);
9585 else
9586 setValue<OpcodeSize::Narrow>(value, func);
9587 }
9588
9589 template <OpcodeSize size, typename Functor>
9590 void setValue(VirtualRegister value, Functor func)
9591 {
9592 if (!Fits<VirtualRegister, size>::check(value))
9593 value = func();
9594 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
9595 *stream = Fits<VirtualRegister, size>::convert(value);
9596 }
9597
9598 template<typename Functor>
9599 void setGetPutInfo(GetPutInfo value, Functor func)
9600 {
9601 if (isWide32())
9602 setGetPutInfo<OpcodeSize::Wide32>(value, func);
9603 else if (isWide16())
9604 setGetPutInfo<OpcodeSize::Wide16>(value, func);
9605 else
9606 setGetPutInfo<OpcodeSize::Narrow>(value, func);
9607 }
9608
9609 template <OpcodeSize size, typename Functor>
9610 void setGetPutInfo(GetPutInfo value, Functor func)
9611 {
9612 if (!Fits<GetPutInfo, size>::check(value))
9613 value = func();
9614 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
9615 *stream = Fits<GetPutInfo, size>::convert(value);
9616 }
9617
9618 template<typename Functor>
9619 void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
9620 {
9621 if (isWide32())
9622 setSymbolTableOrScopeDepth<OpcodeSize::Wide32>(value, func);
9623 else if (isWide16())
9624 setSymbolTableOrScopeDepth<OpcodeSize::Wide16>(value, func);
9625 else
9626 setSymbolTableOrScopeDepth<OpcodeSize::Narrow>(value, func);
9627 }
9628
9629 template <OpcodeSize size, typename Functor>
9630 void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
9631 {
9632 if (!Fits<SymbolTableOrScopeDepth, size>::check(value))
9633 value = func();
9634 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
9635 *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value);
9636 }
9637
9638 template<typename Functor>
9639 void setOffset(unsigned value, Functor func)
9640 {
9641 if (isWide32())
9642 setOffset<OpcodeSize::Wide32>(value, func);
9643 else if (isWide16())
9644 setOffset<OpcodeSize::Wide16>(value, func);
9645 else
9646 setOffset<OpcodeSize::Narrow>(value, func);
9647 }
9648
9649 template <OpcodeSize size, typename Functor>
9650 void setOffset(unsigned value, Functor func)
9651 {
9652 if (!Fits<unsigned, size>::check(value))
9653 value = func();
9654 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 6 * size + PaddingBySize<size>::value);
9655 *stream = Fits<unsigned, size>::convert(value);
9656 }
9657
9658 struct Metadata {
9659 WTF_MAKE_NONCOPYABLE(Metadata);
9660
9661 public:
9662 Metadata(const OpPutToScope& __op)
9663 : m_getPutInfo(__op.m_getPutInfo)
9664 , m_operand(__op.m_offset)
9665 { }
9666
9667 GetPutInfo m_getPutInfo;
9668 union {
9669 WriteBarrierBase<Structure> m_structure;
9670 WatchpointSet* m_watchpointSet;
9671 };
9672 uintptr_t m_operand;
9673 };
9674
9675 Metadata& metadata(CodeBlock* codeBlock) const
9676 {
9677 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
9678 }
9679
9680 Metadata& metadata(ExecState* exec) const
9681 {
9682 return metadata(exec->codeBlock());
9683 }
9684
9685 VirtualRegister m_scope;
9686 unsigned m_var;
9687 VirtualRegister m_value;
9688 GetPutInfo m_getPutInfo;
9689 SymbolTableOrScopeDepth m_symbolTableOrScopeDepth;
9690 unsigned m_offset;
9691 unsigned m_metadataID;
9692};
9693
9694struct OpGetFromArguments : public Instruction {
9695 static constexpr OpcodeID opcodeID = op_get_from_arguments;
9696
9697 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
9698 {
9699 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, arguments, index);
9700 }
9701
9702 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
9703 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
9704 {
9705 auto __metadataID = gen->addMetadataFor(opcodeID);
9706 return emit<size, shouldAssert>(gen, dst, arguments, index, __metadataID);
9707 }
9708
9709 template<OpcodeSize size>
9710 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
9711 {
9712 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
9713 return checkImpl<size>(gen, dst, arguments, index, __metadataID);
9714 }
9715
9716 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
9717 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index, unsigned __metadataID)
9718 {
9719 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, arguments, index, __metadataID);
9720 if (shouldAssert == Assert)
9721 ASSERT(didEmit);
9722 return didEmit;
9723 }
9724
9725 template<OpcodeSize size>
9726 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
9727 {
9728
9729 auto __metadataID = gen->addMetadataFor(opcodeID);
9730 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
9731 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, arguments, index, __metadataID))
9732 return;
9733 }
9734 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
9735 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, arguments, index, __metadataID))
9736 return;
9737 }
9738 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, arguments, index, __metadataID);
9739 }
9740
9741private:
9742 template<OpcodeSize size>
9743 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& arguments, unsigned& index, unsigned __metadataID)
9744 {
9745 UNUSED_PARAM(gen);
9746#if OS(WINDOWS) && ENABLE(C_LOOP)
9747 // FIXME: Disable wide16 optimization for Windows CLoop
9748 // https://bugs.webkit.org/show_bug.cgi?id=198283
9749 if (size == OpcodeSize::Wide16)
9750 return false;
9751#endif
9752 return Fits<OpcodeID, size>::check(opcodeID)
9753 && Fits<VirtualRegister, size>::check(dst)
9754 && Fits<VirtualRegister, size>::check(arguments)
9755 && Fits<unsigned, size>::check(index)
9756 && Fits<unsigned, size>::check(__metadataID)
9757 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
9758 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
9759 }
9760
9761 template<OpcodeSize size, bool recordOpcode>
9762 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index, unsigned __metadataID)
9763 {
9764 if (size == OpcodeSize::Wide16)
9765 gen->alignWideOpcode16();
9766 else if (size == OpcodeSize::Wide32)
9767 gen->alignWideOpcode32();
9768 if (checkImpl<size>(gen, dst, arguments, index, __metadataID)) {
9769 if (recordOpcode)
9770 gen->recordOpcode(opcodeID);
9771 if (size == OpcodeSize::Wide16)
9772 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
9773 else if (size == OpcodeSize::Wide32)
9774 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
9775 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
9776 gen->write(Fits<VirtualRegister, size>::convert(dst));
9777 gen->write(Fits<VirtualRegister, size>::convert(arguments));
9778 gen->write(Fits<unsigned, size>::convert(index));
9779 gen->write(Fits<unsigned, size>::convert(__metadataID));
9780 return true;
9781 }
9782 return false;
9783 }
9784
9785public:
9786 template<typename Block>
9787 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
9788 {
9789 dumper->printLocationAndOp(__location, &"**get_from_arguments"[2 - __sizeShiftAmount]);
9790 dumper->dumpOperand(m_dst, true);
9791 dumper->dumpOperand(m_arguments, false);
9792 dumper->dumpOperand(m_index, false);
9793 }
9794
9795 OpGetFromArguments(const uint8_t* stream)
9796 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
9797 , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
9798 , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
9799 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
9800 {
9801 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9802 }
9803
9804 OpGetFromArguments(const uint16_t* stream)
9805 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
9806 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
9807 , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
9808 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
9809 {
9810 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9811 }
9812
9813
9814 OpGetFromArguments(const uint32_t* stream)
9815 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
9816 , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
9817 , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
9818 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
9819 {
9820 ASSERT_UNUSED(stream, stream[0] == opcodeID);
9821 }
9822
9823 static OpGetFromArguments decode(const uint8_t* stream)
9824 {
9825 if (*stream == op_wide32)
9826 return { bitwise_cast<const uint32_t*>(stream + 1) };
9827 if (*stream == op_wide16)
9828 return { bitwise_cast<const uint16_t*>(stream + 1) };
9829 return { stream };
9830 }
9831
9832 template<typename Functor>
9833 void setDst(VirtualRegister value, Functor func)
9834 {
9835 if (isWide32())
9836 setDst<OpcodeSize::Wide32>(value, func);
9837 else if (isWide16())
9838 setDst<OpcodeSize::Wide16>(value, func);
9839 else
9840 setDst<OpcodeSize::Narrow>(value, func);
9841 }
9842
9843 template <OpcodeSize size, typename Functor>
9844 void setDst(VirtualRegister value, Functor func)
9845 {
9846 if (!Fits<VirtualRegister, size>::check(value))
9847 value = func();
9848 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
9849 *stream = Fits<VirtualRegister, size>::convert(value);
9850 }
9851
9852 template<typename Functor>
9853 void setArguments(VirtualRegister value, Functor func)
9854 {
9855 if (isWide32())
9856 setArguments<OpcodeSize::Wide32>(value, func);
9857 else if (isWide16())
9858 setArguments<OpcodeSize::Wide16>(value, func);
9859 else
9860 setArguments<OpcodeSize::Narrow>(value, func);
9861 }
9862
9863 template <OpcodeSize size, typename Functor>
9864 void setArguments(VirtualRegister value, Functor func)
9865 {
9866 if (!Fits<VirtualRegister, size>::check(value))
9867 value = func();
9868 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
9869 *stream = Fits<VirtualRegister, size>::convert(value);
9870 }
9871
9872 template<typename Functor>
9873 void setIndex(unsigned value, Functor func)
9874 {
9875 if (isWide32())
9876 setIndex<OpcodeSize::Wide32>(value, func);
9877 else if (isWide16())
9878 setIndex<OpcodeSize::Wide16>(value, func);
9879 else
9880 setIndex<OpcodeSize::Narrow>(value, func);
9881 }
9882
9883 template <OpcodeSize size, typename Functor>
9884 void setIndex(unsigned value, Functor func)
9885 {
9886 if (!Fits<unsigned, size>::check(value))
9887 value = func();
9888 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
9889 *stream = Fits<unsigned, size>::convert(value);
9890 }
9891
9892 struct Metadata {
9893 WTF_MAKE_NONCOPYABLE(Metadata);
9894
9895 public:
9896 Metadata(const OpGetFromArguments&) { }
9897
9898 ValueProfile m_profile;
9899 };
9900
9901 Metadata& metadata(CodeBlock* codeBlock) const
9902 {
9903 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
9904 }
9905
9906 Metadata& metadata(ExecState* exec) const
9907 {
9908 return metadata(exec->codeBlock());
9909 }
9910
9911 VirtualRegister m_dst;
9912 VirtualRegister m_arguments;
9913 unsigned m_index;
9914 unsigned m_metadataID;
9915};
9916
9917struct OpCatch : public Instruction {
9918 static constexpr OpcodeID opcodeID = op_catch;
9919
9920 static void emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
9921 {
9922 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, exception, thrownValue);
9923 }
9924
9925 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
9926 static bool emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
9927 {
9928 auto __metadataID = gen->addMetadataFor(opcodeID);
9929 return emit<size, shouldAssert>(gen, exception, thrownValue, __metadataID);
9930 }
9931
9932 template<OpcodeSize size>
9933 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
9934 {
9935 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
9936 return checkImpl<size>(gen, exception, thrownValue, __metadataID);
9937 }
9938
9939 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
9940 static bool emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue, unsigned __metadataID)
9941 {
9942 bool didEmit = emitImpl<size, recordOpcode>(gen, exception, thrownValue, __metadataID);
9943 if (shouldAssert == Assert)
9944 ASSERT(didEmit);
9945 return didEmit;
9946 }
9947
9948 template<OpcodeSize size>
9949 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
9950 {
9951
9952 auto __metadataID = gen->addMetadataFor(opcodeID);
9953 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
9954 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, exception, thrownValue, __metadataID))
9955 return;
9956 }
9957 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
9958 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, exception, thrownValue, __metadataID))
9959 return;
9960 }
9961 emit<OpcodeSize::Wide32, Assert, true>(gen, exception, thrownValue, __metadataID);
9962 }
9963
9964private:
9965 template<OpcodeSize size>
9966 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& exception, VirtualRegister& thrownValue, unsigned __metadataID)
9967 {
9968 UNUSED_PARAM(gen);
9969#if OS(WINDOWS) && ENABLE(C_LOOP)
9970 // FIXME: Disable wide16 optimization for Windows CLoop
9971 // https://bugs.webkit.org/show_bug.cgi?id=198283
9972 if (size == OpcodeSize::Wide16)
9973 return false;
9974#endif
9975 return Fits<OpcodeID, size>::check(opcodeID)
9976 && Fits<VirtualRegister, size>::check(exception)
9977 && Fits<VirtualRegister, size>::check(thrownValue)
9978 && Fits<unsigned, size>::check(__metadataID)
9979 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
9980 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
9981 }
9982
9983 template<OpcodeSize size, bool recordOpcode>
9984 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue, unsigned __metadataID)
9985 {
9986 if (size == OpcodeSize::Wide16)
9987 gen->alignWideOpcode16();
9988 else if (size == OpcodeSize::Wide32)
9989 gen->alignWideOpcode32();
9990 if (checkImpl<size>(gen, exception, thrownValue, __metadataID)) {
9991 if (recordOpcode)
9992 gen->recordOpcode(opcodeID);
9993 if (size == OpcodeSize::Wide16)
9994 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
9995 else if (size == OpcodeSize::Wide32)
9996 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
9997 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
9998 gen->write(Fits<VirtualRegister, size>::convert(exception));
9999 gen->write(Fits<VirtualRegister, size>::convert(thrownValue));
10000 gen->write(Fits<unsigned, size>::convert(__metadataID));
10001 return true;
10002 }
10003 return false;
10004 }
10005
10006public:
10007 template<typename Block>
10008 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
10009 {
10010 dumper->printLocationAndOp(__location, &"**catch"[2 - __sizeShiftAmount]);
10011 dumper->dumpOperand(m_exception, true);
10012 dumper->dumpOperand(m_thrownValue, false);
10013 }
10014
10015 OpCatch(const uint8_t* stream)
10016 : m_exception(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
10017 , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
10018 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
10019 {
10020 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10021 }
10022
10023 OpCatch(const uint16_t* stream)
10024 : m_exception(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
10025 , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
10026 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
10027 {
10028 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10029 }
10030
10031
10032 OpCatch(const uint32_t* stream)
10033 : m_exception(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
10034 , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
10035 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
10036 {
10037 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10038 }
10039
10040 static OpCatch decode(const uint8_t* stream)
10041 {
10042 if (*stream == op_wide32)
10043 return { bitwise_cast<const uint32_t*>(stream + 1) };
10044 if (*stream == op_wide16)
10045 return { bitwise_cast<const uint16_t*>(stream + 1) };
10046 return { stream };
10047 }
10048
10049 template<typename Functor>
10050 void setException(VirtualRegister value, Functor func)
10051 {
10052 if (isWide32())
10053 setException<OpcodeSize::Wide32>(value, func);
10054 else if (isWide16())
10055 setException<OpcodeSize::Wide16>(value, func);
10056 else
10057 setException<OpcodeSize::Narrow>(value, func);
10058 }
10059
10060 template <OpcodeSize size, typename Functor>
10061 void setException(VirtualRegister value, Functor func)
10062 {
10063 if (!Fits<VirtualRegister, size>::check(value))
10064 value = func();
10065 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
10066 *stream = Fits<VirtualRegister, size>::convert(value);
10067 }
10068
10069 template<typename Functor>
10070 void setThrownValue(VirtualRegister value, Functor func)
10071 {
10072 if (isWide32())
10073 setThrownValue<OpcodeSize::Wide32>(value, func);
10074 else if (isWide16())
10075 setThrownValue<OpcodeSize::Wide16>(value, func);
10076 else
10077 setThrownValue<OpcodeSize::Narrow>(value, func);
10078 }
10079
10080 template <OpcodeSize size, typename Functor>
10081 void setThrownValue(VirtualRegister value, Functor func)
10082 {
10083 if (!Fits<VirtualRegister, size>::check(value))
10084 value = func();
10085 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
10086 *stream = Fits<VirtualRegister, size>::convert(value);
10087 }
10088
10089 struct Metadata {
10090 WTF_MAKE_NONCOPYABLE(Metadata);
10091
10092 public:
10093 Metadata(const OpCatch&) { }
10094
10095 ValueProfileAndOperandBuffer* m_buffer;
10096 };
10097
10098 Metadata& metadata(CodeBlock* codeBlock) const
10099 {
10100 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
10101 }
10102
10103 Metadata& metadata(ExecState* exec) const
10104 {
10105 return metadata(exec->codeBlock());
10106 }
10107
10108 VirtualRegister m_exception;
10109 VirtualRegister m_thrownValue;
10110 unsigned m_metadataID;
10111};
10112
10113struct OpProfileType : public Instruction {
10114 static constexpr OpcodeID opcodeID = op_profile_type;
10115
10116 static void emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
10117 {
10118 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType);
10119 }
10120
10121 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
10122 static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
10123 {
10124 auto __metadataID = gen->addMetadataFor(opcodeID);
10125 return emit<size, shouldAssert>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
10126 }
10127
10128 template<OpcodeSize size>
10129 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
10130 {
10131 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
10132 return checkImpl<size>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
10133 }
10134
10135 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
10136 static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType, unsigned __metadataID)
10137 {
10138 bool didEmit = emitImpl<size, recordOpcode>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
10139 if (shouldAssert == Assert)
10140 ASSERT(didEmit);
10141 return didEmit;
10142 }
10143
10144 template<OpcodeSize size>
10145 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
10146 {
10147
10148 auto __metadataID = gen->addMetadataFor(opcodeID);
10149 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
10150 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID))
10151 return;
10152 }
10153 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
10154 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID))
10155 return;
10156 }
10157 emit<OpcodeSize::Wide32, Assert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
10158 }
10159
10160private:
10161 template<OpcodeSize size>
10162 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& targetVirtualRegister, SymbolTableOrScopeDepth& symbolTableOrScopeDepth, ProfileTypeBytecodeFlag& flag, unsigned& identifier, ResolveType& resolveType, unsigned __metadataID)
10163 {
10164 UNUSED_PARAM(gen);
10165#if OS(WINDOWS) && ENABLE(C_LOOP)
10166 // FIXME: Disable wide16 optimization for Windows CLoop
10167 // https://bugs.webkit.org/show_bug.cgi?id=198283
10168 if (size == OpcodeSize::Wide16)
10169 return false;
10170#endif
10171 return Fits<OpcodeID, size>::check(opcodeID)
10172 && Fits<VirtualRegister, size>::check(targetVirtualRegister)
10173 && Fits<SymbolTableOrScopeDepth, size>::check(symbolTableOrScopeDepth)
10174 && Fits<ProfileTypeBytecodeFlag, size>::check(flag)
10175 && Fits<unsigned, size>::check(identifier)
10176 && Fits<ResolveType, size>::check(resolveType)
10177 && Fits<unsigned, size>::check(__metadataID)
10178 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
10179 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
10180 }
10181
10182 template<OpcodeSize size, bool recordOpcode>
10183 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType, unsigned __metadataID)
10184 {
10185 if (size == OpcodeSize::Wide16)
10186 gen->alignWideOpcode16();
10187 else if (size == OpcodeSize::Wide32)
10188 gen->alignWideOpcode32();
10189 if (checkImpl<size>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID)) {
10190 if (recordOpcode)
10191 gen->recordOpcode(opcodeID);
10192 if (size == OpcodeSize::Wide16)
10193 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
10194 else if (size == OpcodeSize::Wide32)
10195 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
10196 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
10197 gen->write(Fits<VirtualRegister, size>::convert(targetVirtualRegister));
10198 gen->write(Fits<SymbolTableOrScopeDepth, size>::convert(symbolTableOrScopeDepth));
10199 gen->write(Fits<ProfileTypeBytecodeFlag, size>::convert(flag));
10200 gen->write(Fits<unsigned, size>::convert(identifier));
10201 gen->write(Fits<ResolveType, size>::convert(resolveType));
10202 gen->write(Fits<unsigned, size>::convert(__metadataID));
10203 return true;
10204 }
10205 return false;
10206 }
10207
10208public:
10209 template<typename Block>
10210 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
10211 {
10212 dumper->printLocationAndOp(__location, &"**profile_type"[2 - __sizeShiftAmount]);
10213 dumper->dumpOperand(m_targetVirtualRegister, true);
10214 dumper->dumpOperand(m_symbolTableOrScopeDepth, false);
10215 dumper->dumpOperand(m_flag, false);
10216 dumper->dumpOperand(m_identifier, false);
10217 dumper->dumpOperand(m_resolveType, false);
10218 }
10219
10220 OpProfileType(const uint8_t* stream)
10221 : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
10222 , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Narrow>::convert(stream[2]))
10223 , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Narrow>::convert(stream[3]))
10224 , m_identifier(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
10225 , m_resolveType(Fits<ResolveType, OpcodeSize::Narrow>::convert(stream[5]))
10226 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
10227 {
10228 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10229 }
10230
10231 OpProfileType(const uint16_t* stream)
10232 : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
10233 , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide16>::convert(stream[2]))
10234 , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Wide16>::convert(stream[3]))
10235 , m_identifier(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
10236 , m_resolveType(Fits<ResolveType, OpcodeSize::Wide16>::convert(stream[5]))
10237 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
10238 {
10239 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10240 }
10241
10242
10243 OpProfileType(const uint32_t* stream)
10244 : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
10245 , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide32>::convert(stream[2]))
10246 , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Wide32>::convert(stream[3]))
10247 , m_identifier(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
10248 , m_resolveType(Fits<ResolveType, OpcodeSize::Wide32>::convert(stream[5]))
10249 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
10250 {
10251 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10252 }
10253
10254 static OpProfileType decode(const uint8_t* stream)
10255 {
10256 if (*stream == op_wide32)
10257 return { bitwise_cast<const uint32_t*>(stream + 1) };
10258 if (*stream == op_wide16)
10259 return { bitwise_cast<const uint16_t*>(stream + 1) };
10260 return { stream };
10261 }
10262
10263 template<typename Functor>
10264 void setTargetVirtualRegister(VirtualRegister value, Functor func)
10265 {
10266 if (isWide32())
10267 setTargetVirtualRegister<OpcodeSize::Wide32>(value, func);
10268 else if (isWide16())
10269 setTargetVirtualRegister<OpcodeSize::Wide16>(value, func);
10270 else
10271 setTargetVirtualRegister<OpcodeSize::Narrow>(value, func);
10272 }
10273
10274 template <OpcodeSize size, typename Functor>
10275 void setTargetVirtualRegister(VirtualRegister value, Functor func)
10276 {
10277 if (!Fits<VirtualRegister, size>::check(value))
10278 value = func();
10279 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
10280 *stream = Fits<VirtualRegister, size>::convert(value);
10281 }
10282
10283 template<typename Functor>
10284 void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
10285 {
10286 if (isWide32())
10287 setSymbolTableOrScopeDepth<OpcodeSize::Wide32>(value, func);
10288 else if (isWide16())
10289 setSymbolTableOrScopeDepth<OpcodeSize::Wide16>(value, func);
10290 else
10291 setSymbolTableOrScopeDepth<OpcodeSize::Narrow>(value, func);
10292 }
10293
10294 template <OpcodeSize size, typename Functor>
10295 void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
10296 {
10297 if (!Fits<SymbolTableOrScopeDepth, size>::check(value))
10298 value = func();
10299 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
10300 *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value);
10301 }
10302
10303 template<typename Functor>
10304 void setFlag(ProfileTypeBytecodeFlag value, Functor func)
10305 {
10306 if (isWide32())
10307 setFlag<OpcodeSize::Wide32>(value, func);
10308 else if (isWide16())
10309 setFlag<OpcodeSize::Wide16>(value, func);
10310 else
10311 setFlag<OpcodeSize::Narrow>(value, func);
10312 }
10313
10314 template <OpcodeSize size, typename Functor>
10315 void setFlag(ProfileTypeBytecodeFlag value, Functor func)
10316 {
10317 if (!Fits<ProfileTypeBytecodeFlag, size>::check(value))
10318 value = func();
10319 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
10320 *stream = Fits<ProfileTypeBytecodeFlag, size>::convert(value);
10321 }
10322
10323 template<typename Functor>
10324 void setIdentifier(unsigned value, Functor func)
10325 {
10326 if (isWide32())
10327 setIdentifier<OpcodeSize::Wide32>(value, func);
10328 else if (isWide16())
10329 setIdentifier<OpcodeSize::Wide16>(value, func);
10330 else
10331 setIdentifier<OpcodeSize::Narrow>(value, func);
10332 }
10333
10334 template <OpcodeSize size, typename Functor>
10335 void setIdentifier(unsigned value, Functor func)
10336 {
10337 if (!Fits<unsigned, size>::check(value))
10338 value = func();
10339 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
10340 *stream = Fits<unsigned, size>::convert(value);
10341 }
10342
10343 template<typename Functor>
10344 void setResolveType(ResolveType value, Functor func)
10345 {
10346 if (isWide32())
10347 setResolveType<OpcodeSize::Wide32>(value, func);
10348 else if (isWide16())
10349 setResolveType<OpcodeSize::Wide16>(value, func);
10350 else
10351 setResolveType<OpcodeSize::Narrow>(value, func);
10352 }
10353
10354 template <OpcodeSize size, typename Functor>
10355 void setResolveType(ResolveType value, Functor func)
10356 {
10357 if (!Fits<ResolveType, size>::check(value))
10358 value = func();
10359 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
10360 *stream = Fits<ResolveType, size>::convert(value);
10361 }
10362
10363 struct Metadata {
10364 WTF_MAKE_NONCOPYABLE(Metadata);
10365
10366 public:
10367 Metadata(const OpProfileType&) { }
10368
10369 TypeLocation* m_typeLocation;
10370 };
10371
10372 Metadata& metadata(CodeBlock* codeBlock) const
10373 {
10374 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
10375 }
10376
10377 Metadata& metadata(ExecState* exec) const
10378 {
10379 return metadata(exec->codeBlock());
10380 }
10381
10382 VirtualRegister m_targetVirtualRegister;
10383 SymbolTableOrScopeDepth m_symbolTableOrScopeDepth;
10384 ProfileTypeBytecodeFlag m_flag;
10385 unsigned m_identifier;
10386 ResolveType m_resolveType;
10387 unsigned m_metadataID;
10388};
10389
10390struct OpProfileControlFlow : public Instruction {
10391 static constexpr OpcodeID opcodeID = op_profile_control_flow;
10392
10393 static void emit(BytecodeGenerator* gen, int textOffset)
10394 {
10395 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, textOffset);
10396 }
10397
10398 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
10399 static bool emit(BytecodeGenerator* gen, int textOffset)
10400 {
10401 auto __metadataID = gen->addMetadataFor(opcodeID);
10402 return emit<size, shouldAssert>(gen, textOffset, __metadataID);
10403 }
10404
10405 template<OpcodeSize size>
10406 static bool checkWithoutMetadataID(BytecodeGenerator* gen, int textOffset)
10407 {
10408 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
10409 return checkImpl<size>(gen, textOffset, __metadataID);
10410 }
10411
10412 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
10413 static bool emit(BytecodeGenerator* gen, int textOffset, unsigned __metadataID)
10414 {
10415 bool didEmit = emitImpl<size, recordOpcode>(gen, textOffset, __metadataID);
10416 if (shouldAssert == Assert)
10417 ASSERT(didEmit);
10418 return didEmit;
10419 }
10420
10421 template<OpcodeSize size>
10422 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, int textOffset)
10423 {
10424
10425 auto __metadataID = gen->addMetadataFor(opcodeID);
10426 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
10427 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, textOffset, __metadataID))
10428 return;
10429 }
10430 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
10431 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, textOffset, __metadataID))
10432 return;
10433 }
10434 emit<OpcodeSize::Wide32, Assert, true>(gen, textOffset, __metadataID);
10435 }
10436
10437private:
10438 template<OpcodeSize size>
10439 static bool checkImpl(BytecodeGenerator* gen, int& textOffset, unsigned __metadataID)
10440 {
10441 UNUSED_PARAM(gen);
10442#if OS(WINDOWS) && ENABLE(C_LOOP)
10443 // FIXME: Disable wide16 optimization for Windows CLoop
10444 // https://bugs.webkit.org/show_bug.cgi?id=198283
10445 if (size == OpcodeSize::Wide16)
10446 return false;
10447#endif
10448 return Fits<OpcodeID, size>::check(opcodeID)
10449 && Fits<int, size>::check(textOffset)
10450 && Fits<unsigned, size>::check(__metadataID)
10451 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
10452 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
10453 }
10454
10455 template<OpcodeSize size, bool recordOpcode>
10456 static bool emitImpl(BytecodeGenerator* gen, int textOffset, unsigned __metadataID)
10457 {
10458 if (size == OpcodeSize::Wide16)
10459 gen->alignWideOpcode16();
10460 else if (size == OpcodeSize::Wide32)
10461 gen->alignWideOpcode32();
10462 if (checkImpl<size>(gen, textOffset, __metadataID)) {
10463 if (recordOpcode)
10464 gen->recordOpcode(opcodeID);
10465 if (size == OpcodeSize::Wide16)
10466 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
10467 else if (size == OpcodeSize::Wide32)
10468 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
10469 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
10470 gen->write(Fits<int, size>::convert(textOffset));
10471 gen->write(Fits<unsigned, size>::convert(__metadataID));
10472 return true;
10473 }
10474 return false;
10475 }
10476
10477public:
10478 template<typename Block>
10479 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
10480 {
10481 dumper->printLocationAndOp(__location, &"**profile_control_flow"[2 - __sizeShiftAmount]);
10482 dumper->dumpOperand(m_textOffset, true);
10483 }
10484
10485 OpProfileControlFlow(const uint8_t* stream)
10486 : m_textOffset(Fits<int, OpcodeSize::Narrow>::convert(stream[1]))
10487 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
10488 {
10489 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10490 }
10491
10492 OpProfileControlFlow(const uint16_t* stream)
10493 : m_textOffset(Fits<int, OpcodeSize::Wide16>::convert(stream[1]))
10494 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
10495 {
10496 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10497 }
10498
10499
10500 OpProfileControlFlow(const uint32_t* stream)
10501 : m_textOffset(Fits<int, OpcodeSize::Wide32>::convert(stream[1]))
10502 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
10503 {
10504 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10505 }
10506
10507 static OpProfileControlFlow decode(const uint8_t* stream)
10508 {
10509 if (*stream == op_wide32)
10510 return { bitwise_cast<const uint32_t*>(stream + 1) };
10511 if (*stream == op_wide16)
10512 return { bitwise_cast<const uint16_t*>(stream + 1) };
10513 return { stream };
10514 }
10515
10516 template<typename Functor>
10517 void setTextOffset(int value, Functor func)
10518 {
10519 if (isWide32())
10520 setTextOffset<OpcodeSize::Wide32>(value, func);
10521 else if (isWide16())
10522 setTextOffset<OpcodeSize::Wide16>(value, func);
10523 else
10524 setTextOffset<OpcodeSize::Narrow>(value, func);
10525 }
10526
10527 template <OpcodeSize size, typename Functor>
10528 void setTextOffset(int value, Functor func)
10529 {
10530 if (!Fits<int, size>::check(value))
10531 value = func();
10532 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
10533 *stream = Fits<int, size>::convert(value);
10534 }
10535
10536 struct Metadata {
10537 WTF_MAKE_NONCOPYABLE(Metadata);
10538
10539 public:
10540 Metadata(const OpProfileControlFlow&) { }
10541
10542 BasicBlockLocation* m_basicBlockLocation;
10543 };
10544
10545 Metadata& metadata(CodeBlock* codeBlock) const
10546 {
10547 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
10548 }
10549
10550 Metadata& metadata(ExecState* exec) const
10551 {
10552 return metadata(exec->codeBlock());
10553 }
10554
10555 int m_textOffset;
10556 unsigned m_metadataID;
10557};
10558
10559struct OpHasIndexedProperty : public Instruction {
10560 static constexpr OpcodeID opcodeID = op_has_indexed_property;
10561
10562 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
10563 {
10564 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
10565 }
10566
10567 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
10568 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
10569 {
10570 auto __metadataID = gen->addMetadataFor(opcodeID);
10571 return emit<size, shouldAssert>(gen, dst, base, property, __metadataID);
10572 }
10573
10574 template<OpcodeSize size>
10575 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
10576 {
10577 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
10578 return checkImpl<size>(gen, dst, base, property, __metadataID);
10579 }
10580
10581 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
10582 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
10583 {
10584 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, __metadataID);
10585 if (shouldAssert == Assert)
10586 ASSERT(didEmit);
10587 return didEmit;
10588 }
10589
10590 template<OpcodeSize size>
10591 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
10592 {
10593
10594 auto __metadataID = gen->addMetadataFor(opcodeID);
10595 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
10596 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, __metadataID))
10597 return;
10598 }
10599 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
10600 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
10601 return;
10602 }
10603 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
10604 }
10605
10606private:
10607 template<OpcodeSize size>
10608 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, unsigned __metadataID)
10609 {
10610 UNUSED_PARAM(gen);
10611#if OS(WINDOWS) && ENABLE(C_LOOP)
10612 // FIXME: Disable wide16 optimization for Windows CLoop
10613 // https://bugs.webkit.org/show_bug.cgi?id=198283
10614 if (size == OpcodeSize::Wide16)
10615 return false;
10616#endif
10617 return Fits<OpcodeID, size>::check(opcodeID)
10618 && Fits<VirtualRegister, size>::check(dst)
10619 && Fits<VirtualRegister, size>::check(base)
10620 && Fits<VirtualRegister, size>::check(property)
10621 && Fits<unsigned, size>::check(__metadataID)
10622 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
10623 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
10624 }
10625
10626 template<OpcodeSize size, bool recordOpcode>
10627 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
10628 {
10629 if (size == OpcodeSize::Wide16)
10630 gen->alignWideOpcode16();
10631 else if (size == OpcodeSize::Wide32)
10632 gen->alignWideOpcode32();
10633 if (checkImpl<size>(gen, dst, base, property, __metadataID)) {
10634 if (recordOpcode)
10635 gen->recordOpcode(opcodeID);
10636 if (size == OpcodeSize::Wide16)
10637 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
10638 else if (size == OpcodeSize::Wide32)
10639 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
10640 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
10641 gen->write(Fits<VirtualRegister, size>::convert(dst));
10642 gen->write(Fits<VirtualRegister, size>::convert(base));
10643 gen->write(Fits<VirtualRegister, size>::convert(property));
10644 gen->write(Fits<unsigned, size>::convert(__metadataID));
10645 return true;
10646 }
10647 return false;
10648 }
10649
10650public:
10651 template<typename Block>
10652 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
10653 {
10654 dumper->printLocationAndOp(__location, &"**has_indexed_property"[2 - __sizeShiftAmount]);
10655 dumper->dumpOperand(m_dst, true);
10656 dumper->dumpOperand(m_base, false);
10657 dumper->dumpOperand(m_property, false);
10658 }
10659
10660 OpHasIndexedProperty(const uint8_t* stream)
10661 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
10662 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
10663 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
10664 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
10665 {
10666 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10667 }
10668
10669 OpHasIndexedProperty(const uint16_t* stream)
10670 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
10671 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
10672 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
10673 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
10674 {
10675 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10676 }
10677
10678
10679 OpHasIndexedProperty(const uint32_t* stream)
10680 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
10681 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
10682 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
10683 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
10684 {
10685 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10686 }
10687
10688 static OpHasIndexedProperty decode(const uint8_t* stream)
10689 {
10690 if (*stream == op_wide32)
10691 return { bitwise_cast<const uint32_t*>(stream + 1) };
10692 if (*stream == op_wide16)
10693 return { bitwise_cast<const uint16_t*>(stream + 1) };
10694 return { stream };
10695 }
10696
10697 template<typename Functor>
10698 void setDst(VirtualRegister value, Functor func)
10699 {
10700 if (isWide32())
10701 setDst<OpcodeSize::Wide32>(value, func);
10702 else if (isWide16())
10703 setDst<OpcodeSize::Wide16>(value, func);
10704 else
10705 setDst<OpcodeSize::Narrow>(value, func);
10706 }
10707
10708 template <OpcodeSize size, typename Functor>
10709 void setDst(VirtualRegister value, Functor func)
10710 {
10711 if (!Fits<VirtualRegister, size>::check(value))
10712 value = func();
10713 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
10714 *stream = Fits<VirtualRegister, size>::convert(value);
10715 }
10716
10717 template<typename Functor>
10718 void setBase(VirtualRegister value, Functor func)
10719 {
10720 if (isWide32())
10721 setBase<OpcodeSize::Wide32>(value, func);
10722 else if (isWide16())
10723 setBase<OpcodeSize::Wide16>(value, func);
10724 else
10725 setBase<OpcodeSize::Narrow>(value, func);
10726 }
10727
10728 template <OpcodeSize size, typename Functor>
10729 void setBase(VirtualRegister value, Functor func)
10730 {
10731 if (!Fits<VirtualRegister, size>::check(value))
10732 value = func();
10733 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
10734 *stream = Fits<VirtualRegister, size>::convert(value);
10735 }
10736
10737 template<typename Functor>
10738 void setProperty(VirtualRegister value, Functor func)
10739 {
10740 if (isWide32())
10741 setProperty<OpcodeSize::Wide32>(value, func);
10742 else if (isWide16())
10743 setProperty<OpcodeSize::Wide16>(value, func);
10744 else
10745 setProperty<OpcodeSize::Narrow>(value, func);
10746 }
10747
10748 template <OpcodeSize size, typename Functor>
10749 void setProperty(VirtualRegister value, Functor func)
10750 {
10751 if (!Fits<VirtualRegister, size>::check(value))
10752 value = func();
10753 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
10754 *stream = Fits<VirtualRegister, size>::convert(value);
10755 }
10756
10757 struct Metadata {
10758 WTF_MAKE_NONCOPYABLE(Metadata);
10759
10760 public:
10761 Metadata(const OpHasIndexedProperty&) { }
10762
10763 ArrayProfile m_arrayProfile;
10764 };
10765
10766 Metadata& metadata(CodeBlock* codeBlock) const
10767 {
10768 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
10769 }
10770
10771 Metadata& metadata(ExecState* exec) const
10772 {
10773 return metadata(exec->codeBlock());
10774 }
10775
10776 VirtualRegister m_dst;
10777 VirtualRegister m_base;
10778 VirtualRegister m_property;
10779 unsigned m_metadataID;
10780};
10781
10782struct OpGetDirectPname : public Instruction {
10783 static constexpr OpcodeID opcodeID = op_get_direct_pname;
10784
10785 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
10786 {
10787 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property, index, enumerator);
10788 }
10789
10790 template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
10791 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
10792 {
10793 auto __metadataID = gen->addMetadataFor(opcodeID);
10794 return emit<size, shouldAssert>(gen, dst, base, property, index, enumerator, __metadataID);
10795 }
10796
10797 template<OpcodeSize size>
10798 static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
10799 {
10800 decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
10801 return checkImpl<size>(gen, dst, base, property, index, enumerator, __metadataID);
10802 }
10803
10804 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
10805 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator, unsigned __metadataID)
10806 {
10807 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, index, enumerator, __metadataID);
10808 if (shouldAssert == Assert)
10809 ASSERT(didEmit);
10810 return didEmit;
10811 }
10812
10813 template<OpcodeSize size>
10814 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
10815 {
10816
10817 auto __metadataID = gen->addMetadataFor(opcodeID);
10818 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
10819 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, index, enumerator, __metadataID))
10820 return;
10821 }
10822 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
10823 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, index, enumerator, __metadataID))
10824 return;
10825 }
10826 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, index, enumerator, __metadataID);
10827 }
10828
10829private:
10830 template<OpcodeSize size>
10831 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, VirtualRegister& index, VirtualRegister& enumerator, unsigned __metadataID)
10832 {
10833 UNUSED_PARAM(gen);
10834#if OS(WINDOWS) && ENABLE(C_LOOP)
10835 // FIXME: Disable wide16 optimization for Windows CLoop
10836 // https://bugs.webkit.org/show_bug.cgi?id=198283
10837 if (size == OpcodeSize::Wide16)
10838 return false;
10839#endif
10840 return Fits<OpcodeID, size>::check(opcodeID)
10841 && Fits<VirtualRegister, size>::check(dst)
10842 && Fits<VirtualRegister, size>::check(base)
10843 && Fits<VirtualRegister, size>::check(property)
10844 && Fits<VirtualRegister, size>::check(index)
10845 && Fits<VirtualRegister, size>::check(enumerator)
10846 && Fits<unsigned, size>::check(__metadataID)
10847 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
10848 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
10849 }
10850
10851 template<OpcodeSize size, bool recordOpcode>
10852 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator, unsigned __metadataID)
10853 {
10854 if (size == OpcodeSize::Wide16)
10855 gen->alignWideOpcode16();
10856 else if (size == OpcodeSize::Wide32)
10857 gen->alignWideOpcode32();
10858 if (checkImpl<size>(gen, dst, base, property, index, enumerator, __metadataID)) {
10859 if (recordOpcode)
10860 gen->recordOpcode(opcodeID);
10861 if (size == OpcodeSize::Wide16)
10862 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
10863 else if (size == OpcodeSize::Wide32)
10864 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
10865 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
10866 gen->write(Fits<VirtualRegister, size>::convert(dst));
10867 gen->write(Fits<VirtualRegister, size>::convert(base));
10868 gen->write(Fits<VirtualRegister, size>::convert(property));
10869 gen->write(Fits<VirtualRegister, size>::convert(index));
10870 gen->write(Fits<VirtualRegister, size>::convert(enumerator));
10871 gen->write(Fits<unsigned, size>::convert(__metadataID));
10872 return true;
10873 }
10874 return false;
10875 }
10876
10877public:
10878 template<typename Block>
10879 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
10880 {
10881 dumper->printLocationAndOp(__location, &"**get_direct_pname"[2 - __sizeShiftAmount]);
10882 dumper->dumpOperand(m_dst, true);
10883 dumper->dumpOperand(m_base, false);
10884 dumper->dumpOperand(m_property, false);
10885 dumper->dumpOperand(m_index, false);
10886 dumper->dumpOperand(m_enumerator, false);
10887 }
10888
10889 OpGetDirectPname(const uint8_t* stream)
10890 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
10891 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
10892 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
10893 , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
10894 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
10895 , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
10896 {
10897 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10898 }
10899
10900 OpGetDirectPname(const uint16_t* stream)
10901 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
10902 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
10903 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
10904 , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
10905 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
10906 , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
10907 {
10908 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10909 }
10910
10911
10912 OpGetDirectPname(const uint32_t* stream)
10913 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
10914 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
10915 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
10916 , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
10917 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
10918 , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
10919 {
10920 ASSERT_UNUSED(stream, stream[0] == opcodeID);
10921 }
10922
10923 static OpGetDirectPname decode(const uint8_t* stream)
10924 {
10925 if (*stream == op_wide32)
10926 return { bitwise_cast<const uint32_t*>(stream + 1) };
10927 if (*stream == op_wide16)
10928 return { bitwise_cast<const uint16_t*>(stream + 1) };
10929 return { stream };
10930 }
10931
10932 template<typename Functor>
10933 void setDst(VirtualRegister value, Functor func)
10934 {
10935 if (isWide32())
10936 setDst<OpcodeSize::Wide32>(value, func);
10937 else if (isWide16())
10938 setDst<OpcodeSize::Wide16>(value, func);
10939 else
10940 setDst<OpcodeSize::Narrow>(value, func);
10941 }
10942
10943 template <OpcodeSize size, typename Functor>
10944 void setDst(VirtualRegister value, Functor func)
10945 {
10946 if (!Fits<VirtualRegister, size>::check(value))
10947 value = func();
10948 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
10949 *stream = Fits<VirtualRegister, size>::convert(value);
10950 }
10951
10952 template<typename Functor>
10953 void setBase(VirtualRegister value, Functor func)
10954 {
10955 if (isWide32())
10956 setBase<OpcodeSize::Wide32>(value, func);
10957 else if (isWide16())
10958 setBase<OpcodeSize::Wide16>(value, func);
10959 else
10960 setBase<OpcodeSize::Narrow>(value, func);
10961 }
10962
10963 template <OpcodeSize size, typename Functor>
10964 void setBase(VirtualRegister value, Functor func)
10965 {
10966 if (!Fits<VirtualRegister, size>::check(value))
10967 value = func();
10968 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
10969 *stream = Fits<VirtualRegister, size>::convert(value);
10970 }
10971
10972 template<typename Functor>
10973 void setProperty(VirtualRegister value, Functor func)
10974 {
10975 if (isWide32())
10976 setProperty<OpcodeSize::Wide32>(value, func);
10977 else if (isWide16())
10978 setProperty<OpcodeSize::Wide16>(value, func);
10979 else
10980 setProperty<OpcodeSize::Narrow>(value, func);
10981 }
10982
10983 template <OpcodeSize size, typename Functor>
10984 void setProperty(VirtualRegister value, Functor func)
10985 {
10986 if (!Fits<VirtualRegister, size>::check(value))
10987 value = func();
10988 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
10989 *stream = Fits<VirtualRegister, size>::convert(value);
10990 }
10991
10992 template<typename Functor>
10993 void setIndex(VirtualRegister value, Functor func)
10994 {
10995 if (isWide32())
10996 setIndex<OpcodeSize::Wide32>(value, func);
10997 else if (isWide16())
10998 setIndex<OpcodeSize::Wide16>(value, func);
10999 else
11000 setIndex<OpcodeSize::Narrow>(value, func);
11001 }
11002
11003 template <OpcodeSize size, typename Functor>
11004 void setIndex(VirtualRegister value, Functor func)
11005 {
11006 if (!Fits<VirtualRegister, size>::check(value))
11007 value = func();
11008 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
11009 *stream = Fits<VirtualRegister, size>::convert(value);
11010 }
11011
11012 template<typename Functor>
11013 void setEnumerator(VirtualRegister value, Functor func)
11014 {
11015 if (isWide32())
11016 setEnumerator<OpcodeSize::Wide32>(value, func);
11017 else if (isWide16())
11018 setEnumerator<OpcodeSize::Wide16>(value, func);
11019 else
11020 setEnumerator<OpcodeSize::Narrow>(value, func);
11021 }
11022
11023 template <OpcodeSize size, typename Functor>
11024 void setEnumerator(VirtualRegister value, Functor func)
11025 {
11026 if (!Fits<VirtualRegister, size>::check(value))
11027 value = func();
11028 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
11029 *stream = Fits<VirtualRegister, size>::convert(value);
11030 }
11031
11032 struct Metadata {
11033 WTF_MAKE_NONCOPYABLE(Metadata);
11034
11035 public:
11036 Metadata(const OpGetDirectPname&) { }
11037
11038 ValueProfile m_profile;
11039 };
11040
11041 Metadata& metadata(CodeBlock* codeBlock) const
11042 {
11043 return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
11044 }
11045
11046 Metadata& metadata(ExecState* exec) const
11047 {
11048 return metadata(exec->codeBlock());
11049 }
11050
11051 VirtualRegister m_dst;
11052 VirtualRegister m_base;
11053 VirtualRegister m_property;
11054 VirtualRegister m_index;
11055 VirtualRegister m_enumerator;
11056 unsigned m_metadataID;
11057};
11058
11059struct OpWide16 : public Instruction {
11060 static constexpr OpcodeID opcodeID = op_wide16;
11061
11062 static void emit(BytecodeGenerator* gen)
11063 {
11064 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
11065 }
11066
11067 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11068 static bool emit(BytecodeGenerator* gen)
11069 {
11070 bool didEmit = emitImpl<size, recordOpcode>(gen);
11071 if (shouldAssert == Assert)
11072 ASSERT(didEmit);
11073 return didEmit;
11074 }
11075
11076 template<OpcodeSize size>
11077 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
11078 {
11079
11080 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11081 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
11082 return;
11083 }
11084 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11085 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
11086 return;
11087 }
11088 emit<OpcodeSize::Wide32, Assert, true>(gen);
11089 }
11090
11091private:
11092 template<OpcodeSize size>
11093 static bool checkImpl(BytecodeGenerator* gen)
11094 {
11095 UNUSED_PARAM(gen);
11096#if OS(WINDOWS) && ENABLE(C_LOOP)
11097 // FIXME: Disable wide16 optimization for Windows CLoop
11098 // https://bugs.webkit.org/show_bug.cgi?id=198283
11099 if (size == OpcodeSize::Wide16)
11100 return false;
11101#endif
11102 return Fits<OpcodeID, size>::check(opcodeID)
11103 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11104 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11105 }
11106
11107 template<OpcodeSize size, bool recordOpcode>
11108 static bool emitImpl(BytecodeGenerator* gen)
11109 {
11110 if (size == OpcodeSize::Wide16)
11111 gen->alignWideOpcode16();
11112 else if (size == OpcodeSize::Wide32)
11113 gen->alignWideOpcode32();
11114 if (checkImpl<size>(gen)) {
11115 if (recordOpcode)
11116 gen->recordOpcode(opcodeID);
11117 if (size == OpcodeSize::Wide16)
11118 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11119 else if (size == OpcodeSize::Wide32)
11120 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11121 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11122 return true;
11123 }
11124 return false;
11125 }
11126
11127public:
11128 template<typename Block>
11129 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11130 {
11131 dumper->printLocationAndOp(__location, &"**wide16"[2 - __sizeShiftAmount]);
11132
11133 }
11134
11135 OpWide16(const uint8_t* stream)
11136
11137 {
11138 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11139 }
11140
11141 OpWide16(const uint16_t* stream)
11142
11143 {
11144 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11145 }
11146
11147
11148 OpWide16(const uint32_t* stream)
11149
11150 {
11151 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11152 }
11153
11154 static OpWide16 decode(const uint8_t* stream)
11155 {
11156 if (*stream == op_wide32)
11157 return { bitwise_cast<const uint32_t*>(stream + 1) };
11158 if (*stream == op_wide16)
11159 return { bitwise_cast<const uint16_t*>(stream + 1) };
11160 return { stream };
11161 }
11162
11163
11164
11165};
11166
11167struct OpWide32 : public Instruction {
11168 static constexpr OpcodeID opcodeID = op_wide32;
11169
11170 static void emit(BytecodeGenerator* gen)
11171 {
11172 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
11173 }
11174
11175 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11176 static bool emit(BytecodeGenerator* gen)
11177 {
11178 bool didEmit = emitImpl<size, recordOpcode>(gen);
11179 if (shouldAssert == Assert)
11180 ASSERT(didEmit);
11181 return didEmit;
11182 }
11183
11184 template<OpcodeSize size>
11185 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
11186 {
11187
11188 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11189 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
11190 return;
11191 }
11192 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11193 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
11194 return;
11195 }
11196 emit<OpcodeSize::Wide32, Assert, true>(gen);
11197 }
11198
11199private:
11200 template<OpcodeSize size>
11201 static bool checkImpl(BytecodeGenerator* gen)
11202 {
11203 UNUSED_PARAM(gen);
11204#if OS(WINDOWS) && ENABLE(C_LOOP)
11205 // FIXME: Disable wide16 optimization for Windows CLoop
11206 // https://bugs.webkit.org/show_bug.cgi?id=198283
11207 if (size == OpcodeSize::Wide16)
11208 return false;
11209#endif
11210 return Fits<OpcodeID, size>::check(opcodeID)
11211 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11212 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11213 }
11214
11215 template<OpcodeSize size, bool recordOpcode>
11216 static bool emitImpl(BytecodeGenerator* gen)
11217 {
11218 if (size == OpcodeSize::Wide16)
11219 gen->alignWideOpcode16();
11220 else if (size == OpcodeSize::Wide32)
11221 gen->alignWideOpcode32();
11222 if (checkImpl<size>(gen)) {
11223 if (recordOpcode)
11224 gen->recordOpcode(opcodeID);
11225 if (size == OpcodeSize::Wide16)
11226 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11227 else if (size == OpcodeSize::Wide32)
11228 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11229 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11230 return true;
11231 }
11232 return false;
11233 }
11234
11235public:
11236 template<typename Block>
11237 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11238 {
11239 dumper->printLocationAndOp(__location, &"**wide32"[2 - __sizeShiftAmount]);
11240
11241 }
11242
11243 OpWide32(const uint8_t* stream)
11244
11245 {
11246 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11247 }
11248
11249 OpWide32(const uint16_t* stream)
11250
11251 {
11252 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11253 }
11254
11255
11256 OpWide32(const uint32_t* stream)
11257
11258 {
11259 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11260 }
11261
11262 static OpWide32 decode(const uint8_t* stream)
11263 {
11264 if (*stream == op_wide32)
11265 return { bitwise_cast<const uint32_t*>(stream + 1) };
11266 if (*stream == op_wide16)
11267 return { bitwise_cast<const uint16_t*>(stream + 1) };
11268 return { stream };
11269 }
11270
11271
11272
11273};
11274
11275struct OpEnter : public Instruction {
11276 static constexpr OpcodeID opcodeID = op_enter;
11277
11278 static void emit(BytecodeGenerator* gen)
11279 {
11280 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
11281 }
11282
11283 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11284 static bool emit(BytecodeGenerator* gen)
11285 {
11286 bool didEmit = emitImpl<size, recordOpcode>(gen);
11287 if (shouldAssert == Assert)
11288 ASSERT(didEmit);
11289 return didEmit;
11290 }
11291
11292 template<OpcodeSize size>
11293 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
11294 {
11295
11296 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11297 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
11298 return;
11299 }
11300 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11301 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
11302 return;
11303 }
11304 emit<OpcodeSize::Wide32, Assert, true>(gen);
11305 }
11306
11307private:
11308 template<OpcodeSize size>
11309 static bool checkImpl(BytecodeGenerator* gen)
11310 {
11311 UNUSED_PARAM(gen);
11312#if OS(WINDOWS) && ENABLE(C_LOOP)
11313 // FIXME: Disable wide16 optimization for Windows CLoop
11314 // https://bugs.webkit.org/show_bug.cgi?id=198283
11315 if (size == OpcodeSize::Wide16)
11316 return false;
11317#endif
11318 return Fits<OpcodeID, size>::check(opcodeID)
11319 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11320 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11321 }
11322
11323 template<OpcodeSize size, bool recordOpcode>
11324 static bool emitImpl(BytecodeGenerator* gen)
11325 {
11326 if (size == OpcodeSize::Wide16)
11327 gen->alignWideOpcode16();
11328 else if (size == OpcodeSize::Wide32)
11329 gen->alignWideOpcode32();
11330 if (checkImpl<size>(gen)) {
11331 if (recordOpcode)
11332 gen->recordOpcode(opcodeID);
11333 if (size == OpcodeSize::Wide16)
11334 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11335 else if (size == OpcodeSize::Wide32)
11336 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11337 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11338 return true;
11339 }
11340 return false;
11341 }
11342
11343public:
11344 template<typename Block>
11345 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11346 {
11347 dumper->printLocationAndOp(__location, &"**enter"[2 - __sizeShiftAmount]);
11348
11349 }
11350
11351 OpEnter(const uint8_t* stream)
11352
11353 {
11354 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11355 }
11356
11357 OpEnter(const uint16_t* stream)
11358
11359 {
11360 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11361 }
11362
11363
11364 OpEnter(const uint32_t* stream)
11365
11366 {
11367 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11368 }
11369
11370 static OpEnter decode(const uint8_t* stream)
11371 {
11372 if (*stream == op_wide32)
11373 return { bitwise_cast<const uint32_t*>(stream + 1) };
11374 if (*stream == op_wide16)
11375 return { bitwise_cast<const uint16_t*>(stream + 1) };
11376 return { stream };
11377 }
11378
11379
11380
11381};
11382
11383struct OpGetScope : public Instruction {
11384 static constexpr OpcodeID opcodeID = op_get_scope;
11385
11386 static void emit(BytecodeGenerator* gen, VirtualRegister dst)
11387 {
11388 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst);
11389 }
11390
11391 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11392 static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
11393 {
11394 bool didEmit = emitImpl<size, recordOpcode>(gen, dst);
11395 if (shouldAssert == Assert)
11396 ASSERT(didEmit);
11397 return didEmit;
11398 }
11399
11400 template<OpcodeSize size>
11401 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
11402 {
11403
11404 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11405 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
11406 return;
11407 }
11408 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11409 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
11410 return;
11411 }
11412 emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
11413 }
11414
11415private:
11416 template<OpcodeSize size>
11417 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
11418 {
11419 UNUSED_PARAM(gen);
11420#if OS(WINDOWS) && ENABLE(C_LOOP)
11421 // FIXME: Disable wide16 optimization for Windows CLoop
11422 // https://bugs.webkit.org/show_bug.cgi?id=198283
11423 if (size == OpcodeSize::Wide16)
11424 return false;
11425#endif
11426 return Fits<OpcodeID, size>::check(opcodeID)
11427 && Fits<VirtualRegister, size>::check(dst)
11428 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11429 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11430 }
11431
11432 template<OpcodeSize size, bool recordOpcode>
11433 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
11434 {
11435 if (size == OpcodeSize::Wide16)
11436 gen->alignWideOpcode16();
11437 else if (size == OpcodeSize::Wide32)
11438 gen->alignWideOpcode32();
11439 if (checkImpl<size>(gen, dst)) {
11440 if (recordOpcode)
11441 gen->recordOpcode(opcodeID);
11442 if (size == OpcodeSize::Wide16)
11443 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11444 else if (size == OpcodeSize::Wide32)
11445 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11446 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11447 gen->write(Fits<VirtualRegister, size>::convert(dst));
11448 return true;
11449 }
11450 return false;
11451 }
11452
11453public:
11454 template<typename Block>
11455 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11456 {
11457 dumper->printLocationAndOp(__location, &"**get_scope"[2 - __sizeShiftAmount]);
11458 dumper->dumpOperand(m_dst, true);
11459 }
11460
11461 OpGetScope(const uint8_t* stream)
11462 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
11463 {
11464 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11465 }
11466
11467 OpGetScope(const uint16_t* stream)
11468 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
11469 {
11470 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11471 }
11472
11473
11474 OpGetScope(const uint32_t* stream)
11475 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
11476 {
11477 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11478 }
11479
11480 static OpGetScope decode(const uint8_t* stream)
11481 {
11482 if (*stream == op_wide32)
11483 return { bitwise_cast<const uint32_t*>(stream + 1) };
11484 if (*stream == op_wide16)
11485 return { bitwise_cast<const uint16_t*>(stream + 1) };
11486 return { stream };
11487 }
11488
11489 template<typename Functor>
11490 void setDst(VirtualRegister value, Functor func)
11491 {
11492 if (isWide32())
11493 setDst<OpcodeSize::Wide32>(value, func);
11494 else if (isWide16())
11495 setDst<OpcodeSize::Wide16>(value, func);
11496 else
11497 setDst<OpcodeSize::Narrow>(value, func);
11498 }
11499
11500 template <OpcodeSize size, typename Functor>
11501 void setDst(VirtualRegister value, Functor func)
11502 {
11503 if (!Fits<VirtualRegister, size>::check(value))
11504 value = func();
11505 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
11506 *stream = Fits<VirtualRegister, size>::convert(value);
11507 }
11508
11509 VirtualRegister m_dst;
11510};
11511
11512struct OpCreateDirectArguments : public Instruction {
11513 static constexpr OpcodeID opcodeID = op_create_direct_arguments;
11514
11515 static void emit(BytecodeGenerator* gen, VirtualRegister dst)
11516 {
11517 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst);
11518 }
11519
11520 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11521 static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
11522 {
11523 bool didEmit = emitImpl<size, recordOpcode>(gen, dst);
11524 if (shouldAssert == Assert)
11525 ASSERT(didEmit);
11526 return didEmit;
11527 }
11528
11529 template<OpcodeSize size>
11530 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
11531 {
11532
11533 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11534 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
11535 return;
11536 }
11537 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11538 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
11539 return;
11540 }
11541 emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
11542 }
11543
11544private:
11545 template<OpcodeSize size>
11546 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
11547 {
11548 UNUSED_PARAM(gen);
11549#if OS(WINDOWS) && ENABLE(C_LOOP)
11550 // FIXME: Disable wide16 optimization for Windows CLoop
11551 // https://bugs.webkit.org/show_bug.cgi?id=198283
11552 if (size == OpcodeSize::Wide16)
11553 return false;
11554#endif
11555 return Fits<OpcodeID, size>::check(opcodeID)
11556 && Fits<VirtualRegister, size>::check(dst)
11557 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11558 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11559 }
11560
11561 template<OpcodeSize size, bool recordOpcode>
11562 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
11563 {
11564 if (size == OpcodeSize::Wide16)
11565 gen->alignWideOpcode16();
11566 else if (size == OpcodeSize::Wide32)
11567 gen->alignWideOpcode32();
11568 if (checkImpl<size>(gen, dst)) {
11569 if (recordOpcode)
11570 gen->recordOpcode(opcodeID);
11571 if (size == OpcodeSize::Wide16)
11572 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11573 else if (size == OpcodeSize::Wide32)
11574 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11575 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11576 gen->write(Fits<VirtualRegister, size>::convert(dst));
11577 return true;
11578 }
11579 return false;
11580 }
11581
11582public:
11583 template<typename Block>
11584 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11585 {
11586 dumper->printLocationAndOp(__location, &"**create_direct_arguments"[2 - __sizeShiftAmount]);
11587 dumper->dumpOperand(m_dst, true);
11588 }
11589
11590 OpCreateDirectArguments(const uint8_t* stream)
11591 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
11592 {
11593 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11594 }
11595
11596 OpCreateDirectArguments(const uint16_t* stream)
11597 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
11598 {
11599 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11600 }
11601
11602
11603 OpCreateDirectArguments(const uint32_t* stream)
11604 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
11605 {
11606 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11607 }
11608
11609 static OpCreateDirectArguments decode(const uint8_t* stream)
11610 {
11611 if (*stream == op_wide32)
11612 return { bitwise_cast<const uint32_t*>(stream + 1) };
11613 if (*stream == op_wide16)
11614 return { bitwise_cast<const uint16_t*>(stream + 1) };
11615 return { stream };
11616 }
11617
11618 template<typename Functor>
11619 void setDst(VirtualRegister value, Functor func)
11620 {
11621 if (isWide32())
11622 setDst<OpcodeSize::Wide32>(value, func);
11623 else if (isWide16())
11624 setDst<OpcodeSize::Wide16>(value, func);
11625 else
11626 setDst<OpcodeSize::Narrow>(value, func);
11627 }
11628
11629 template <OpcodeSize size, typename Functor>
11630 void setDst(VirtualRegister value, Functor func)
11631 {
11632 if (!Fits<VirtualRegister, size>::check(value))
11633 value = func();
11634 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
11635 *stream = Fits<VirtualRegister, size>::convert(value);
11636 }
11637
11638 VirtualRegister m_dst;
11639};
11640
11641struct OpCreateScopedArguments : public Instruction {
11642 static constexpr OpcodeID opcodeID = op_create_scoped_arguments;
11643
11644 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
11645 {
11646 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope);
11647 }
11648
11649 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11650 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
11651 {
11652 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope);
11653 if (shouldAssert == Assert)
11654 ASSERT(didEmit);
11655 return didEmit;
11656 }
11657
11658 template<OpcodeSize size>
11659 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
11660 {
11661
11662 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11663 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope))
11664 return;
11665 }
11666 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11667 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope))
11668 return;
11669 }
11670 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope);
11671 }
11672
11673private:
11674 template<OpcodeSize size>
11675 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope)
11676 {
11677 UNUSED_PARAM(gen);
11678#if OS(WINDOWS) && ENABLE(C_LOOP)
11679 // FIXME: Disable wide16 optimization for Windows CLoop
11680 // https://bugs.webkit.org/show_bug.cgi?id=198283
11681 if (size == OpcodeSize::Wide16)
11682 return false;
11683#endif
11684 return Fits<OpcodeID, size>::check(opcodeID)
11685 && Fits<VirtualRegister, size>::check(dst)
11686 && Fits<VirtualRegister, size>::check(scope)
11687 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11688 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11689 }
11690
11691 template<OpcodeSize size, bool recordOpcode>
11692 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
11693 {
11694 if (size == OpcodeSize::Wide16)
11695 gen->alignWideOpcode16();
11696 else if (size == OpcodeSize::Wide32)
11697 gen->alignWideOpcode32();
11698 if (checkImpl<size>(gen, dst, scope)) {
11699 if (recordOpcode)
11700 gen->recordOpcode(opcodeID);
11701 if (size == OpcodeSize::Wide16)
11702 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11703 else if (size == OpcodeSize::Wide32)
11704 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11705 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11706 gen->write(Fits<VirtualRegister, size>::convert(dst));
11707 gen->write(Fits<VirtualRegister, size>::convert(scope));
11708 return true;
11709 }
11710 return false;
11711 }
11712
11713public:
11714 template<typename Block>
11715 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11716 {
11717 dumper->printLocationAndOp(__location, &"**create_scoped_arguments"[2 - __sizeShiftAmount]);
11718 dumper->dumpOperand(m_dst, true);
11719 dumper->dumpOperand(m_scope, false);
11720 }
11721
11722 OpCreateScopedArguments(const uint8_t* stream)
11723 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
11724 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
11725 {
11726 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11727 }
11728
11729 OpCreateScopedArguments(const uint16_t* stream)
11730 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
11731 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
11732 {
11733 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11734 }
11735
11736
11737 OpCreateScopedArguments(const uint32_t* stream)
11738 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
11739 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
11740 {
11741 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11742 }
11743
11744 static OpCreateScopedArguments decode(const uint8_t* stream)
11745 {
11746 if (*stream == op_wide32)
11747 return { bitwise_cast<const uint32_t*>(stream + 1) };
11748 if (*stream == op_wide16)
11749 return { bitwise_cast<const uint16_t*>(stream + 1) };
11750 return { stream };
11751 }
11752
11753 template<typename Functor>
11754 void setDst(VirtualRegister value, Functor func)
11755 {
11756 if (isWide32())
11757 setDst<OpcodeSize::Wide32>(value, func);
11758 else if (isWide16())
11759 setDst<OpcodeSize::Wide16>(value, func);
11760 else
11761 setDst<OpcodeSize::Narrow>(value, func);
11762 }
11763
11764 template <OpcodeSize size, typename Functor>
11765 void setDst(VirtualRegister value, Functor func)
11766 {
11767 if (!Fits<VirtualRegister, size>::check(value))
11768 value = func();
11769 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
11770 *stream = Fits<VirtualRegister, size>::convert(value);
11771 }
11772
11773 template<typename Functor>
11774 void setScope(VirtualRegister value, Functor func)
11775 {
11776 if (isWide32())
11777 setScope<OpcodeSize::Wide32>(value, func);
11778 else if (isWide16())
11779 setScope<OpcodeSize::Wide16>(value, func);
11780 else
11781 setScope<OpcodeSize::Narrow>(value, func);
11782 }
11783
11784 template <OpcodeSize size, typename Functor>
11785 void setScope(VirtualRegister value, Functor func)
11786 {
11787 if (!Fits<VirtualRegister, size>::check(value))
11788 value = func();
11789 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
11790 *stream = Fits<VirtualRegister, size>::convert(value);
11791 }
11792
11793 VirtualRegister m_dst;
11794 VirtualRegister m_scope;
11795};
11796
11797struct OpCreateClonedArguments : public Instruction {
11798 static constexpr OpcodeID opcodeID = op_create_cloned_arguments;
11799
11800 static void emit(BytecodeGenerator* gen, VirtualRegister dst)
11801 {
11802 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst);
11803 }
11804
11805 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11806 static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
11807 {
11808 bool didEmit = emitImpl<size, recordOpcode>(gen, dst);
11809 if (shouldAssert == Assert)
11810 ASSERT(didEmit);
11811 return didEmit;
11812 }
11813
11814 template<OpcodeSize size>
11815 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
11816 {
11817
11818 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11819 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
11820 return;
11821 }
11822 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11823 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
11824 return;
11825 }
11826 emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
11827 }
11828
11829private:
11830 template<OpcodeSize size>
11831 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
11832 {
11833 UNUSED_PARAM(gen);
11834#if OS(WINDOWS) && ENABLE(C_LOOP)
11835 // FIXME: Disable wide16 optimization for Windows CLoop
11836 // https://bugs.webkit.org/show_bug.cgi?id=198283
11837 if (size == OpcodeSize::Wide16)
11838 return false;
11839#endif
11840 return Fits<OpcodeID, size>::check(opcodeID)
11841 && Fits<VirtualRegister, size>::check(dst)
11842 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11843 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11844 }
11845
11846 template<OpcodeSize size, bool recordOpcode>
11847 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
11848 {
11849 if (size == OpcodeSize::Wide16)
11850 gen->alignWideOpcode16();
11851 else if (size == OpcodeSize::Wide32)
11852 gen->alignWideOpcode32();
11853 if (checkImpl<size>(gen, dst)) {
11854 if (recordOpcode)
11855 gen->recordOpcode(opcodeID);
11856 if (size == OpcodeSize::Wide16)
11857 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11858 else if (size == OpcodeSize::Wide32)
11859 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11860 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11861 gen->write(Fits<VirtualRegister, size>::convert(dst));
11862 return true;
11863 }
11864 return false;
11865 }
11866
11867public:
11868 template<typename Block>
11869 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11870 {
11871 dumper->printLocationAndOp(__location, &"**create_cloned_arguments"[2 - __sizeShiftAmount]);
11872 dumper->dumpOperand(m_dst, true);
11873 }
11874
11875 OpCreateClonedArguments(const uint8_t* stream)
11876 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
11877 {
11878 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11879 }
11880
11881 OpCreateClonedArguments(const uint16_t* stream)
11882 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
11883 {
11884 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11885 }
11886
11887
11888 OpCreateClonedArguments(const uint32_t* stream)
11889 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
11890 {
11891 ASSERT_UNUSED(stream, stream[0] == opcodeID);
11892 }
11893
11894 static OpCreateClonedArguments decode(const uint8_t* stream)
11895 {
11896 if (*stream == op_wide32)
11897 return { bitwise_cast<const uint32_t*>(stream + 1) };
11898 if (*stream == op_wide16)
11899 return { bitwise_cast<const uint16_t*>(stream + 1) };
11900 return { stream };
11901 }
11902
11903 template<typename Functor>
11904 void setDst(VirtualRegister value, Functor func)
11905 {
11906 if (isWide32())
11907 setDst<OpcodeSize::Wide32>(value, func);
11908 else if (isWide16())
11909 setDst<OpcodeSize::Wide16>(value, func);
11910 else
11911 setDst<OpcodeSize::Narrow>(value, func);
11912 }
11913
11914 template <OpcodeSize size, typename Functor>
11915 void setDst(VirtualRegister value, Functor func)
11916 {
11917 if (!Fits<VirtualRegister, size>::check(value))
11918 value = func();
11919 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
11920 *stream = Fits<VirtualRegister, size>::convert(value);
11921 }
11922
11923 VirtualRegister m_dst;
11924};
11925
11926struct OpArgumentCount : public Instruction {
11927 static constexpr OpcodeID opcodeID = op_argument_count;
11928
11929 static void emit(BytecodeGenerator* gen, VirtualRegister dst)
11930 {
11931 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst);
11932 }
11933
11934 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
11935 static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
11936 {
11937 bool didEmit = emitImpl<size, recordOpcode>(gen, dst);
11938 if (shouldAssert == Assert)
11939 ASSERT(didEmit);
11940 return didEmit;
11941 }
11942
11943 template<OpcodeSize size>
11944 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
11945 {
11946
11947 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
11948 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
11949 return;
11950 }
11951 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
11952 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
11953 return;
11954 }
11955 emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
11956 }
11957
11958private:
11959 template<OpcodeSize size>
11960 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
11961 {
11962 UNUSED_PARAM(gen);
11963#if OS(WINDOWS) && ENABLE(C_LOOP)
11964 // FIXME: Disable wide16 optimization for Windows CLoop
11965 // https://bugs.webkit.org/show_bug.cgi?id=198283
11966 if (size == OpcodeSize::Wide16)
11967 return false;
11968#endif
11969 return Fits<OpcodeID, size>::check(opcodeID)
11970 && Fits<VirtualRegister, size>::check(dst)
11971 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
11972 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
11973 }
11974
11975 template<OpcodeSize size, bool recordOpcode>
11976 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
11977 {
11978 if (size == OpcodeSize::Wide16)
11979 gen->alignWideOpcode16();
11980 else if (size == OpcodeSize::Wide32)
11981 gen->alignWideOpcode32();
11982 if (checkImpl<size>(gen, dst)) {
11983 if (recordOpcode)
11984 gen->recordOpcode(opcodeID);
11985 if (size == OpcodeSize::Wide16)
11986 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
11987 else if (size == OpcodeSize::Wide32)
11988 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
11989 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
11990 gen->write(Fits<VirtualRegister, size>::convert(dst));
11991 return true;
11992 }
11993 return false;
11994 }
11995
11996public:
11997 template<typename Block>
11998 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
11999 {
12000 dumper->printLocationAndOp(__location, &"**argument_count"[2 - __sizeShiftAmount]);
12001 dumper->dumpOperand(m_dst, true);
12002 }
12003
12004 OpArgumentCount(const uint8_t* stream)
12005 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
12006 {
12007 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12008 }
12009
12010 OpArgumentCount(const uint16_t* stream)
12011 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
12012 {
12013 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12014 }
12015
12016
12017 OpArgumentCount(const uint32_t* stream)
12018 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
12019 {
12020 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12021 }
12022
12023 static OpArgumentCount decode(const uint8_t* stream)
12024 {
12025 if (*stream == op_wide32)
12026 return { bitwise_cast<const uint32_t*>(stream + 1) };
12027 if (*stream == op_wide16)
12028 return { bitwise_cast<const uint16_t*>(stream + 1) };
12029 return { stream };
12030 }
12031
12032 template<typename Functor>
12033 void setDst(VirtualRegister value, Functor func)
12034 {
12035 if (isWide32())
12036 setDst<OpcodeSize::Wide32>(value, func);
12037 else if (isWide16())
12038 setDst<OpcodeSize::Wide16>(value, func);
12039 else
12040 setDst<OpcodeSize::Narrow>(value, func);
12041 }
12042
12043 template <OpcodeSize size, typename Functor>
12044 void setDst(VirtualRegister value, Functor func)
12045 {
12046 if (!Fits<VirtualRegister, size>::check(value))
12047 value = func();
12048 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
12049 *stream = Fits<VirtualRegister, size>::convert(value);
12050 }
12051
12052 VirtualRegister m_dst;
12053};
12054
12055struct OpCheckTdz : public Instruction {
12056 static constexpr OpcodeID opcodeID = op_check_tdz;
12057
12058 static void emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
12059 {
12060 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, targetVirtualRegister);
12061 }
12062
12063 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
12064 static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
12065 {
12066 bool didEmit = emitImpl<size, recordOpcode>(gen, targetVirtualRegister);
12067 if (shouldAssert == Assert)
12068 ASSERT(didEmit);
12069 return didEmit;
12070 }
12071
12072 template<OpcodeSize size>
12073 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
12074 {
12075
12076 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
12077 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetVirtualRegister))
12078 return;
12079 }
12080 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
12081 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, targetVirtualRegister))
12082 return;
12083 }
12084 emit<OpcodeSize::Wide32, Assert, true>(gen, targetVirtualRegister);
12085 }
12086
12087private:
12088 template<OpcodeSize size>
12089 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& targetVirtualRegister)
12090 {
12091 UNUSED_PARAM(gen);
12092#if OS(WINDOWS) && ENABLE(C_LOOP)
12093 // FIXME: Disable wide16 optimization for Windows CLoop
12094 // https://bugs.webkit.org/show_bug.cgi?id=198283
12095 if (size == OpcodeSize::Wide16)
12096 return false;
12097#endif
12098 return Fits<OpcodeID, size>::check(opcodeID)
12099 && Fits<VirtualRegister, size>::check(targetVirtualRegister)
12100 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
12101 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
12102 }
12103
12104 template<OpcodeSize size, bool recordOpcode>
12105 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
12106 {
12107 if (size == OpcodeSize::Wide16)
12108 gen->alignWideOpcode16();
12109 else if (size == OpcodeSize::Wide32)
12110 gen->alignWideOpcode32();
12111 if (checkImpl<size>(gen, targetVirtualRegister)) {
12112 if (recordOpcode)
12113 gen->recordOpcode(opcodeID);
12114 if (size == OpcodeSize::Wide16)
12115 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
12116 else if (size == OpcodeSize::Wide32)
12117 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
12118 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
12119 gen->write(Fits<VirtualRegister, size>::convert(targetVirtualRegister));
12120 return true;
12121 }
12122 return false;
12123 }
12124
12125public:
12126 template<typename Block>
12127 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
12128 {
12129 dumper->printLocationAndOp(__location, &"**check_tdz"[2 - __sizeShiftAmount]);
12130 dumper->dumpOperand(m_targetVirtualRegister, true);
12131 }
12132
12133 OpCheckTdz(const uint8_t* stream)
12134 : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
12135 {
12136 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12137 }
12138
12139 OpCheckTdz(const uint16_t* stream)
12140 : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
12141 {
12142 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12143 }
12144
12145
12146 OpCheckTdz(const uint32_t* stream)
12147 : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
12148 {
12149 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12150 }
12151
12152 static OpCheckTdz decode(const uint8_t* stream)
12153 {
12154 if (*stream == op_wide32)
12155 return { bitwise_cast<const uint32_t*>(stream + 1) };
12156 if (*stream == op_wide16)
12157 return { bitwise_cast<const uint16_t*>(stream + 1) };
12158 return { stream };
12159 }
12160
12161 template<typename Functor>
12162 void setTargetVirtualRegister(VirtualRegister value, Functor func)
12163 {
12164 if (isWide32())
12165 setTargetVirtualRegister<OpcodeSize::Wide32>(value, func);
12166 else if (isWide16())
12167 setTargetVirtualRegister<OpcodeSize::Wide16>(value, func);
12168 else
12169 setTargetVirtualRegister<OpcodeSize::Narrow>(value, func);
12170 }
12171
12172 template <OpcodeSize size, typename Functor>
12173 void setTargetVirtualRegister(VirtualRegister value, Functor func)
12174 {
12175 if (!Fits<VirtualRegister, size>::check(value))
12176 value = func();
12177 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
12178 *stream = Fits<VirtualRegister, size>::convert(value);
12179 }
12180
12181 VirtualRegister m_targetVirtualRegister;
12182};
12183
12184struct OpNewArrayWithSpread : public Instruction {
12185 static constexpr OpcodeID opcodeID = op_new_array_with_spread;
12186
12187 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
12188 {
12189 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, argv, argc, bitVector);
12190 }
12191
12192 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
12193 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
12194 {
12195 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, argv, argc, bitVector);
12196 if (shouldAssert == Assert)
12197 ASSERT(didEmit);
12198 return didEmit;
12199 }
12200
12201 template<OpcodeSize size>
12202 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
12203 {
12204
12205 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
12206 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, argv, argc, bitVector))
12207 return;
12208 }
12209 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
12210 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, argv, argc, bitVector))
12211 return;
12212 }
12213 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, argv, argc, bitVector);
12214 }
12215
12216private:
12217 template<OpcodeSize size>
12218 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& argv, unsigned& argc, unsigned& bitVector)
12219 {
12220 UNUSED_PARAM(gen);
12221#if OS(WINDOWS) && ENABLE(C_LOOP)
12222 // FIXME: Disable wide16 optimization for Windows CLoop
12223 // https://bugs.webkit.org/show_bug.cgi?id=198283
12224 if (size == OpcodeSize::Wide16)
12225 return false;
12226#endif
12227 return Fits<OpcodeID, size>::check(opcodeID)
12228 && Fits<VirtualRegister, size>::check(dst)
12229 && Fits<VirtualRegister, size>::check(argv)
12230 && Fits<unsigned, size>::check(argc)
12231 && Fits<unsigned, size>::check(bitVector)
12232 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
12233 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
12234 }
12235
12236 template<OpcodeSize size, bool recordOpcode>
12237 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
12238 {
12239 if (size == OpcodeSize::Wide16)
12240 gen->alignWideOpcode16();
12241 else if (size == OpcodeSize::Wide32)
12242 gen->alignWideOpcode32();
12243 if (checkImpl<size>(gen, dst, argv, argc, bitVector)) {
12244 if (recordOpcode)
12245 gen->recordOpcode(opcodeID);
12246 if (size == OpcodeSize::Wide16)
12247 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
12248 else if (size == OpcodeSize::Wide32)
12249 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
12250 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
12251 gen->write(Fits<VirtualRegister, size>::convert(dst));
12252 gen->write(Fits<VirtualRegister, size>::convert(argv));
12253 gen->write(Fits<unsigned, size>::convert(argc));
12254 gen->write(Fits<unsigned, size>::convert(bitVector));
12255 return true;
12256 }
12257 return false;
12258 }
12259
12260public:
12261 template<typename Block>
12262 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
12263 {
12264 dumper->printLocationAndOp(__location, &"**new_array_with_spread"[2 - __sizeShiftAmount]);
12265 dumper->dumpOperand(m_dst, true);
12266 dumper->dumpOperand(m_argv, false);
12267 dumper->dumpOperand(m_argc, false);
12268 dumper->dumpOperand(m_bitVector, false);
12269 }
12270
12271 OpNewArrayWithSpread(const uint8_t* stream)
12272 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
12273 , m_argv(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
12274 , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
12275 , m_bitVector(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
12276 {
12277 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12278 }
12279
12280 OpNewArrayWithSpread(const uint16_t* stream)
12281 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
12282 , m_argv(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
12283 , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
12284 , m_bitVector(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
12285 {
12286 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12287 }
12288
12289
12290 OpNewArrayWithSpread(const uint32_t* stream)
12291 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
12292 , m_argv(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
12293 , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
12294 , m_bitVector(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
12295 {
12296 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12297 }
12298
12299 static OpNewArrayWithSpread decode(const uint8_t* stream)
12300 {
12301 if (*stream == op_wide32)
12302 return { bitwise_cast<const uint32_t*>(stream + 1) };
12303 if (*stream == op_wide16)
12304 return { bitwise_cast<const uint16_t*>(stream + 1) };
12305 return { stream };
12306 }
12307
12308 template<typename Functor>
12309 void setDst(VirtualRegister value, Functor func)
12310 {
12311 if (isWide32())
12312 setDst<OpcodeSize::Wide32>(value, func);
12313 else if (isWide16())
12314 setDst<OpcodeSize::Wide16>(value, func);
12315 else
12316 setDst<OpcodeSize::Narrow>(value, func);
12317 }
12318
12319 template <OpcodeSize size, typename Functor>
12320 void setDst(VirtualRegister value, Functor func)
12321 {
12322 if (!Fits<VirtualRegister, size>::check(value))
12323 value = func();
12324 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
12325 *stream = Fits<VirtualRegister, size>::convert(value);
12326 }
12327
12328 template<typename Functor>
12329 void setArgv(VirtualRegister value, Functor func)
12330 {
12331 if (isWide32())
12332 setArgv<OpcodeSize::Wide32>(value, func);
12333 else if (isWide16())
12334 setArgv<OpcodeSize::Wide16>(value, func);
12335 else
12336 setArgv<OpcodeSize::Narrow>(value, func);
12337 }
12338
12339 template <OpcodeSize size, typename Functor>
12340 void setArgv(VirtualRegister value, Functor func)
12341 {
12342 if (!Fits<VirtualRegister, size>::check(value))
12343 value = func();
12344 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
12345 *stream = Fits<VirtualRegister, size>::convert(value);
12346 }
12347
12348 template<typename Functor>
12349 void setArgc(unsigned value, Functor func)
12350 {
12351 if (isWide32())
12352 setArgc<OpcodeSize::Wide32>(value, func);
12353 else if (isWide16())
12354 setArgc<OpcodeSize::Wide16>(value, func);
12355 else
12356 setArgc<OpcodeSize::Narrow>(value, func);
12357 }
12358
12359 template <OpcodeSize size, typename Functor>
12360 void setArgc(unsigned value, Functor func)
12361 {
12362 if (!Fits<unsigned, size>::check(value))
12363 value = func();
12364 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
12365 *stream = Fits<unsigned, size>::convert(value);
12366 }
12367
12368 template<typename Functor>
12369 void setBitVector(unsigned value, Functor func)
12370 {
12371 if (isWide32())
12372 setBitVector<OpcodeSize::Wide32>(value, func);
12373 else if (isWide16())
12374 setBitVector<OpcodeSize::Wide16>(value, func);
12375 else
12376 setBitVector<OpcodeSize::Narrow>(value, func);
12377 }
12378
12379 template <OpcodeSize size, typename Functor>
12380 void setBitVector(unsigned value, Functor func)
12381 {
12382 if (!Fits<unsigned, size>::check(value))
12383 value = func();
12384 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
12385 *stream = Fits<unsigned, size>::convert(value);
12386 }
12387
12388 VirtualRegister m_dst;
12389 VirtualRegister m_argv;
12390 unsigned m_argc;
12391 unsigned m_bitVector;
12392};
12393
12394struct OpSpread : public Instruction {
12395 static constexpr OpcodeID opcodeID = op_spread;
12396
12397 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
12398 {
12399 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, argument);
12400 }
12401
12402 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
12403 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
12404 {
12405 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, argument);
12406 if (shouldAssert == Assert)
12407 ASSERT(didEmit);
12408 return didEmit;
12409 }
12410
12411 template<OpcodeSize size>
12412 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
12413 {
12414
12415 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
12416 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, argument))
12417 return;
12418 }
12419 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
12420 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, argument))
12421 return;
12422 }
12423 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, argument);
12424 }
12425
12426private:
12427 template<OpcodeSize size>
12428 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& argument)
12429 {
12430 UNUSED_PARAM(gen);
12431#if OS(WINDOWS) && ENABLE(C_LOOP)
12432 // FIXME: Disable wide16 optimization for Windows CLoop
12433 // https://bugs.webkit.org/show_bug.cgi?id=198283
12434 if (size == OpcodeSize::Wide16)
12435 return false;
12436#endif
12437 return Fits<OpcodeID, size>::check(opcodeID)
12438 && Fits<VirtualRegister, size>::check(dst)
12439 && Fits<VirtualRegister, size>::check(argument)
12440 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
12441 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
12442 }
12443
12444 template<OpcodeSize size, bool recordOpcode>
12445 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
12446 {
12447 if (size == OpcodeSize::Wide16)
12448 gen->alignWideOpcode16();
12449 else if (size == OpcodeSize::Wide32)
12450 gen->alignWideOpcode32();
12451 if (checkImpl<size>(gen, dst, argument)) {
12452 if (recordOpcode)
12453 gen->recordOpcode(opcodeID);
12454 if (size == OpcodeSize::Wide16)
12455 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
12456 else if (size == OpcodeSize::Wide32)
12457 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
12458 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
12459 gen->write(Fits<VirtualRegister, size>::convert(dst));
12460 gen->write(Fits<VirtualRegister, size>::convert(argument));
12461 return true;
12462 }
12463 return false;
12464 }
12465
12466public:
12467 template<typename Block>
12468 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
12469 {
12470 dumper->printLocationAndOp(__location, &"**spread"[2 - __sizeShiftAmount]);
12471 dumper->dumpOperand(m_dst, true);
12472 dumper->dumpOperand(m_argument, false);
12473 }
12474
12475 OpSpread(const uint8_t* stream)
12476 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
12477 , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
12478 {
12479 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12480 }
12481
12482 OpSpread(const uint16_t* stream)
12483 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
12484 , m_argument(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
12485 {
12486 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12487 }
12488
12489
12490 OpSpread(const uint32_t* stream)
12491 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
12492 , m_argument(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
12493 {
12494 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12495 }
12496
12497 static OpSpread decode(const uint8_t* stream)
12498 {
12499 if (*stream == op_wide32)
12500 return { bitwise_cast<const uint32_t*>(stream + 1) };
12501 if (*stream == op_wide16)
12502 return { bitwise_cast<const uint16_t*>(stream + 1) };
12503 return { stream };
12504 }
12505
12506 template<typename Functor>
12507 void setDst(VirtualRegister value, Functor func)
12508 {
12509 if (isWide32())
12510 setDst<OpcodeSize::Wide32>(value, func);
12511 else if (isWide16())
12512 setDst<OpcodeSize::Wide16>(value, func);
12513 else
12514 setDst<OpcodeSize::Narrow>(value, func);
12515 }
12516
12517 template <OpcodeSize size, typename Functor>
12518 void setDst(VirtualRegister value, Functor func)
12519 {
12520 if (!Fits<VirtualRegister, size>::check(value))
12521 value = func();
12522 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
12523 *stream = Fits<VirtualRegister, size>::convert(value);
12524 }
12525
12526 template<typename Functor>
12527 void setArgument(VirtualRegister value, Functor func)
12528 {
12529 if (isWide32())
12530 setArgument<OpcodeSize::Wide32>(value, func);
12531 else if (isWide16())
12532 setArgument<OpcodeSize::Wide16>(value, func);
12533 else
12534 setArgument<OpcodeSize::Narrow>(value, func);
12535 }
12536
12537 template <OpcodeSize size, typename Functor>
12538 void setArgument(VirtualRegister value, Functor func)
12539 {
12540 if (!Fits<VirtualRegister, size>::check(value))
12541 value = func();
12542 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
12543 *stream = Fits<VirtualRegister, size>::convert(value);
12544 }
12545
12546 VirtualRegister m_dst;
12547 VirtualRegister m_argument;
12548};
12549
12550struct OpNewRegexp : public Instruction {
12551 static constexpr OpcodeID opcodeID = op_new_regexp;
12552
12553 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
12554 {
12555 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, regexp);
12556 }
12557
12558 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
12559 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
12560 {
12561 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, regexp);
12562 if (shouldAssert == Assert)
12563 ASSERT(didEmit);
12564 return didEmit;
12565 }
12566
12567 template<OpcodeSize size>
12568 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
12569 {
12570
12571 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
12572 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, regexp))
12573 return;
12574 }
12575 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
12576 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, regexp))
12577 return;
12578 }
12579 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, regexp);
12580 }
12581
12582private:
12583 template<OpcodeSize size>
12584 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& regexp)
12585 {
12586 UNUSED_PARAM(gen);
12587#if OS(WINDOWS) && ENABLE(C_LOOP)
12588 // FIXME: Disable wide16 optimization for Windows CLoop
12589 // https://bugs.webkit.org/show_bug.cgi?id=198283
12590 if (size == OpcodeSize::Wide16)
12591 return false;
12592#endif
12593 return Fits<OpcodeID, size>::check(opcodeID)
12594 && Fits<VirtualRegister, size>::check(dst)
12595 && Fits<VirtualRegister, size>::check(regexp)
12596 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
12597 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
12598 }
12599
12600 template<OpcodeSize size, bool recordOpcode>
12601 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
12602 {
12603 if (size == OpcodeSize::Wide16)
12604 gen->alignWideOpcode16();
12605 else if (size == OpcodeSize::Wide32)
12606 gen->alignWideOpcode32();
12607 if (checkImpl<size>(gen, dst, regexp)) {
12608 if (recordOpcode)
12609 gen->recordOpcode(opcodeID);
12610 if (size == OpcodeSize::Wide16)
12611 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
12612 else if (size == OpcodeSize::Wide32)
12613 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
12614 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
12615 gen->write(Fits<VirtualRegister, size>::convert(dst));
12616 gen->write(Fits<VirtualRegister, size>::convert(regexp));
12617 return true;
12618 }
12619 return false;
12620 }
12621
12622public:
12623 template<typename Block>
12624 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
12625 {
12626 dumper->printLocationAndOp(__location, &"**new_regexp"[2 - __sizeShiftAmount]);
12627 dumper->dumpOperand(m_dst, true);
12628 dumper->dumpOperand(m_regexp, false);
12629 }
12630
12631 OpNewRegexp(const uint8_t* stream)
12632 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
12633 , m_regexp(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
12634 {
12635 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12636 }
12637
12638 OpNewRegexp(const uint16_t* stream)
12639 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
12640 , m_regexp(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
12641 {
12642 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12643 }
12644
12645
12646 OpNewRegexp(const uint32_t* stream)
12647 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
12648 , m_regexp(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
12649 {
12650 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12651 }
12652
12653 static OpNewRegexp decode(const uint8_t* stream)
12654 {
12655 if (*stream == op_wide32)
12656 return { bitwise_cast<const uint32_t*>(stream + 1) };
12657 if (*stream == op_wide16)
12658 return { bitwise_cast<const uint16_t*>(stream + 1) };
12659 return { stream };
12660 }
12661
12662 template<typename Functor>
12663 void setDst(VirtualRegister value, Functor func)
12664 {
12665 if (isWide32())
12666 setDst<OpcodeSize::Wide32>(value, func);
12667 else if (isWide16())
12668 setDst<OpcodeSize::Wide16>(value, func);
12669 else
12670 setDst<OpcodeSize::Narrow>(value, func);
12671 }
12672
12673 template <OpcodeSize size, typename Functor>
12674 void setDst(VirtualRegister value, Functor func)
12675 {
12676 if (!Fits<VirtualRegister, size>::check(value))
12677 value = func();
12678 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
12679 *stream = Fits<VirtualRegister, size>::convert(value);
12680 }
12681
12682 template<typename Functor>
12683 void setRegexp(VirtualRegister value, Functor func)
12684 {
12685 if (isWide32())
12686 setRegexp<OpcodeSize::Wide32>(value, func);
12687 else if (isWide16())
12688 setRegexp<OpcodeSize::Wide16>(value, func);
12689 else
12690 setRegexp<OpcodeSize::Narrow>(value, func);
12691 }
12692
12693 template <OpcodeSize size, typename Functor>
12694 void setRegexp(VirtualRegister value, Functor func)
12695 {
12696 if (!Fits<VirtualRegister, size>::check(value))
12697 value = func();
12698 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
12699 *stream = Fits<VirtualRegister, size>::convert(value);
12700 }
12701
12702 VirtualRegister m_dst;
12703 VirtualRegister m_regexp;
12704};
12705
12706struct OpMov : public Instruction {
12707 static constexpr OpcodeID opcodeID = op_mov;
12708
12709 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
12710 {
12711 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, src);
12712 }
12713
12714 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
12715 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
12716 {
12717 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, src);
12718 if (shouldAssert == Assert)
12719 ASSERT(didEmit);
12720 return didEmit;
12721 }
12722
12723 template<OpcodeSize size>
12724 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
12725 {
12726
12727 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
12728 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src))
12729 return;
12730 }
12731 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
12732 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, src))
12733 return;
12734 }
12735 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, src);
12736 }
12737
12738private:
12739 template<OpcodeSize size>
12740 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src)
12741 {
12742 UNUSED_PARAM(gen);
12743#if OS(WINDOWS) && ENABLE(C_LOOP)
12744 // FIXME: Disable wide16 optimization for Windows CLoop
12745 // https://bugs.webkit.org/show_bug.cgi?id=198283
12746 if (size == OpcodeSize::Wide16)
12747 return false;
12748#endif
12749 return Fits<OpcodeID, size>::check(opcodeID)
12750 && Fits<VirtualRegister, size>::check(dst)
12751 && Fits<VirtualRegister, size>::check(src)
12752 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
12753 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
12754 }
12755
12756 template<OpcodeSize size, bool recordOpcode>
12757 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
12758 {
12759 if (size == OpcodeSize::Wide16)
12760 gen->alignWideOpcode16();
12761 else if (size == OpcodeSize::Wide32)
12762 gen->alignWideOpcode32();
12763 if (checkImpl<size>(gen, dst, src)) {
12764 if (recordOpcode)
12765 gen->recordOpcode(opcodeID);
12766 if (size == OpcodeSize::Wide16)
12767 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
12768 else if (size == OpcodeSize::Wide32)
12769 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
12770 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
12771 gen->write(Fits<VirtualRegister, size>::convert(dst));
12772 gen->write(Fits<VirtualRegister, size>::convert(src));
12773 return true;
12774 }
12775 return false;
12776 }
12777
12778public:
12779 template<typename Block>
12780 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
12781 {
12782 dumper->printLocationAndOp(__location, &"**mov"[2 - __sizeShiftAmount]);
12783 dumper->dumpOperand(m_dst, true);
12784 dumper->dumpOperand(m_src, false);
12785 }
12786
12787 OpMov(const uint8_t* stream)
12788 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
12789 , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
12790 {
12791 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12792 }
12793
12794 OpMov(const uint16_t* stream)
12795 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
12796 , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
12797 {
12798 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12799 }
12800
12801
12802 OpMov(const uint32_t* stream)
12803 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
12804 , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
12805 {
12806 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12807 }
12808
12809 static OpMov decode(const uint8_t* stream)
12810 {
12811 if (*stream == op_wide32)
12812 return { bitwise_cast<const uint32_t*>(stream + 1) };
12813 if (*stream == op_wide16)
12814 return { bitwise_cast<const uint16_t*>(stream + 1) };
12815 return { stream };
12816 }
12817
12818 template<typename Functor>
12819 void setDst(VirtualRegister value, Functor func)
12820 {
12821 if (isWide32())
12822 setDst<OpcodeSize::Wide32>(value, func);
12823 else if (isWide16())
12824 setDst<OpcodeSize::Wide16>(value, func);
12825 else
12826 setDst<OpcodeSize::Narrow>(value, func);
12827 }
12828
12829 template <OpcodeSize size, typename Functor>
12830 void setDst(VirtualRegister value, Functor func)
12831 {
12832 if (!Fits<VirtualRegister, size>::check(value))
12833 value = func();
12834 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
12835 *stream = Fits<VirtualRegister, size>::convert(value);
12836 }
12837
12838 template<typename Functor>
12839 void setSrc(VirtualRegister value, Functor func)
12840 {
12841 if (isWide32())
12842 setSrc<OpcodeSize::Wide32>(value, func);
12843 else if (isWide16())
12844 setSrc<OpcodeSize::Wide16>(value, func);
12845 else
12846 setSrc<OpcodeSize::Narrow>(value, func);
12847 }
12848
12849 template <OpcodeSize size, typename Functor>
12850 void setSrc(VirtualRegister value, Functor func)
12851 {
12852 if (!Fits<VirtualRegister, size>::check(value))
12853 value = func();
12854 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
12855 *stream = Fits<VirtualRegister, size>::convert(value);
12856 }
12857
12858 VirtualRegister m_dst;
12859 VirtualRegister m_src;
12860};
12861
12862struct OpEq : public Instruction {
12863 static constexpr OpcodeID opcodeID = op_eq;
12864
12865 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
12866 {
12867 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
12868 }
12869
12870 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
12871 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
12872 {
12873 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
12874 if (shouldAssert == Assert)
12875 ASSERT(didEmit);
12876 return didEmit;
12877 }
12878
12879 template<OpcodeSize size>
12880 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
12881 {
12882
12883 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
12884 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
12885 return;
12886 }
12887 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
12888 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
12889 return;
12890 }
12891 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
12892 }
12893
12894private:
12895 template<OpcodeSize size>
12896 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
12897 {
12898 UNUSED_PARAM(gen);
12899#if OS(WINDOWS) && ENABLE(C_LOOP)
12900 // FIXME: Disable wide16 optimization for Windows CLoop
12901 // https://bugs.webkit.org/show_bug.cgi?id=198283
12902 if (size == OpcodeSize::Wide16)
12903 return false;
12904#endif
12905 return Fits<OpcodeID, size>::check(opcodeID)
12906 && Fits<VirtualRegister, size>::check(dst)
12907 && Fits<VirtualRegister, size>::check(lhs)
12908 && Fits<VirtualRegister, size>::check(rhs)
12909 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
12910 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
12911 }
12912
12913 template<OpcodeSize size, bool recordOpcode>
12914 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
12915 {
12916 if (size == OpcodeSize::Wide16)
12917 gen->alignWideOpcode16();
12918 else if (size == OpcodeSize::Wide32)
12919 gen->alignWideOpcode32();
12920 if (checkImpl<size>(gen, dst, lhs, rhs)) {
12921 if (recordOpcode)
12922 gen->recordOpcode(opcodeID);
12923 if (size == OpcodeSize::Wide16)
12924 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
12925 else if (size == OpcodeSize::Wide32)
12926 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
12927 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
12928 gen->write(Fits<VirtualRegister, size>::convert(dst));
12929 gen->write(Fits<VirtualRegister, size>::convert(lhs));
12930 gen->write(Fits<VirtualRegister, size>::convert(rhs));
12931 return true;
12932 }
12933 return false;
12934 }
12935
12936public:
12937 template<typename Block>
12938 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
12939 {
12940 dumper->printLocationAndOp(__location, &"**eq"[2 - __sizeShiftAmount]);
12941 dumper->dumpOperand(m_dst, true);
12942 dumper->dumpOperand(m_lhs, false);
12943 dumper->dumpOperand(m_rhs, false);
12944 }
12945
12946 OpEq(const uint8_t* stream)
12947 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
12948 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
12949 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
12950 {
12951 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12952 }
12953
12954 OpEq(const uint16_t* stream)
12955 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
12956 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
12957 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
12958 {
12959 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12960 }
12961
12962
12963 OpEq(const uint32_t* stream)
12964 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
12965 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
12966 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
12967 {
12968 ASSERT_UNUSED(stream, stream[0] == opcodeID);
12969 }
12970
12971 static OpEq decode(const uint8_t* stream)
12972 {
12973 if (*stream == op_wide32)
12974 return { bitwise_cast<const uint32_t*>(stream + 1) };
12975 if (*stream == op_wide16)
12976 return { bitwise_cast<const uint16_t*>(stream + 1) };
12977 return { stream };
12978 }
12979
12980 template<typename Functor>
12981 void setDst(VirtualRegister value, Functor func)
12982 {
12983 if (isWide32())
12984 setDst<OpcodeSize::Wide32>(value, func);
12985 else if (isWide16())
12986 setDst<OpcodeSize::Wide16>(value, func);
12987 else
12988 setDst<OpcodeSize::Narrow>(value, func);
12989 }
12990
12991 template <OpcodeSize size, typename Functor>
12992 void setDst(VirtualRegister value, Functor func)
12993 {
12994 if (!Fits<VirtualRegister, size>::check(value))
12995 value = func();
12996 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
12997 *stream = Fits<VirtualRegister, size>::convert(value);
12998 }
12999
13000 template<typename Functor>
13001 void setLhs(VirtualRegister value, Functor func)
13002 {
13003 if (isWide32())
13004 setLhs<OpcodeSize::Wide32>(value, func);
13005 else if (isWide16())
13006 setLhs<OpcodeSize::Wide16>(value, func);
13007 else
13008 setLhs<OpcodeSize::Narrow>(value, func);
13009 }
13010
13011 template <OpcodeSize size, typename Functor>
13012 void setLhs(VirtualRegister value, Functor func)
13013 {
13014 if (!Fits<VirtualRegister, size>::check(value))
13015 value = func();
13016 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
13017 *stream = Fits<VirtualRegister, size>::convert(value);
13018 }
13019
13020 template<typename Functor>
13021 void setRhs(VirtualRegister value, Functor func)
13022 {
13023 if (isWide32())
13024 setRhs<OpcodeSize::Wide32>(value, func);
13025 else if (isWide16())
13026 setRhs<OpcodeSize::Wide16>(value, func);
13027 else
13028 setRhs<OpcodeSize::Narrow>(value, func);
13029 }
13030
13031 template <OpcodeSize size, typename Functor>
13032 void setRhs(VirtualRegister value, Functor func)
13033 {
13034 if (!Fits<VirtualRegister, size>::check(value))
13035 value = func();
13036 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
13037 *stream = Fits<VirtualRegister, size>::convert(value);
13038 }
13039
13040 VirtualRegister m_dst;
13041 VirtualRegister m_lhs;
13042 VirtualRegister m_rhs;
13043};
13044
13045struct OpNeq : public Instruction {
13046 static constexpr OpcodeID opcodeID = op_neq;
13047
13048 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13049 {
13050 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
13051 }
13052
13053 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
13054 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13055 {
13056 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
13057 if (shouldAssert == Assert)
13058 ASSERT(didEmit);
13059 return didEmit;
13060 }
13061
13062 template<OpcodeSize size>
13063 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13064 {
13065
13066 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
13067 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
13068 return;
13069 }
13070 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
13071 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
13072 return;
13073 }
13074 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
13075 }
13076
13077private:
13078 template<OpcodeSize size>
13079 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
13080 {
13081 UNUSED_PARAM(gen);
13082#if OS(WINDOWS) && ENABLE(C_LOOP)
13083 // FIXME: Disable wide16 optimization for Windows CLoop
13084 // https://bugs.webkit.org/show_bug.cgi?id=198283
13085 if (size == OpcodeSize::Wide16)
13086 return false;
13087#endif
13088 return Fits<OpcodeID, size>::check(opcodeID)
13089 && Fits<VirtualRegister, size>::check(dst)
13090 && Fits<VirtualRegister, size>::check(lhs)
13091 && Fits<VirtualRegister, size>::check(rhs)
13092 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
13093 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
13094 }
13095
13096 template<OpcodeSize size, bool recordOpcode>
13097 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13098 {
13099 if (size == OpcodeSize::Wide16)
13100 gen->alignWideOpcode16();
13101 else if (size == OpcodeSize::Wide32)
13102 gen->alignWideOpcode32();
13103 if (checkImpl<size>(gen, dst, lhs, rhs)) {
13104 if (recordOpcode)
13105 gen->recordOpcode(opcodeID);
13106 if (size == OpcodeSize::Wide16)
13107 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
13108 else if (size == OpcodeSize::Wide32)
13109 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
13110 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
13111 gen->write(Fits<VirtualRegister, size>::convert(dst));
13112 gen->write(Fits<VirtualRegister, size>::convert(lhs));
13113 gen->write(Fits<VirtualRegister, size>::convert(rhs));
13114 return true;
13115 }
13116 return false;
13117 }
13118
13119public:
13120 template<typename Block>
13121 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
13122 {
13123 dumper->printLocationAndOp(__location, &"**neq"[2 - __sizeShiftAmount]);
13124 dumper->dumpOperand(m_dst, true);
13125 dumper->dumpOperand(m_lhs, false);
13126 dumper->dumpOperand(m_rhs, false);
13127 }
13128
13129 OpNeq(const uint8_t* stream)
13130 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
13131 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
13132 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
13133 {
13134 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13135 }
13136
13137 OpNeq(const uint16_t* stream)
13138 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
13139 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
13140 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
13141 {
13142 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13143 }
13144
13145
13146 OpNeq(const uint32_t* stream)
13147 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
13148 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
13149 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
13150 {
13151 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13152 }
13153
13154 static OpNeq decode(const uint8_t* stream)
13155 {
13156 if (*stream == op_wide32)
13157 return { bitwise_cast<const uint32_t*>(stream + 1) };
13158 if (*stream == op_wide16)
13159 return { bitwise_cast<const uint16_t*>(stream + 1) };
13160 return { stream };
13161 }
13162
13163 template<typename Functor>
13164 void setDst(VirtualRegister value, Functor func)
13165 {
13166 if (isWide32())
13167 setDst<OpcodeSize::Wide32>(value, func);
13168 else if (isWide16())
13169 setDst<OpcodeSize::Wide16>(value, func);
13170 else
13171 setDst<OpcodeSize::Narrow>(value, func);
13172 }
13173
13174 template <OpcodeSize size, typename Functor>
13175 void setDst(VirtualRegister value, Functor func)
13176 {
13177 if (!Fits<VirtualRegister, size>::check(value))
13178 value = func();
13179 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
13180 *stream = Fits<VirtualRegister, size>::convert(value);
13181 }
13182
13183 template<typename Functor>
13184 void setLhs(VirtualRegister value, Functor func)
13185 {
13186 if (isWide32())
13187 setLhs<OpcodeSize::Wide32>(value, func);
13188 else if (isWide16())
13189 setLhs<OpcodeSize::Wide16>(value, func);
13190 else
13191 setLhs<OpcodeSize::Narrow>(value, func);
13192 }
13193
13194 template <OpcodeSize size, typename Functor>
13195 void setLhs(VirtualRegister value, Functor func)
13196 {
13197 if (!Fits<VirtualRegister, size>::check(value))
13198 value = func();
13199 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
13200 *stream = Fits<VirtualRegister, size>::convert(value);
13201 }
13202
13203 template<typename Functor>
13204 void setRhs(VirtualRegister value, Functor func)
13205 {
13206 if (isWide32())
13207 setRhs<OpcodeSize::Wide32>(value, func);
13208 else if (isWide16())
13209 setRhs<OpcodeSize::Wide16>(value, func);
13210 else
13211 setRhs<OpcodeSize::Narrow>(value, func);
13212 }
13213
13214 template <OpcodeSize size, typename Functor>
13215 void setRhs(VirtualRegister value, Functor func)
13216 {
13217 if (!Fits<VirtualRegister, size>::check(value))
13218 value = func();
13219 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
13220 *stream = Fits<VirtualRegister, size>::convert(value);
13221 }
13222
13223 VirtualRegister m_dst;
13224 VirtualRegister m_lhs;
13225 VirtualRegister m_rhs;
13226};
13227
13228struct OpStricteq : public Instruction {
13229 static constexpr OpcodeID opcodeID = op_stricteq;
13230
13231 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13232 {
13233 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
13234 }
13235
13236 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
13237 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13238 {
13239 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
13240 if (shouldAssert == Assert)
13241 ASSERT(didEmit);
13242 return didEmit;
13243 }
13244
13245 template<OpcodeSize size>
13246 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13247 {
13248
13249 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
13250 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
13251 return;
13252 }
13253 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
13254 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
13255 return;
13256 }
13257 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
13258 }
13259
13260private:
13261 template<OpcodeSize size>
13262 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
13263 {
13264 UNUSED_PARAM(gen);
13265#if OS(WINDOWS) && ENABLE(C_LOOP)
13266 // FIXME: Disable wide16 optimization for Windows CLoop
13267 // https://bugs.webkit.org/show_bug.cgi?id=198283
13268 if (size == OpcodeSize::Wide16)
13269 return false;
13270#endif
13271 return Fits<OpcodeID, size>::check(opcodeID)
13272 && Fits<VirtualRegister, size>::check(dst)
13273 && Fits<VirtualRegister, size>::check(lhs)
13274 && Fits<VirtualRegister, size>::check(rhs)
13275 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
13276 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
13277 }
13278
13279 template<OpcodeSize size, bool recordOpcode>
13280 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13281 {
13282 if (size == OpcodeSize::Wide16)
13283 gen->alignWideOpcode16();
13284 else if (size == OpcodeSize::Wide32)
13285 gen->alignWideOpcode32();
13286 if (checkImpl<size>(gen, dst, lhs, rhs)) {
13287 if (recordOpcode)
13288 gen->recordOpcode(opcodeID);
13289 if (size == OpcodeSize::Wide16)
13290 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
13291 else if (size == OpcodeSize::Wide32)
13292 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
13293 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
13294 gen->write(Fits<VirtualRegister, size>::convert(dst));
13295 gen->write(Fits<VirtualRegister, size>::convert(lhs));
13296 gen->write(Fits<VirtualRegister, size>::convert(rhs));
13297 return true;
13298 }
13299 return false;
13300 }
13301
13302public:
13303 template<typename Block>
13304 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
13305 {
13306 dumper->printLocationAndOp(__location, &"**stricteq"[2 - __sizeShiftAmount]);
13307 dumper->dumpOperand(m_dst, true);
13308 dumper->dumpOperand(m_lhs, false);
13309 dumper->dumpOperand(m_rhs, false);
13310 }
13311
13312 OpStricteq(const uint8_t* stream)
13313 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
13314 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
13315 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
13316 {
13317 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13318 }
13319
13320 OpStricteq(const uint16_t* stream)
13321 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
13322 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
13323 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
13324 {
13325 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13326 }
13327
13328
13329 OpStricteq(const uint32_t* stream)
13330 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
13331 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
13332 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
13333 {
13334 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13335 }
13336
13337 static OpStricteq decode(const uint8_t* stream)
13338 {
13339 if (*stream == op_wide32)
13340 return { bitwise_cast<const uint32_t*>(stream + 1) };
13341 if (*stream == op_wide16)
13342 return { bitwise_cast<const uint16_t*>(stream + 1) };
13343 return { stream };
13344 }
13345
13346 template<typename Functor>
13347 void setDst(VirtualRegister value, Functor func)
13348 {
13349 if (isWide32())
13350 setDst<OpcodeSize::Wide32>(value, func);
13351 else if (isWide16())
13352 setDst<OpcodeSize::Wide16>(value, func);
13353 else
13354 setDst<OpcodeSize::Narrow>(value, func);
13355 }
13356
13357 template <OpcodeSize size, typename Functor>
13358 void setDst(VirtualRegister value, Functor func)
13359 {
13360 if (!Fits<VirtualRegister, size>::check(value))
13361 value = func();
13362 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
13363 *stream = Fits<VirtualRegister, size>::convert(value);
13364 }
13365
13366 template<typename Functor>
13367 void setLhs(VirtualRegister value, Functor func)
13368 {
13369 if (isWide32())
13370 setLhs<OpcodeSize::Wide32>(value, func);
13371 else if (isWide16())
13372 setLhs<OpcodeSize::Wide16>(value, func);
13373 else
13374 setLhs<OpcodeSize::Narrow>(value, func);
13375 }
13376
13377 template <OpcodeSize size, typename Functor>
13378 void setLhs(VirtualRegister value, Functor func)
13379 {
13380 if (!Fits<VirtualRegister, size>::check(value))
13381 value = func();
13382 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
13383 *stream = Fits<VirtualRegister, size>::convert(value);
13384 }
13385
13386 template<typename Functor>
13387 void setRhs(VirtualRegister value, Functor func)
13388 {
13389 if (isWide32())
13390 setRhs<OpcodeSize::Wide32>(value, func);
13391 else if (isWide16())
13392 setRhs<OpcodeSize::Wide16>(value, func);
13393 else
13394 setRhs<OpcodeSize::Narrow>(value, func);
13395 }
13396
13397 template <OpcodeSize size, typename Functor>
13398 void setRhs(VirtualRegister value, Functor func)
13399 {
13400 if (!Fits<VirtualRegister, size>::check(value))
13401 value = func();
13402 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
13403 *stream = Fits<VirtualRegister, size>::convert(value);
13404 }
13405
13406 VirtualRegister m_dst;
13407 VirtualRegister m_lhs;
13408 VirtualRegister m_rhs;
13409};
13410
13411struct OpNstricteq : public Instruction {
13412 static constexpr OpcodeID opcodeID = op_nstricteq;
13413
13414 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13415 {
13416 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
13417 }
13418
13419 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
13420 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13421 {
13422 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
13423 if (shouldAssert == Assert)
13424 ASSERT(didEmit);
13425 return didEmit;
13426 }
13427
13428 template<OpcodeSize size>
13429 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13430 {
13431
13432 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
13433 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
13434 return;
13435 }
13436 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
13437 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
13438 return;
13439 }
13440 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
13441 }
13442
13443private:
13444 template<OpcodeSize size>
13445 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
13446 {
13447 UNUSED_PARAM(gen);
13448#if OS(WINDOWS) && ENABLE(C_LOOP)
13449 // FIXME: Disable wide16 optimization for Windows CLoop
13450 // https://bugs.webkit.org/show_bug.cgi?id=198283
13451 if (size == OpcodeSize::Wide16)
13452 return false;
13453#endif
13454 return Fits<OpcodeID, size>::check(opcodeID)
13455 && Fits<VirtualRegister, size>::check(dst)
13456 && Fits<VirtualRegister, size>::check(lhs)
13457 && Fits<VirtualRegister, size>::check(rhs)
13458 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
13459 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
13460 }
13461
13462 template<OpcodeSize size, bool recordOpcode>
13463 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13464 {
13465 if (size == OpcodeSize::Wide16)
13466 gen->alignWideOpcode16();
13467 else if (size == OpcodeSize::Wide32)
13468 gen->alignWideOpcode32();
13469 if (checkImpl<size>(gen, dst, lhs, rhs)) {
13470 if (recordOpcode)
13471 gen->recordOpcode(opcodeID);
13472 if (size == OpcodeSize::Wide16)
13473 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
13474 else if (size == OpcodeSize::Wide32)
13475 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
13476 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
13477 gen->write(Fits<VirtualRegister, size>::convert(dst));
13478 gen->write(Fits<VirtualRegister, size>::convert(lhs));
13479 gen->write(Fits<VirtualRegister, size>::convert(rhs));
13480 return true;
13481 }
13482 return false;
13483 }
13484
13485public:
13486 template<typename Block>
13487 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
13488 {
13489 dumper->printLocationAndOp(__location, &"**nstricteq"[2 - __sizeShiftAmount]);
13490 dumper->dumpOperand(m_dst, true);
13491 dumper->dumpOperand(m_lhs, false);
13492 dumper->dumpOperand(m_rhs, false);
13493 }
13494
13495 OpNstricteq(const uint8_t* stream)
13496 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
13497 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
13498 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
13499 {
13500 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13501 }
13502
13503 OpNstricteq(const uint16_t* stream)
13504 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
13505 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
13506 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
13507 {
13508 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13509 }
13510
13511
13512 OpNstricteq(const uint32_t* stream)
13513 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
13514 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
13515 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
13516 {
13517 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13518 }
13519
13520 static OpNstricteq decode(const uint8_t* stream)
13521 {
13522 if (*stream == op_wide32)
13523 return { bitwise_cast<const uint32_t*>(stream + 1) };
13524 if (*stream == op_wide16)
13525 return { bitwise_cast<const uint16_t*>(stream + 1) };
13526 return { stream };
13527 }
13528
13529 template<typename Functor>
13530 void setDst(VirtualRegister value, Functor func)
13531 {
13532 if (isWide32())
13533 setDst<OpcodeSize::Wide32>(value, func);
13534 else if (isWide16())
13535 setDst<OpcodeSize::Wide16>(value, func);
13536 else
13537 setDst<OpcodeSize::Narrow>(value, func);
13538 }
13539
13540 template <OpcodeSize size, typename Functor>
13541 void setDst(VirtualRegister value, Functor func)
13542 {
13543 if (!Fits<VirtualRegister, size>::check(value))
13544 value = func();
13545 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
13546 *stream = Fits<VirtualRegister, size>::convert(value);
13547 }
13548
13549 template<typename Functor>
13550 void setLhs(VirtualRegister value, Functor func)
13551 {
13552 if (isWide32())
13553 setLhs<OpcodeSize::Wide32>(value, func);
13554 else if (isWide16())
13555 setLhs<OpcodeSize::Wide16>(value, func);
13556 else
13557 setLhs<OpcodeSize::Narrow>(value, func);
13558 }
13559
13560 template <OpcodeSize size, typename Functor>
13561 void setLhs(VirtualRegister value, Functor func)
13562 {
13563 if (!Fits<VirtualRegister, size>::check(value))
13564 value = func();
13565 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
13566 *stream = Fits<VirtualRegister, size>::convert(value);
13567 }
13568
13569 template<typename Functor>
13570 void setRhs(VirtualRegister value, Functor func)
13571 {
13572 if (isWide32())
13573 setRhs<OpcodeSize::Wide32>(value, func);
13574 else if (isWide16())
13575 setRhs<OpcodeSize::Wide16>(value, func);
13576 else
13577 setRhs<OpcodeSize::Narrow>(value, func);
13578 }
13579
13580 template <OpcodeSize size, typename Functor>
13581 void setRhs(VirtualRegister value, Functor func)
13582 {
13583 if (!Fits<VirtualRegister, size>::check(value))
13584 value = func();
13585 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
13586 *stream = Fits<VirtualRegister, size>::convert(value);
13587 }
13588
13589 VirtualRegister m_dst;
13590 VirtualRegister m_lhs;
13591 VirtualRegister m_rhs;
13592};
13593
13594struct OpLess : public Instruction {
13595 static constexpr OpcodeID opcodeID = op_less;
13596
13597 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13598 {
13599 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
13600 }
13601
13602 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
13603 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13604 {
13605 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
13606 if (shouldAssert == Assert)
13607 ASSERT(didEmit);
13608 return didEmit;
13609 }
13610
13611 template<OpcodeSize size>
13612 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13613 {
13614
13615 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
13616 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
13617 return;
13618 }
13619 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
13620 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
13621 return;
13622 }
13623 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
13624 }
13625
13626private:
13627 template<OpcodeSize size>
13628 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
13629 {
13630 UNUSED_PARAM(gen);
13631#if OS(WINDOWS) && ENABLE(C_LOOP)
13632 // FIXME: Disable wide16 optimization for Windows CLoop
13633 // https://bugs.webkit.org/show_bug.cgi?id=198283
13634 if (size == OpcodeSize::Wide16)
13635 return false;
13636#endif
13637 return Fits<OpcodeID, size>::check(opcodeID)
13638 && Fits<VirtualRegister, size>::check(dst)
13639 && Fits<VirtualRegister, size>::check(lhs)
13640 && Fits<VirtualRegister, size>::check(rhs)
13641 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
13642 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
13643 }
13644
13645 template<OpcodeSize size, bool recordOpcode>
13646 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13647 {
13648 if (size == OpcodeSize::Wide16)
13649 gen->alignWideOpcode16();
13650 else if (size == OpcodeSize::Wide32)
13651 gen->alignWideOpcode32();
13652 if (checkImpl<size>(gen, dst, lhs, rhs)) {
13653 if (recordOpcode)
13654 gen->recordOpcode(opcodeID);
13655 if (size == OpcodeSize::Wide16)
13656 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
13657 else if (size == OpcodeSize::Wide32)
13658 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
13659 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
13660 gen->write(Fits<VirtualRegister, size>::convert(dst));
13661 gen->write(Fits<VirtualRegister, size>::convert(lhs));
13662 gen->write(Fits<VirtualRegister, size>::convert(rhs));
13663 return true;
13664 }
13665 return false;
13666 }
13667
13668public:
13669 template<typename Block>
13670 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
13671 {
13672 dumper->printLocationAndOp(__location, &"**less"[2 - __sizeShiftAmount]);
13673 dumper->dumpOperand(m_dst, true);
13674 dumper->dumpOperand(m_lhs, false);
13675 dumper->dumpOperand(m_rhs, false);
13676 }
13677
13678 OpLess(const uint8_t* stream)
13679 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
13680 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
13681 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
13682 {
13683 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13684 }
13685
13686 OpLess(const uint16_t* stream)
13687 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
13688 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
13689 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
13690 {
13691 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13692 }
13693
13694
13695 OpLess(const uint32_t* stream)
13696 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
13697 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
13698 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
13699 {
13700 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13701 }
13702
13703 static OpLess decode(const uint8_t* stream)
13704 {
13705 if (*stream == op_wide32)
13706 return { bitwise_cast<const uint32_t*>(stream + 1) };
13707 if (*stream == op_wide16)
13708 return { bitwise_cast<const uint16_t*>(stream + 1) };
13709 return { stream };
13710 }
13711
13712 template<typename Functor>
13713 void setDst(VirtualRegister value, Functor func)
13714 {
13715 if (isWide32())
13716 setDst<OpcodeSize::Wide32>(value, func);
13717 else if (isWide16())
13718 setDst<OpcodeSize::Wide16>(value, func);
13719 else
13720 setDst<OpcodeSize::Narrow>(value, func);
13721 }
13722
13723 template <OpcodeSize size, typename Functor>
13724 void setDst(VirtualRegister value, Functor func)
13725 {
13726 if (!Fits<VirtualRegister, size>::check(value))
13727 value = func();
13728 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
13729 *stream = Fits<VirtualRegister, size>::convert(value);
13730 }
13731
13732 template<typename Functor>
13733 void setLhs(VirtualRegister value, Functor func)
13734 {
13735 if (isWide32())
13736 setLhs<OpcodeSize::Wide32>(value, func);
13737 else if (isWide16())
13738 setLhs<OpcodeSize::Wide16>(value, func);
13739 else
13740 setLhs<OpcodeSize::Narrow>(value, func);
13741 }
13742
13743 template <OpcodeSize size, typename Functor>
13744 void setLhs(VirtualRegister value, Functor func)
13745 {
13746 if (!Fits<VirtualRegister, size>::check(value))
13747 value = func();
13748 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
13749 *stream = Fits<VirtualRegister, size>::convert(value);
13750 }
13751
13752 template<typename Functor>
13753 void setRhs(VirtualRegister value, Functor func)
13754 {
13755 if (isWide32())
13756 setRhs<OpcodeSize::Wide32>(value, func);
13757 else if (isWide16())
13758 setRhs<OpcodeSize::Wide16>(value, func);
13759 else
13760 setRhs<OpcodeSize::Narrow>(value, func);
13761 }
13762
13763 template <OpcodeSize size, typename Functor>
13764 void setRhs(VirtualRegister value, Functor func)
13765 {
13766 if (!Fits<VirtualRegister, size>::check(value))
13767 value = func();
13768 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
13769 *stream = Fits<VirtualRegister, size>::convert(value);
13770 }
13771
13772 VirtualRegister m_dst;
13773 VirtualRegister m_lhs;
13774 VirtualRegister m_rhs;
13775};
13776
13777struct OpLesseq : public Instruction {
13778 static constexpr OpcodeID opcodeID = op_lesseq;
13779
13780 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13781 {
13782 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
13783 }
13784
13785 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
13786 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13787 {
13788 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
13789 if (shouldAssert == Assert)
13790 ASSERT(didEmit);
13791 return didEmit;
13792 }
13793
13794 template<OpcodeSize size>
13795 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13796 {
13797
13798 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
13799 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
13800 return;
13801 }
13802 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
13803 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
13804 return;
13805 }
13806 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
13807 }
13808
13809private:
13810 template<OpcodeSize size>
13811 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
13812 {
13813 UNUSED_PARAM(gen);
13814#if OS(WINDOWS) && ENABLE(C_LOOP)
13815 // FIXME: Disable wide16 optimization for Windows CLoop
13816 // https://bugs.webkit.org/show_bug.cgi?id=198283
13817 if (size == OpcodeSize::Wide16)
13818 return false;
13819#endif
13820 return Fits<OpcodeID, size>::check(opcodeID)
13821 && Fits<VirtualRegister, size>::check(dst)
13822 && Fits<VirtualRegister, size>::check(lhs)
13823 && Fits<VirtualRegister, size>::check(rhs)
13824 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
13825 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
13826 }
13827
13828 template<OpcodeSize size, bool recordOpcode>
13829 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13830 {
13831 if (size == OpcodeSize::Wide16)
13832 gen->alignWideOpcode16();
13833 else if (size == OpcodeSize::Wide32)
13834 gen->alignWideOpcode32();
13835 if (checkImpl<size>(gen, dst, lhs, rhs)) {
13836 if (recordOpcode)
13837 gen->recordOpcode(opcodeID);
13838 if (size == OpcodeSize::Wide16)
13839 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
13840 else if (size == OpcodeSize::Wide32)
13841 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
13842 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
13843 gen->write(Fits<VirtualRegister, size>::convert(dst));
13844 gen->write(Fits<VirtualRegister, size>::convert(lhs));
13845 gen->write(Fits<VirtualRegister, size>::convert(rhs));
13846 return true;
13847 }
13848 return false;
13849 }
13850
13851public:
13852 template<typename Block>
13853 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
13854 {
13855 dumper->printLocationAndOp(__location, &"**lesseq"[2 - __sizeShiftAmount]);
13856 dumper->dumpOperand(m_dst, true);
13857 dumper->dumpOperand(m_lhs, false);
13858 dumper->dumpOperand(m_rhs, false);
13859 }
13860
13861 OpLesseq(const uint8_t* stream)
13862 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
13863 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
13864 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
13865 {
13866 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13867 }
13868
13869 OpLesseq(const uint16_t* stream)
13870 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
13871 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
13872 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
13873 {
13874 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13875 }
13876
13877
13878 OpLesseq(const uint32_t* stream)
13879 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
13880 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
13881 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
13882 {
13883 ASSERT_UNUSED(stream, stream[0] == opcodeID);
13884 }
13885
13886 static OpLesseq decode(const uint8_t* stream)
13887 {
13888 if (*stream == op_wide32)
13889 return { bitwise_cast<const uint32_t*>(stream + 1) };
13890 if (*stream == op_wide16)
13891 return { bitwise_cast<const uint16_t*>(stream + 1) };
13892 return { stream };
13893 }
13894
13895 template<typename Functor>
13896 void setDst(VirtualRegister value, Functor func)
13897 {
13898 if (isWide32())
13899 setDst<OpcodeSize::Wide32>(value, func);
13900 else if (isWide16())
13901 setDst<OpcodeSize::Wide16>(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>::unsignedType*>(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 setLhs(VirtualRegister value, Functor func)
13917 {
13918 if (isWide32())
13919 setLhs<OpcodeSize::Wide32>(value, func);
13920 else if (isWide16())
13921 setLhs<OpcodeSize::Wide16>(value, func);
13922 else
13923 setLhs<OpcodeSize::Narrow>(value, func);
13924 }
13925
13926 template <OpcodeSize size, typename Functor>
13927 void setLhs(VirtualRegister value, Functor func)
13928 {
13929 if (!Fits<VirtualRegister, size>::check(value))
13930 value = func();
13931 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
13932 *stream = Fits<VirtualRegister, size>::convert(value);
13933 }
13934
13935 template<typename Functor>
13936 void setRhs(VirtualRegister value, Functor func)
13937 {
13938 if (isWide32())
13939 setRhs<OpcodeSize::Wide32>(value, func);
13940 else if (isWide16())
13941 setRhs<OpcodeSize::Wide16>(value, func);
13942 else
13943 setRhs<OpcodeSize::Narrow>(value, func);
13944 }
13945
13946 template <OpcodeSize size, typename Functor>
13947 void setRhs(VirtualRegister value, Functor func)
13948 {
13949 if (!Fits<VirtualRegister, size>::check(value))
13950 value = func();
13951 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
13952 *stream = Fits<VirtualRegister, size>::convert(value);
13953 }
13954
13955 VirtualRegister m_dst;
13956 VirtualRegister m_lhs;
13957 VirtualRegister m_rhs;
13958};
13959
13960struct OpGreater : public Instruction {
13961 static constexpr OpcodeID opcodeID = op_greater;
13962
13963 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13964 {
13965 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
13966 }
13967
13968 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
13969 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13970 {
13971 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
13972 if (shouldAssert == Assert)
13973 ASSERT(didEmit);
13974 return didEmit;
13975 }
13976
13977 template<OpcodeSize size>
13978 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
13979 {
13980
13981 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
13982 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
13983 return;
13984 }
13985 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
13986 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
13987 return;
13988 }
13989 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
13990 }
13991
13992private:
13993 template<OpcodeSize size>
13994 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
13995 {
13996 UNUSED_PARAM(gen);
13997#if OS(WINDOWS) && ENABLE(C_LOOP)
13998 // FIXME: Disable wide16 optimization for Windows CLoop
13999 // https://bugs.webkit.org/show_bug.cgi?id=198283
14000 if (size == OpcodeSize::Wide16)
14001 return false;
14002#endif
14003 return Fits<OpcodeID, size>::check(opcodeID)
14004 && Fits<VirtualRegister, size>::check(dst)
14005 && Fits<VirtualRegister, size>::check(lhs)
14006 && Fits<VirtualRegister, size>::check(rhs)
14007 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
14008 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
14009 }
14010
14011 template<OpcodeSize size, bool recordOpcode>
14012 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14013 {
14014 if (size == OpcodeSize::Wide16)
14015 gen->alignWideOpcode16();
14016 else if (size == OpcodeSize::Wide32)
14017 gen->alignWideOpcode32();
14018 if (checkImpl<size>(gen, dst, lhs, rhs)) {
14019 if (recordOpcode)
14020 gen->recordOpcode(opcodeID);
14021 if (size == OpcodeSize::Wide16)
14022 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
14023 else if (size == OpcodeSize::Wide32)
14024 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
14025 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
14026 gen->write(Fits<VirtualRegister, size>::convert(dst));
14027 gen->write(Fits<VirtualRegister, size>::convert(lhs));
14028 gen->write(Fits<VirtualRegister, size>::convert(rhs));
14029 return true;
14030 }
14031 return false;
14032 }
14033
14034public:
14035 template<typename Block>
14036 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
14037 {
14038 dumper->printLocationAndOp(__location, &"**greater"[2 - __sizeShiftAmount]);
14039 dumper->dumpOperand(m_dst, true);
14040 dumper->dumpOperand(m_lhs, false);
14041 dumper->dumpOperand(m_rhs, false);
14042 }
14043
14044 OpGreater(const uint8_t* stream)
14045 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
14046 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
14047 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
14048 {
14049 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14050 }
14051
14052 OpGreater(const uint16_t* stream)
14053 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
14054 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
14055 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
14056 {
14057 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14058 }
14059
14060
14061 OpGreater(const uint32_t* stream)
14062 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
14063 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
14064 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
14065 {
14066 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14067 }
14068
14069 static OpGreater decode(const uint8_t* stream)
14070 {
14071 if (*stream == op_wide32)
14072 return { bitwise_cast<const uint32_t*>(stream + 1) };
14073 if (*stream == op_wide16)
14074 return { bitwise_cast<const uint16_t*>(stream + 1) };
14075 return { stream };
14076 }
14077
14078 template<typename Functor>
14079 void setDst(VirtualRegister value, Functor func)
14080 {
14081 if (isWide32())
14082 setDst<OpcodeSize::Wide32>(value, func);
14083 else if (isWide16())
14084 setDst<OpcodeSize::Wide16>(value, func);
14085 else
14086 setDst<OpcodeSize::Narrow>(value, func);
14087 }
14088
14089 template <OpcodeSize size, typename Functor>
14090 void setDst(VirtualRegister value, Functor func)
14091 {
14092 if (!Fits<VirtualRegister, size>::check(value))
14093 value = func();
14094 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
14095 *stream = Fits<VirtualRegister, size>::convert(value);
14096 }
14097
14098 template<typename Functor>
14099 void setLhs(VirtualRegister value, Functor func)
14100 {
14101 if (isWide32())
14102 setLhs<OpcodeSize::Wide32>(value, func);
14103 else if (isWide16())
14104 setLhs<OpcodeSize::Wide16>(value, func);
14105 else
14106 setLhs<OpcodeSize::Narrow>(value, func);
14107 }
14108
14109 template <OpcodeSize size, typename Functor>
14110 void setLhs(VirtualRegister value, Functor func)
14111 {
14112 if (!Fits<VirtualRegister, size>::check(value))
14113 value = func();
14114 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
14115 *stream = Fits<VirtualRegister, size>::convert(value);
14116 }
14117
14118 template<typename Functor>
14119 void setRhs(VirtualRegister value, Functor func)
14120 {
14121 if (isWide32())
14122 setRhs<OpcodeSize::Wide32>(value, func);
14123 else if (isWide16())
14124 setRhs<OpcodeSize::Wide16>(value, func);
14125 else
14126 setRhs<OpcodeSize::Narrow>(value, func);
14127 }
14128
14129 template <OpcodeSize size, typename Functor>
14130 void setRhs(VirtualRegister value, Functor func)
14131 {
14132 if (!Fits<VirtualRegister, size>::check(value))
14133 value = func();
14134 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
14135 *stream = Fits<VirtualRegister, size>::convert(value);
14136 }
14137
14138 VirtualRegister m_dst;
14139 VirtualRegister m_lhs;
14140 VirtualRegister m_rhs;
14141};
14142
14143struct OpGreatereq : public Instruction {
14144 static constexpr OpcodeID opcodeID = op_greatereq;
14145
14146 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14147 {
14148 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
14149 }
14150
14151 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
14152 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14153 {
14154 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
14155 if (shouldAssert == Assert)
14156 ASSERT(didEmit);
14157 return didEmit;
14158 }
14159
14160 template<OpcodeSize size>
14161 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14162 {
14163
14164 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
14165 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
14166 return;
14167 }
14168 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
14169 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
14170 return;
14171 }
14172 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
14173 }
14174
14175private:
14176 template<OpcodeSize size>
14177 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
14178 {
14179 UNUSED_PARAM(gen);
14180#if OS(WINDOWS) && ENABLE(C_LOOP)
14181 // FIXME: Disable wide16 optimization for Windows CLoop
14182 // https://bugs.webkit.org/show_bug.cgi?id=198283
14183 if (size == OpcodeSize::Wide16)
14184 return false;
14185#endif
14186 return Fits<OpcodeID, size>::check(opcodeID)
14187 && Fits<VirtualRegister, size>::check(dst)
14188 && Fits<VirtualRegister, size>::check(lhs)
14189 && Fits<VirtualRegister, size>::check(rhs)
14190 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
14191 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
14192 }
14193
14194 template<OpcodeSize size, bool recordOpcode>
14195 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14196 {
14197 if (size == OpcodeSize::Wide16)
14198 gen->alignWideOpcode16();
14199 else if (size == OpcodeSize::Wide32)
14200 gen->alignWideOpcode32();
14201 if (checkImpl<size>(gen, dst, lhs, rhs)) {
14202 if (recordOpcode)
14203 gen->recordOpcode(opcodeID);
14204 if (size == OpcodeSize::Wide16)
14205 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
14206 else if (size == OpcodeSize::Wide32)
14207 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
14208 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
14209 gen->write(Fits<VirtualRegister, size>::convert(dst));
14210 gen->write(Fits<VirtualRegister, size>::convert(lhs));
14211 gen->write(Fits<VirtualRegister, size>::convert(rhs));
14212 return true;
14213 }
14214 return false;
14215 }
14216
14217public:
14218 template<typename Block>
14219 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
14220 {
14221 dumper->printLocationAndOp(__location, &"**greatereq"[2 - __sizeShiftAmount]);
14222 dumper->dumpOperand(m_dst, true);
14223 dumper->dumpOperand(m_lhs, false);
14224 dumper->dumpOperand(m_rhs, false);
14225 }
14226
14227 OpGreatereq(const uint8_t* stream)
14228 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
14229 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
14230 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
14231 {
14232 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14233 }
14234
14235 OpGreatereq(const uint16_t* stream)
14236 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
14237 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
14238 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
14239 {
14240 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14241 }
14242
14243
14244 OpGreatereq(const uint32_t* stream)
14245 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
14246 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
14247 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
14248 {
14249 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14250 }
14251
14252 static OpGreatereq decode(const uint8_t* stream)
14253 {
14254 if (*stream == op_wide32)
14255 return { bitwise_cast<const uint32_t*>(stream + 1) };
14256 if (*stream == op_wide16)
14257 return { bitwise_cast<const uint16_t*>(stream + 1) };
14258 return { stream };
14259 }
14260
14261 template<typename Functor>
14262 void setDst(VirtualRegister value, Functor func)
14263 {
14264 if (isWide32())
14265 setDst<OpcodeSize::Wide32>(value, func);
14266 else if (isWide16())
14267 setDst<OpcodeSize::Wide16>(value, func);
14268 else
14269 setDst<OpcodeSize::Narrow>(value, func);
14270 }
14271
14272 template <OpcodeSize size, typename Functor>
14273 void setDst(VirtualRegister value, Functor func)
14274 {
14275 if (!Fits<VirtualRegister, size>::check(value))
14276 value = func();
14277 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
14278 *stream = Fits<VirtualRegister, size>::convert(value);
14279 }
14280
14281 template<typename Functor>
14282 void setLhs(VirtualRegister value, Functor func)
14283 {
14284 if (isWide32())
14285 setLhs<OpcodeSize::Wide32>(value, func);
14286 else if (isWide16())
14287 setLhs<OpcodeSize::Wide16>(value, func);
14288 else
14289 setLhs<OpcodeSize::Narrow>(value, func);
14290 }
14291
14292 template <OpcodeSize size, typename Functor>
14293 void setLhs(VirtualRegister value, Functor func)
14294 {
14295 if (!Fits<VirtualRegister, size>::check(value))
14296 value = func();
14297 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
14298 *stream = Fits<VirtualRegister, size>::convert(value);
14299 }
14300
14301 template<typename Functor>
14302 void setRhs(VirtualRegister value, Functor func)
14303 {
14304 if (isWide32())
14305 setRhs<OpcodeSize::Wide32>(value, func);
14306 else if (isWide16())
14307 setRhs<OpcodeSize::Wide16>(value, func);
14308 else
14309 setRhs<OpcodeSize::Narrow>(value, func);
14310 }
14311
14312 template <OpcodeSize size, typename Functor>
14313 void setRhs(VirtualRegister value, Functor func)
14314 {
14315 if (!Fits<VirtualRegister, size>::check(value))
14316 value = func();
14317 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
14318 *stream = Fits<VirtualRegister, size>::convert(value);
14319 }
14320
14321 VirtualRegister m_dst;
14322 VirtualRegister m_lhs;
14323 VirtualRegister m_rhs;
14324};
14325
14326struct OpBelow : public Instruction {
14327 static constexpr OpcodeID opcodeID = op_below;
14328
14329 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14330 {
14331 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
14332 }
14333
14334 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
14335 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14336 {
14337 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
14338 if (shouldAssert == Assert)
14339 ASSERT(didEmit);
14340 return didEmit;
14341 }
14342
14343 template<OpcodeSize size>
14344 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14345 {
14346
14347 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
14348 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
14349 return;
14350 }
14351 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
14352 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
14353 return;
14354 }
14355 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
14356 }
14357
14358private:
14359 template<OpcodeSize size>
14360 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
14361 {
14362 UNUSED_PARAM(gen);
14363#if OS(WINDOWS) && ENABLE(C_LOOP)
14364 // FIXME: Disable wide16 optimization for Windows CLoop
14365 // https://bugs.webkit.org/show_bug.cgi?id=198283
14366 if (size == OpcodeSize::Wide16)
14367 return false;
14368#endif
14369 return Fits<OpcodeID, size>::check(opcodeID)
14370 && Fits<VirtualRegister, size>::check(dst)
14371 && Fits<VirtualRegister, size>::check(lhs)
14372 && Fits<VirtualRegister, size>::check(rhs)
14373 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
14374 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
14375 }
14376
14377 template<OpcodeSize size, bool recordOpcode>
14378 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14379 {
14380 if (size == OpcodeSize::Wide16)
14381 gen->alignWideOpcode16();
14382 else if (size == OpcodeSize::Wide32)
14383 gen->alignWideOpcode32();
14384 if (checkImpl<size>(gen, dst, lhs, rhs)) {
14385 if (recordOpcode)
14386 gen->recordOpcode(opcodeID);
14387 if (size == OpcodeSize::Wide16)
14388 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
14389 else if (size == OpcodeSize::Wide32)
14390 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
14391 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
14392 gen->write(Fits<VirtualRegister, size>::convert(dst));
14393 gen->write(Fits<VirtualRegister, size>::convert(lhs));
14394 gen->write(Fits<VirtualRegister, size>::convert(rhs));
14395 return true;
14396 }
14397 return false;
14398 }
14399
14400public:
14401 template<typename Block>
14402 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
14403 {
14404 dumper->printLocationAndOp(__location, &"**below"[2 - __sizeShiftAmount]);
14405 dumper->dumpOperand(m_dst, true);
14406 dumper->dumpOperand(m_lhs, false);
14407 dumper->dumpOperand(m_rhs, false);
14408 }
14409
14410 OpBelow(const uint8_t* stream)
14411 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
14412 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
14413 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
14414 {
14415 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14416 }
14417
14418 OpBelow(const uint16_t* stream)
14419 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
14420 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
14421 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
14422 {
14423 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14424 }
14425
14426
14427 OpBelow(const uint32_t* stream)
14428 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
14429 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
14430 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
14431 {
14432 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14433 }
14434
14435 static OpBelow decode(const uint8_t* stream)
14436 {
14437 if (*stream == op_wide32)
14438 return { bitwise_cast<const uint32_t*>(stream + 1) };
14439 if (*stream == op_wide16)
14440 return { bitwise_cast<const uint16_t*>(stream + 1) };
14441 return { stream };
14442 }
14443
14444 template<typename Functor>
14445 void setDst(VirtualRegister value, Functor func)
14446 {
14447 if (isWide32())
14448 setDst<OpcodeSize::Wide32>(value, func);
14449 else if (isWide16())
14450 setDst<OpcodeSize::Wide16>(value, func);
14451 else
14452 setDst<OpcodeSize::Narrow>(value, func);
14453 }
14454
14455 template <OpcodeSize size, typename Functor>
14456 void setDst(VirtualRegister value, Functor func)
14457 {
14458 if (!Fits<VirtualRegister, size>::check(value))
14459 value = func();
14460 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
14461 *stream = Fits<VirtualRegister, size>::convert(value);
14462 }
14463
14464 template<typename Functor>
14465 void setLhs(VirtualRegister value, Functor func)
14466 {
14467 if (isWide32())
14468 setLhs<OpcodeSize::Wide32>(value, func);
14469 else if (isWide16())
14470 setLhs<OpcodeSize::Wide16>(value, func);
14471 else
14472 setLhs<OpcodeSize::Narrow>(value, func);
14473 }
14474
14475 template <OpcodeSize size, typename Functor>
14476 void setLhs(VirtualRegister value, Functor func)
14477 {
14478 if (!Fits<VirtualRegister, size>::check(value))
14479 value = func();
14480 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
14481 *stream = Fits<VirtualRegister, size>::convert(value);
14482 }
14483
14484 template<typename Functor>
14485 void setRhs(VirtualRegister value, Functor func)
14486 {
14487 if (isWide32())
14488 setRhs<OpcodeSize::Wide32>(value, func);
14489 else if (isWide16())
14490 setRhs<OpcodeSize::Wide16>(value, func);
14491 else
14492 setRhs<OpcodeSize::Narrow>(value, func);
14493 }
14494
14495 template <OpcodeSize size, typename Functor>
14496 void setRhs(VirtualRegister value, Functor func)
14497 {
14498 if (!Fits<VirtualRegister, size>::check(value))
14499 value = func();
14500 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
14501 *stream = Fits<VirtualRegister, size>::convert(value);
14502 }
14503
14504 VirtualRegister m_dst;
14505 VirtualRegister m_lhs;
14506 VirtualRegister m_rhs;
14507};
14508
14509struct OpBeloweq : public Instruction {
14510 static constexpr OpcodeID opcodeID = op_beloweq;
14511
14512 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14513 {
14514 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
14515 }
14516
14517 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
14518 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14519 {
14520 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
14521 if (shouldAssert == Assert)
14522 ASSERT(didEmit);
14523 return didEmit;
14524 }
14525
14526 template<OpcodeSize size>
14527 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14528 {
14529
14530 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
14531 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
14532 return;
14533 }
14534 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
14535 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
14536 return;
14537 }
14538 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
14539 }
14540
14541private:
14542 template<OpcodeSize size>
14543 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
14544 {
14545 UNUSED_PARAM(gen);
14546#if OS(WINDOWS) && ENABLE(C_LOOP)
14547 // FIXME: Disable wide16 optimization for Windows CLoop
14548 // https://bugs.webkit.org/show_bug.cgi?id=198283
14549 if (size == OpcodeSize::Wide16)
14550 return false;
14551#endif
14552 return Fits<OpcodeID, size>::check(opcodeID)
14553 && Fits<VirtualRegister, size>::check(dst)
14554 && Fits<VirtualRegister, size>::check(lhs)
14555 && Fits<VirtualRegister, size>::check(rhs)
14556 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
14557 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
14558 }
14559
14560 template<OpcodeSize size, bool recordOpcode>
14561 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14562 {
14563 if (size == OpcodeSize::Wide16)
14564 gen->alignWideOpcode16();
14565 else if (size == OpcodeSize::Wide32)
14566 gen->alignWideOpcode32();
14567 if (checkImpl<size>(gen, dst, lhs, rhs)) {
14568 if (recordOpcode)
14569 gen->recordOpcode(opcodeID);
14570 if (size == OpcodeSize::Wide16)
14571 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
14572 else if (size == OpcodeSize::Wide32)
14573 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
14574 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
14575 gen->write(Fits<VirtualRegister, size>::convert(dst));
14576 gen->write(Fits<VirtualRegister, size>::convert(lhs));
14577 gen->write(Fits<VirtualRegister, size>::convert(rhs));
14578 return true;
14579 }
14580 return false;
14581 }
14582
14583public:
14584 template<typename Block>
14585 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
14586 {
14587 dumper->printLocationAndOp(__location, &"**beloweq"[2 - __sizeShiftAmount]);
14588 dumper->dumpOperand(m_dst, true);
14589 dumper->dumpOperand(m_lhs, false);
14590 dumper->dumpOperand(m_rhs, false);
14591 }
14592
14593 OpBeloweq(const uint8_t* stream)
14594 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
14595 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
14596 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
14597 {
14598 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14599 }
14600
14601 OpBeloweq(const uint16_t* stream)
14602 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
14603 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
14604 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
14605 {
14606 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14607 }
14608
14609
14610 OpBeloweq(const uint32_t* stream)
14611 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
14612 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
14613 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
14614 {
14615 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14616 }
14617
14618 static OpBeloweq decode(const uint8_t* stream)
14619 {
14620 if (*stream == op_wide32)
14621 return { bitwise_cast<const uint32_t*>(stream + 1) };
14622 if (*stream == op_wide16)
14623 return { bitwise_cast<const uint16_t*>(stream + 1) };
14624 return { stream };
14625 }
14626
14627 template<typename Functor>
14628 void setDst(VirtualRegister value, Functor func)
14629 {
14630 if (isWide32())
14631 setDst<OpcodeSize::Wide32>(value, func);
14632 else if (isWide16())
14633 setDst<OpcodeSize::Wide16>(value, func);
14634 else
14635 setDst<OpcodeSize::Narrow>(value, func);
14636 }
14637
14638 template <OpcodeSize size, typename Functor>
14639 void setDst(VirtualRegister value, Functor func)
14640 {
14641 if (!Fits<VirtualRegister, size>::check(value))
14642 value = func();
14643 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
14644 *stream = Fits<VirtualRegister, size>::convert(value);
14645 }
14646
14647 template<typename Functor>
14648 void setLhs(VirtualRegister value, Functor func)
14649 {
14650 if (isWide32())
14651 setLhs<OpcodeSize::Wide32>(value, func);
14652 else if (isWide16())
14653 setLhs<OpcodeSize::Wide16>(value, func);
14654 else
14655 setLhs<OpcodeSize::Narrow>(value, func);
14656 }
14657
14658 template <OpcodeSize size, typename Functor>
14659 void setLhs(VirtualRegister value, Functor func)
14660 {
14661 if (!Fits<VirtualRegister, size>::check(value))
14662 value = func();
14663 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
14664 *stream = Fits<VirtualRegister, size>::convert(value);
14665 }
14666
14667 template<typename Functor>
14668 void setRhs(VirtualRegister value, Functor func)
14669 {
14670 if (isWide32())
14671 setRhs<OpcodeSize::Wide32>(value, func);
14672 else if (isWide16())
14673 setRhs<OpcodeSize::Wide16>(value, func);
14674 else
14675 setRhs<OpcodeSize::Narrow>(value, func);
14676 }
14677
14678 template <OpcodeSize size, typename Functor>
14679 void setRhs(VirtualRegister value, Functor func)
14680 {
14681 if (!Fits<VirtualRegister, size>::check(value))
14682 value = func();
14683 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
14684 *stream = Fits<VirtualRegister, size>::convert(value);
14685 }
14686
14687 VirtualRegister m_dst;
14688 VirtualRegister m_lhs;
14689 VirtualRegister m_rhs;
14690};
14691
14692struct OpMod : public Instruction {
14693 static constexpr OpcodeID opcodeID = op_mod;
14694
14695 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14696 {
14697 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
14698 }
14699
14700 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
14701 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14702 {
14703 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
14704 if (shouldAssert == Assert)
14705 ASSERT(didEmit);
14706 return didEmit;
14707 }
14708
14709 template<OpcodeSize size>
14710 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14711 {
14712
14713 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
14714 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
14715 return;
14716 }
14717 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
14718 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
14719 return;
14720 }
14721 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
14722 }
14723
14724private:
14725 template<OpcodeSize size>
14726 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
14727 {
14728 UNUSED_PARAM(gen);
14729#if OS(WINDOWS) && ENABLE(C_LOOP)
14730 // FIXME: Disable wide16 optimization for Windows CLoop
14731 // https://bugs.webkit.org/show_bug.cgi?id=198283
14732 if (size == OpcodeSize::Wide16)
14733 return false;
14734#endif
14735 return Fits<OpcodeID, size>::check(opcodeID)
14736 && Fits<VirtualRegister, size>::check(dst)
14737 && Fits<VirtualRegister, size>::check(lhs)
14738 && Fits<VirtualRegister, size>::check(rhs)
14739 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
14740 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
14741 }
14742
14743 template<OpcodeSize size, bool recordOpcode>
14744 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14745 {
14746 if (size == OpcodeSize::Wide16)
14747 gen->alignWideOpcode16();
14748 else if (size == OpcodeSize::Wide32)
14749 gen->alignWideOpcode32();
14750 if (checkImpl<size>(gen, dst, lhs, rhs)) {
14751 if (recordOpcode)
14752 gen->recordOpcode(opcodeID);
14753 if (size == OpcodeSize::Wide16)
14754 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
14755 else if (size == OpcodeSize::Wide32)
14756 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
14757 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
14758 gen->write(Fits<VirtualRegister, size>::convert(dst));
14759 gen->write(Fits<VirtualRegister, size>::convert(lhs));
14760 gen->write(Fits<VirtualRegister, size>::convert(rhs));
14761 return true;
14762 }
14763 return false;
14764 }
14765
14766public:
14767 template<typename Block>
14768 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
14769 {
14770 dumper->printLocationAndOp(__location, &"**mod"[2 - __sizeShiftAmount]);
14771 dumper->dumpOperand(m_dst, true);
14772 dumper->dumpOperand(m_lhs, false);
14773 dumper->dumpOperand(m_rhs, false);
14774 }
14775
14776 OpMod(const uint8_t* stream)
14777 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
14778 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
14779 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
14780 {
14781 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14782 }
14783
14784 OpMod(const uint16_t* stream)
14785 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
14786 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
14787 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
14788 {
14789 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14790 }
14791
14792
14793 OpMod(const uint32_t* stream)
14794 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
14795 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
14796 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
14797 {
14798 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14799 }
14800
14801 static OpMod decode(const uint8_t* stream)
14802 {
14803 if (*stream == op_wide32)
14804 return { bitwise_cast<const uint32_t*>(stream + 1) };
14805 if (*stream == op_wide16)
14806 return { bitwise_cast<const uint16_t*>(stream + 1) };
14807 return { stream };
14808 }
14809
14810 template<typename Functor>
14811 void setDst(VirtualRegister value, Functor func)
14812 {
14813 if (isWide32())
14814 setDst<OpcodeSize::Wide32>(value, func);
14815 else if (isWide16())
14816 setDst<OpcodeSize::Wide16>(value, func);
14817 else
14818 setDst<OpcodeSize::Narrow>(value, func);
14819 }
14820
14821 template <OpcodeSize size, typename Functor>
14822 void setDst(VirtualRegister value, Functor func)
14823 {
14824 if (!Fits<VirtualRegister, size>::check(value))
14825 value = func();
14826 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
14827 *stream = Fits<VirtualRegister, size>::convert(value);
14828 }
14829
14830 template<typename Functor>
14831 void setLhs(VirtualRegister value, Functor func)
14832 {
14833 if (isWide32())
14834 setLhs<OpcodeSize::Wide32>(value, func);
14835 else if (isWide16())
14836 setLhs<OpcodeSize::Wide16>(value, func);
14837 else
14838 setLhs<OpcodeSize::Narrow>(value, func);
14839 }
14840
14841 template <OpcodeSize size, typename Functor>
14842 void setLhs(VirtualRegister value, Functor func)
14843 {
14844 if (!Fits<VirtualRegister, size>::check(value))
14845 value = func();
14846 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
14847 *stream = Fits<VirtualRegister, size>::convert(value);
14848 }
14849
14850 template<typename Functor>
14851 void setRhs(VirtualRegister value, Functor func)
14852 {
14853 if (isWide32())
14854 setRhs<OpcodeSize::Wide32>(value, func);
14855 else if (isWide16())
14856 setRhs<OpcodeSize::Wide16>(value, func);
14857 else
14858 setRhs<OpcodeSize::Narrow>(value, func);
14859 }
14860
14861 template <OpcodeSize size, typename Functor>
14862 void setRhs(VirtualRegister value, Functor func)
14863 {
14864 if (!Fits<VirtualRegister, size>::check(value))
14865 value = func();
14866 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
14867 *stream = Fits<VirtualRegister, size>::convert(value);
14868 }
14869
14870 VirtualRegister m_dst;
14871 VirtualRegister m_lhs;
14872 VirtualRegister m_rhs;
14873};
14874
14875struct OpPow : public Instruction {
14876 static constexpr OpcodeID opcodeID = op_pow;
14877
14878 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14879 {
14880 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
14881 }
14882
14883 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
14884 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14885 {
14886 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
14887 if (shouldAssert == Assert)
14888 ASSERT(didEmit);
14889 return didEmit;
14890 }
14891
14892 template<OpcodeSize size>
14893 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14894 {
14895
14896 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
14897 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
14898 return;
14899 }
14900 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
14901 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
14902 return;
14903 }
14904 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
14905 }
14906
14907private:
14908 template<OpcodeSize size>
14909 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
14910 {
14911 UNUSED_PARAM(gen);
14912#if OS(WINDOWS) && ENABLE(C_LOOP)
14913 // FIXME: Disable wide16 optimization for Windows CLoop
14914 // https://bugs.webkit.org/show_bug.cgi?id=198283
14915 if (size == OpcodeSize::Wide16)
14916 return false;
14917#endif
14918 return Fits<OpcodeID, size>::check(opcodeID)
14919 && Fits<VirtualRegister, size>::check(dst)
14920 && Fits<VirtualRegister, size>::check(lhs)
14921 && Fits<VirtualRegister, size>::check(rhs)
14922 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
14923 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
14924 }
14925
14926 template<OpcodeSize size, bool recordOpcode>
14927 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
14928 {
14929 if (size == OpcodeSize::Wide16)
14930 gen->alignWideOpcode16();
14931 else if (size == OpcodeSize::Wide32)
14932 gen->alignWideOpcode32();
14933 if (checkImpl<size>(gen, dst, lhs, rhs)) {
14934 if (recordOpcode)
14935 gen->recordOpcode(opcodeID);
14936 if (size == OpcodeSize::Wide16)
14937 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
14938 else if (size == OpcodeSize::Wide32)
14939 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
14940 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
14941 gen->write(Fits<VirtualRegister, size>::convert(dst));
14942 gen->write(Fits<VirtualRegister, size>::convert(lhs));
14943 gen->write(Fits<VirtualRegister, size>::convert(rhs));
14944 return true;
14945 }
14946 return false;
14947 }
14948
14949public:
14950 template<typename Block>
14951 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
14952 {
14953 dumper->printLocationAndOp(__location, &"**pow"[2 - __sizeShiftAmount]);
14954 dumper->dumpOperand(m_dst, true);
14955 dumper->dumpOperand(m_lhs, false);
14956 dumper->dumpOperand(m_rhs, false);
14957 }
14958
14959 OpPow(const uint8_t* stream)
14960 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
14961 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
14962 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
14963 {
14964 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14965 }
14966
14967 OpPow(const uint16_t* stream)
14968 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
14969 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
14970 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
14971 {
14972 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14973 }
14974
14975
14976 OpPow(const uint32_t* stream)
14977 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
14978 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
14979 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
14980 {
14981 ASSERT_UNUSED(stream, stream[0] == opcodeID);
14982 }
14983
14984 static OpPow decode(const uint8_t* stream)
14985 {
14986 if (*stream == op_wide32)
14987 return { bitwise_cast<const uint32_t*>(stream + 1) };
14988 if (*stream == op_wide16)
14989 return { bitwise_cast<const uint16_t*>(stream + 1) };
14990 return { stream };
14991 }
14992
14993 template<typename Functor>
14994 void setDst(VirtualRegister value, Functor func)
14995 {
14996 if (isWide32())
14997 setDst<OpcodeSize::Wide32>(value, func);
14998 else if (isWide16())
14999 setDst<OpcodeSize::Wide16>(value, func);
15000 else
15001 setDst<OpcodeSize::Narrow>(value, func);
15002 }
15003
15004 template <OpcodeSize size, typename Functor>
15005 void setDst(VirtualRegister value, Functor func)
15006 {
15007 if (!Fits<VirtualRegister, size>::check(value))
15008 value = func();
15009 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
15010 *stream = Fits<VirtualRegister, size>::convert(value);
15011 }
15012
15013 template<typename Functor>
15014 void setLhs(VirtualRegister value, Functor func)
15015 {
15016 if (isWide32())
15017 setLhs<OpcodeSize::Wide32>(value, func);
15018 else if (isWide16())
15019 setLhs<OpcodeSize::Wide16>(value, func);
15020 else
15021 setLhs<OpcodeSize::Narrow>(value, func);
15022 }
15023
15024 template <OpcodeSize size, typename Functor>
15025 void setLhs(VirtualRegister value, Functor func)
15026 {
15027 if (!Fits<VirtualRegister, size>::check(value))
15028 value = func();
15029 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
15030 *stream = Fits<VirtualRegister, size>::convert(value);
15031 }
15032
15033 template<typename Functor>
15034 void setRhs(VirtualRegister value, Functor func)
15035 {
15036 if (isWide32())
15037 setRhs<OpcodeSize::Wide32>(value, func);
15038 else if (isWide16())
15039 setRhs<OpcodeSize::Wide16>(value, func);
15040 else
15041 setRhs<OpcodeSize::Narrow>(value, func);
15042 }
15043
15044 template <OpcodeSize size, typename Functor>
15045 void setRhs(VirtualRegister value, Functor func)
15046 {
15047 if (!Fits<VirtualRegister, size>::check(value))
15048 value = func();
15049 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
15050 *stream = Fits<VirtualRegister, size>::convert(value);
15051 }
15052
15053 VirtualRegister m_dst;
15054 VirtualRegister m_lhs;
15055 VirtualRegister m_rhs;
15056};
15057
15058struct OpLshift : public Instruction {
15059 static constexpr OpcodeID opcodeID = op_lshift;
15060
15061 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15062 {
15063 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
15064 }
15065
15066 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
15067 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15068 {
15069 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
15070 if (shouldAssert == Assert)
15071 ASSERT(didEmit);
15072 return didEmit;
15073 }
15074
15075 template<OpcodeSize size>
15076 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15077 {
15078
15079 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
15080 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
15081 return;
15082 }
15083 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
15084 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
15085 return;
15086 }
15087 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
15088 }
15089
15090private:
15091 template<OpcodeSize size>
15092 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
15093 {
15094 UNUSED_PARAM(gen);
15095#if OS(WINDOWS) && ENABLE(C_LOOP)
15096 // FIXME: Disable wide16 optimization for Windows CLoop
15097 // https://bugs.webkit.org/show_bug.cgi?id=198283
15098 if (size == OpcodeSize::Wide16)
15099 return false;
15100#endif
15101 return Fits<OpcodeID, size>::check(opcodeID)
15102 && Fits<VirtualRegister, size>::check(dst)
15103 && Fits<VirtualRegister, size>::check(lhs)
15104 && Fits<VirtualRegister, size>::check(rhs)
15105 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
15106 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
15107 }
15108
15109 template<OpcodeSize size, bool recordOpcode>
15110 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15111 {
15112 if (size == OpcodeSize::Wide16)
15113 gen->alignWideOpcode16();
15114 else if (size == OpcodeSize::Wide32)
15115 gen->alignWideOpcode32();
15116 if (checkImpl<size>(gen, dst, lhs, rhs)) {
15117 if (recordOpcode)
15118 gen->recordOpcode(opcodeID);
15119 if (size == OpcodeSize::Wide16)
15120 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
15121 else if (size == OpcodeSize::Wide32)
15122 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
15123 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
15124 gen->write(Fits<VirtualRegister, size>::convert(dst));
15125 gen->write(Fits<VirtualRegister, size>::convert(lhs));
15126 gen->write(Fits<VirtualRegister, size>::convert(rhs));
15127 return true;
15128 }
15129 return false;
15130 }
15131
15132public:
15133 template<typename Block>
15134 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
15135 {
15136 dumper->printLocationAndOp(__location, &"**lshift"[2 - __sizeShiftAmount]);
15137 dumper->dumpOperand(m_dst, true);
15138 dumper->dumpOperand(m_lhs, false);
15139 dumper->dumpOperand(m_rhs, false);
15140 }
15141
15142 OpLshift(const uint8_t* stream)
15143 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
15144 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
15145 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
15146 {
15147 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15148 }
15149
15150 OpLshift(const uint16_t* stream)
15151 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
15152 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
15153 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
15154 {
15155 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15156 }
15157
15158
15159 OpLshift(const uint32_t* stream)
15160 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
15161 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
15162 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
15163 {
15164 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15165 }
15166
15167 static OpLshift decode(const uint8_t* stream)
15168 {
15169 if (*stream == op_wide32)
15170 return { bitwise_cast<const uint32_t*>(stream + 1) };
15171 if (*stream == op_wide16)
15172 return { bitwise_cast<const uint16_t*>(stream + 1) };
15173 return { stream };
15174 }
15175
15176 template<typename Functor>
15177 void setDst(VirtualRegister value, Functor func)
15178 {
15179 if (isWide32())
15180 setDst<OpcodeSize::Wide32>(value, func);
15181 else if (isWide16())
15182 setDst<OpcodeSize::Wide16>(value, func);
15183 else
15184 setDst<OpcodeSize::Narrow>(value, func);
15185 }
15186
15187 template <OpcodeSize size, typename Functor>
15188 void setDst(VirtualRegister value, Functor func)
15189 {
15190 if (!Fits<VirtualRegister, size>::check(value))
15191 value = func();
15192 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
15193 *stream = Fits<VirtualRegister, size>::convert(value);
15194 }
15195
15196 template<typename Functor>
15197 void setLhs(VirtualRegister value, Functor func)
15198 {
15199 if (isWide32())
15200 setLhs<OpcodeSize::Wide32>(value, func);
15201 else if (isWide16())
15202 setLhs<OpcodeSize::Wide16>(value, func);
15203 else
15204 setLhs<OpcodeSize::Narrow>(value, func);
15205 }
15206
15207 template <OpcodeSize size, typename Functor>
15208 void setLhs(VirtualRegister value, Functor func)
15209 {
15210 if (!Fits<VirtualRegister, size>::check(value))
15211 value = func();
15212 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
15213 *stream = Fits<VirtualRegister, size>::convert(value);
15214 }
15215
15216 template<typename Functor>
15217 void setRhs(VirtualRegister value, Functor func)
15218 {
15219 if (isWide32())
15220 setRhs<OpcodeSize::Wide32>(value, func);
15221 else if (isWide16())
15222 setRhs<OpcodeSize::Wide16>(value, func);
15223 else
15224 setRhs<OpcodeSize::Narrow>(value, func);
15225 }
15226
15227 template <OpcodeSize size, typename Functor>
15228 void setRhs(VirtualRegister value, Functor func)
15229 {
15230 if (!Fits<VirtualRegister, size>::check(value))
15231 value = func();
15232 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
15233 *stream = Fits<VirtualRegister, size>::convert(value);
15234 }
15235
15236 VirtualRegister m_dst;
15237 VirtualRegister m_lhs;
15238 VirtualRegister m_rhs;
15239};
15240
15241struct OpRshift : public Instruction {
15242 static constexpr OpcodeID opcodeID = op_rshift;
15243
15244 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15245 {
15246 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
15247 }
15248
15249 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
15250 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15251 {
15252 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
15253 if (shouldAssert == Assert)
15254 ASSERT(didEmit);
15255 return didEmit;
15256 }
15257
15258 template<OpcodeSize size>
15259 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15260 {
15261
15262 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
15263 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
15264 return;
15265 }
15266 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
15267 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
15268 return;
15269 }
15270 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
15271 }
15272
15273private:
15274 template<OpcodeSize size>
15275 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
15276 {
15277 UNUSED_PARAM(gen);
15278#if OS(WINDOWS) && ENABLE(C_LOOP)
15279 // FIXME: Disable wide16 optimization for Windows CLoop
15280 // https://bugs.webkit.org/show_bug.cgi?id=198283
15281 if (size == OpcodeSize::Wide16)
15282 return false;
15283#endif
15284 return Fits<OpcodeID, size>::check(opcodeID)
15285 && Fits<VirtualRegister, size>::check(dst)
15286 && Fits<VirtualRegister, size>::check(lhs)
15287 && Fits<VirtualRegister, size>::check(rhs)
15288 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
15289 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
15290 }
15291
15292 template<OpcodeSize size, bool recordOpcode>
15293 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15294 {
15295 if (size == OpcodeSize::Wide16)
15296 gen->alignWideOpcode16();
15297 else if (size == OpcodeSize::Wide32)
15298 gen->alignWideOpcode32();
15299 if (checkImpl<size>(gen, dst, lhs, rhs)) {
15300 if (recordOpcode)
15301 gen->recordOpcode(opcodeID);
15302 if (size == OpcodeSize::Wide16)
15303 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
15304 else if (size == OpcodeSize::Wide32)
15305 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
15306 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
15307 gen->write(Fits<VirtualRegister, size>::convert(dst));
15308 gen->write(Fits<VirtualRegister, size>::convert(lhs));
15309 gen->write(Fits<VirtualRegister, size>::convert(rhs));
15310 return true;
15311 }
15312 return false;
15313 }
15314
15315public:
15316 template<typename Block>
15317 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
15318 {
15319 dumper->printLocationAndOp(__location, &"**rshift"[2 - __sizeShiftAmount]);
15320 dumper->dumpOperand(m_dst, true);
15321 dumper->dumpOperand(m_lhs, false);
15322 dumper->dumpOperand(m_rhs, false);
15323 }
15324
15325 OpRshift(const uint8_t* stream)
15326 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
15327 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
15328 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
15329 {
15330 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15331 }
15332
15333 OpRshift(const uint16_t* stream)
15334 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
15335 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
15336 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
15337 {
15338 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15339 }
15340
15341
15342 OpRshift(const uint32_t* stream)
15343 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
15344 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
15345 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
15346 {
15347 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15348 }
15349
15350 static OpRshift decode(const uint8_t* stream)
15351 {
15352 if (*stream == op_wide32)
15353 return { bitwise_cast<const uint32_t*>(stream + 1) };
15354 if (*stream == op_wide16)
15355 return { bitwise_cast<const uint16_t*>(stream + 1) };
15356 return { stream };
15357 }
15358
15359 template<typename Functor>
15360 void setDst(VirtualRegister value, Functor func)
15361 {
15362 if (isWide32())
15363 setDst<OpcodeSize::Wide32>(value, func);
15364 else if (isWide16())
15365 setDst<OpcodeSize::Wide16>(value, func);
15366 else
15367 setDst<OpcodeSize::Narrow>(value, func);
15368 }
15369
15370 template <OpcodeSize size, typename Functor>
15371 void setDst(VirtualRegister value, Functor func)
15372 {
15373 if (!Fits<VirtualRegister, size>::check(value))
15374 value = func();
15375 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
15376 *stream = Fits<VirtualRegister, size>::convert(value);
15377 }
15378
15379 template<typename Functor>
15380 void setLhs(VirtualRegister value, Functor func)
15381 {
15382 if (isWide32())
15383 setLhs<OpcodeSize::Wide32>(value, func);
15384 else if (isWide16())
15385 setLhs<OpcodeSize::Wide16>(value, func);
15386 else
15387 setLhs<OpcodeSize::Narrow>(value, func);
15388 }
15389
15390 template <OpcodeSize size, typename Functor>
15391 void setLhs(VirtualRegister value, Functor func)
15392 {
15393 if (!Fits<VirtualRegister, size>::check(value))
15394 value = func();
15395 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
15396 *stream = Fits<VirtualRegister, size>::convert(value);
15397 }
15398
15399 template<typename Functor>
15400 void setRhs(VirtualRegister value, Functor func)
15401 {
15402 if (isWide32())
15403 setRhs<OpcodeSize::Wide32>(value, func);
15404 else if (isWide16())
15405 setRhs<OpcodeSize::Wide16>(value, func);
15406 else
15407 setRhs<OpcodeSize::Narrow>(value, func);
15408 }
15409
15410 template <OpcodeSize size, typename Functor>
15411 void setRhs(VirtualRegister value, Functor func)
15412 {
15413 if (!Fits<VirtualRegister, size>::check(value))
15414 value = func();
15415 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
15416 *stream = Fits<VirtualRegister, size>::convert(value);
15417 }
15418
15419 VirtualRegister m_dst;
15420 VirtualRegister m_lhs;
15421 VirtualRegister m_rhs;
15422};
15423
15424struct OpUrshift : public Instruction {
15425 static constexpr OpcodeID opcodeID = op_urshift;
15426
15427 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15428 {
15429 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
15430 }
15431
15432 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
15433 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15434 {
15435 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, lhs, rhs);
15436 if (shouldAssert == Assert)
15437 ASSERT(didEmit);
15438 return didEmit;
15439 }
15440
15441 template<OpcodeSize size>
15442 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15443 {
15444
15445 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
15446 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, lhs, rhs))
15447 return;
15448 }
15449 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
15450 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
15451 return;
15452 }
15453 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
15454 }
15455
15456private:
15457 template<OpcodeSize size>
15458 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
15459 {
15460 UNUSED_PARAM(gen);
15461#if OS(WINDOWS) && ENABLE(C_LOOP)
15462 // FIXME: Disable wide16 optimization for Windows CLoop
15463 // https://bugs.webkit.org/show_bug.cgi?id=198283
15464 if (size == OpcodeSize::Wide16)
15465 return false;
15466#endif
15467 return Fits<OpcodeID, size>::check(opcodeID)
15468 && Fits<VirtualRegister, size>::check(dst)
15469 && Fits<VirtualRegister, size>::check(lhs)
15470 && Fits<VirtualRegister, size>::check(rhs)
15471 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
15472 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
15473 }
15474
15475 template<OpcodeSize size, bool recordOpcode>
15476 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
15477 {
15478 if (size == OpcodeSize::Wide16)
15479 gen->alignWideOpcode16();
15480 else if (size == OpcodeSize::Wide32)
15481 gen->alignWideOpcode32();
15482 if (checkImpl<size>(gen, dst, lhs, rhs)) {
15483 if (recordOpcode)
15484 gen->recordOpcode(opcodeID);
15485 if (size == OpcodeSize::Wide16)
15486 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
15487 else if (size == OpcodeSize::Wide32)
15488 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
15489 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
15490 gen->write(Fits<VirtualRegister, size>::convert(dst));
15491 gen->write(Fits<VirtualRegister, size>::convert(lhs));
15492 gen->write(Fits<VirtualRegister, size>::convert(rhs));
15493 return true;
15494 }
15495 return false;
15496 }
15497
15498public:
15499 template<typename Block>
15500 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
15501 {
15502 dumper->printLocationAndOp(__location, &"**urshift"[2 - __sizeShiftAmount]);
15503 dumper->dumpOperand(m_dst, true);
15504 dumper->dumpOperand(m_lhs, false);
15505 dumper->dumpOperand(m_rhs, false);
15506 }
15507
15508 OpUrshift(const uint8_t* stream)
15509 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
15510 , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
15511 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
15512 {
15513 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15514 }
15515
15516 OpUrshift(const uint16_t* stream)
15517 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
15518 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
15519 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
15520 {
15521 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15522 }
15523
15524
15525 OpUrshift(const uint32_t* stream)
15526 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
15527 , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
15528 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
15529 {
15530 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15531 }
15532
15533 static OpUrshift decode(const uint8_t* stream)
15534 {
15535 if (*stream == op_wide32)
15536 return { bitwise_cast<const uint32_t*>(stream + 1) };
15537 if (*stream == op_wide16)
15538 return { bitwise_cast<const uint16_t*>(stream + 1) };
15539 return { stream };
15540 }
15541
15542 template<typename Functor>
15543 void setDst(VirtualRegister value, Functor func)
15544 {
15545 if (isWide32())
15546 setDst<OpcodeSize::Wide32>(value, func);
15547 else if (isWide16())
15548 setDst<OpcodeSize::Wide16>(value, func);
15549 else
15550 setDst<OpcodeSize::Narrow>(value, func);
15551 }
15552
15553 template <OpcodeSize size, typename Functor>
15554 void setDst(VirtualRegister value, Functor func)
15555 {
15556 if (!Fits<VirtualRegister, size>::check(value))
15557 value = func();
15558 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
15559 *stream = Fits<VirtualRegister, size>::convert(value);
15560 }
15561
15562 template<typename Functor>
15563 void setLhs(VirtualRegister value, Functor func)
15564 {
15565 if (isWide32())
15566 setLhs<OpcodeSize::Wide32>(value, func);
15567 else if (isWide16())
15568 setLhs<OpcodeSize::Wide16>(value, func);
15569 else
15570 setLhs<OpcodeSize::Narrow>(value, func);
15571 }
15572
15573 template <OpcodeSize size, typename Functor>
15574 void setLhs(VirtualRegister value, Functor func)
15575 {
15576 if (!Fits<VirtualRegister, size>::check(value))
15577 value = func();
15578 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
15579 *stream = Fits<VirtualRegister, size>::convert(value);
15580 }
15581
15582 template<typename Functor>
15583 void setRhs(VirtualRegister value, Functor func)
15584 {
15585 if (isWide32())
15586 setRhs<OpcodeSize::Wide32>(value, func);
15587 else if (isWide16())
15588 setRhs<OpcodeSize::Wide16>(value, func);
15589 else
15590 setRhs<OpcodeSize::Narrow>(value, func);
15591 }
15592
15593 template <OpcodeSize size, typename Functor>
15594 void setRhs(VirtualRegister value, Functor func)
15595 {
15596 if (!Fits<VirtualRegister, size>::check(value))
15597 value = func();
15598 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
15599 *stream = Fits<VirtualRegister, size>::convert(value);
15600 }
15601
15602 VirtualRegister m_dst;
15603 VirtualRegister m_lhs;
15604 VirtualRegister m_rhs;
15605};
15606
15607struct OpEqNull : public Instruction {
15608 static constexpr OpcodeID opcodeID = op_eq_null;
15609
15610 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15611 {
15612 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
15613 }
15614
15615 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
15616 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15617 {
15618 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
15619 if (shouldAssert == Assert)
15620 ASSERT(didEmit);
15621 return didEmit;
15622 }
15623
15624 template<OpcodeSize size>
15625 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15626 {
15627
15628 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
15629 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
15630 return;
15631 }
15632 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
15633 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
15634 return;
15635 }
15636 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
15637 }
15638
15639private:
15640 template<OpcodeSize size>
15641 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
15642 {
15643 UNUSED_PARAM(gen);
15644#if OS(WINDOWS) && ENABLE(C_LOOP)
15645 // FIXME: Disable wide16 optimization for Windows CLoop
15646 // https://bugs.webkit.org/show_bug.cgi?id=198283
15647 if (size == OpcodeSize::Wide16)
15648 return false;
15649#endif
15650 return Fits<OpcodeID, size>::check(opcodeID)
15651 && Fits<VirtualRegister, size>::check(dst)
15652 && Fits<VirtualRegister, size>::check(operand)
15653 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
15654 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
15655 }
15656
15657 template<OpcodeSize size, bool recordOpcode>
15658 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15659 {
15660 if (size == OpcodeSize::Wide16)
15661 gen->alignWideOpcode16();
15662 else if (size == OpcodeSize::Wide32)
15663 gen->alignWideOpcode32();
15664 if (checkImpl<size>(gen, dst, operand)) {
15665 if (recordOpcode)
15666 gen->recordOpcode(opcodeID);
15667 if (size == OpcodeSize::Wide16)
15668 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
15669 else if (size == OpcodeSize::Wide32)
15670 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
15671 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
15672 gen->write(Fits<VirtualRegister, size>::convert(dst));
15673 gen->write(Fits<VirtualRegister, size>::convert(operand));
15674 return true;
15675 }
15676 return false;
15677 }
15678
15679public:
15680 template<typename Block>
15681 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
15682 {
15683 dumper->printLocationAndOp(__location, &"**eq_null"[2 - __sizeShiftAmount]);
15684 dumper->dumpOperand(m_dst, true);
15685 dumper->dumpOperand(m_operand, false);
15686 }
15687
15688 OpEqNull(const uint8_t* stream)
15689 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
15690 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
15691 {
15692 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15693 }
15694
15695 OpEqNull(const uint16_t* stream)
15696 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
15697 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
15698 {
15699 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15700 }
15701
15702
15703 OpEqNull(const uint32_t* stream)
15704 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
15705 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
15706 {
15707 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15708 }
15709
15710 static OpEqNull decode(const uint8_t* stream)
15711 {
15712 if (*stream == op_wide32)
15713 return { bitwise_cast<const uint32_t*>(stream + 1) };
15714 if (*stream == op_wide16)
15715 return { bitwise_cast<const uint16_t*>(stream + 1) };
15716 return { stream };
15717 }
15718
15719 template<typename Functor>
15720 void setDst(VirtualRegister value, Functor func)
15721 {
15722 if (isWide32())
15723 setDst<OpcodeSize::Wide32>(value, func);
15724 else if (isWide16())
15725 setDst<OpcodeSize::Wide16>(value, func);
15726 else
15727 setDst<OpcodeSize::Narrow>(value, func);
15728 }
15729
15730 template <OpcodeSize size, typename Functor>
15731 void setDst(VirtualRegister value, Functor func)
15732 {
15733 if (!Fits<VirtualRegister, size>::check(value))
15734 value = func();
15735 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
15736 *stream = Fits<VirtualRegister, size>::convert(value);
15737 }
15738
15739 template<typename Functor>
15740 void setOperand(VirtualRegister value, Functor func)
15741 {
15742 if (isWide32())
15743 setOperand<OpcodeSize::Wide32>(value, func);
15744 else if (isWide16())
15745 setOperand<OpcodeSize::Wide16>(value, func);
15746 else
15747 setOperand<OpcodeSize::Narrow>(value, func);
15748 }
15749
15750 template <OpcodeSize size, typename Functor>
15751 void setOperand(VirtualRegister value, Functor func)
15752 {
15753 if (!Fits<VirtualRegister, size>::check(value))
15754 value = func();
15755 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
15756 *stream = Fits<VirtualRegister, size>::convert(value);
15757 }
15758
15759 VirtualRegister m_dst;
15760 VirtualRegister m_operand;
15761};
15762
15763struct OpNeqNull : public Instruction {
15764 static constexpr OpcodeID opcodeID = op_neq_null;
15765
15766 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15767 {
15768 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
15769 }
15770
15771 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
15772 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15773 {
15774 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
15775 if (shouldAssert == Assert)
15776 ASSERT(didEmit);
15777 return didEmit;
15778 }
15779
15780 template<OpcodeSize size>
15781 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15782 {
15783
15784 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
15785 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
15786 return;
15787 }
15788 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
15789 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
15790 return;
15791 }
15792 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
15793 }
15794
15795private:
15796 template<OpcodeSize size>
15797 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
15798 {
15799 UNUSED_PARAM(gen);
15800#if OS(WINDOWS) && ENABLE(C_LOOP)
15801 // FIXME: Disable wide16 optimization for Windows CLoop
15802 // https://bugs.webkit.org/show_bug.cgi?id=198283
15803 if (size == OpcodeSize::Wide16)
15804 return false;
15805#endif
15806 return Fits<OpcodeID, size>::check(opcodeID)
15807 && Fits<VirtualRegister, size>::check(dst)
15808 && Fits<VirtualRegister, size>::check(operand)
15809 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
15810 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
15811 }
15812
15813 template<OpcodeSize size, bool recordOpcode>
15814 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15815 {
15816 if (size == OpcodeSize::Wide16)
15817 gen->alignWideOpcode16();
15818 else if (size == OpcodeSize::Wide32)
15819 gen->alignWideOpcode32();
15820 if (checkImpl<size>(gen, dst, operand)) {
15821 if (recordOpcode)
15822 gen->recordOpcode(opcodeID);
15823 if (size == OpcodeSize::Wide16)
15824 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
15825 else if (size == OpcodeSize::Wide32)
15826 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
15827 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
15828 gen->write(Fits<VirtualRegister, size>::convert(dst));
15829 gen->write(Fits<VirtualRegister, size>::convert(operand));
15830 return true;
15831 }
15832 return false;
15833 }
15834
15835public:
15836 template<typename Block>
15837 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
15838 {
15839 dumper->printLocationAndOp(__location, &"**neq_null"[2 - __sizeShiftAmount]);
15840 dumper->dumpOperand(m_dst, true);
15841 dumper->dumpOperand(m_operand, false);
15842 }
15843
15844 OpNeqNull(const uint8_t* stream)
15845 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
15846 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
15847 {
15848 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15849 }
15850
15851 OpNeqNull(const uint16_t* stream)
15852 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
15853 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
15854 {
15855 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15856 }
15857
15858
15859 OpNeqNull(const uint32_t* stream)
15860 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
15861 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
15862 {
15863 ASSERT_UNUSED(stream, stream[0] == opcodeID);
15864 }
15865
15866 static OpNeqNull decode(const uint8_t* stream)
15867 {
15868 if (*stream == op_wide32)
15869 return { bitwise_cast<const uint32_t*>(stream + 1) };
15870 if (*stream == op_wide16)
15871 return { bitwise_cast<const uint16_t*>(stream + 1) };
15872 return { stream };
15873 }
15874
15875 template<typename Functor>
15876 void setDst(VirtualRegister value, Functor func)
15877 {
15878 if (isWide32())
15879 setDst<OpcodeSize::Wide32>(value, func);
15880 else if (isWide16())
15881 setDst<OpcodeSize::Wide16>(value, func);
15882 else
15883 setDst<OpcodeSize::Narrow>(value, func);
15884 }
15885
15886 template <OpcodeSize size, typename Functor>
15887 void setDst(VirtualRegister value, Functor func)
15888 {
15889 if (!Fits<VirtualRegister, size>::check(value))
15890 value = func();
15891 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
15892 *stream = Fits<VirtualRegister, size>::convert(value);
15893 }
15894
15895 template<typename Functor>
15896 void setOperand(VirtualRegister value, Functor func)
15897 {
15898 if (isWide32())
15899 setOperand<OpcodeSize::Wide32>(value, func);
15900 else if (isWide16())
15901 setOperand<OpcodeSize::Wide16>(value, func);
15902 else
15903 setOperand<OpcodeSize::Narrow>(value, func);
15904 }
15905
15906 template <OpcodeSize size, typename Functor>
15907 void setOperand(VirtualRegister value, Functor func)
15908 {
15909 if (!Fits<VirtualRegister, size>::check(value))
15910 value = func();
15911 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
15912 *stream = Fits<VirtualRegister, size>::convert(value);
15913 }
15914
15915 VirtualRegister m_dst;
15916 VirtualRegister m_operand;
15917};
15918
15919struct OpToString : public Instruction {
15920 static constexpr OpcodeID opcodeID = op_to_string;
15921
15922 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15923 {
15924 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
15925 }
15926
15927 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
15928 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15929 {
15930 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
15931 if (shouldAssert == Assert)
15932 ASSERT(didEmit);
15933 return didEmit;
15934 }
15935
15936 template<OpcodeSize size>
15937 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15938 {
15939
15940 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
15941 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
15942 return;
15943 }
15944 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
15945 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
15946 return;
15947 }
15948 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
15949 }
15950
15951private:
15952 template<OpcodeSize size>
15953 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
15954 {
15955 UNUSED_PARAM(gen);
15956#if OS(WINDOWS) && ENABLE(C_LOOP)
15957 // FIXME: Disable wide16 optimization for Windows CLoop
15958 // https://bugs.webkit.org/show_bug.cgi?id=198283
15959 if (size == OpcodeSize::Wide16)
15960 return false;
15961#endif
15962 return Fits<OpcodeID, size>::check(opcodeID)
15963 && Fits<VirtualRegister, size>::check(dst)
15964 && Fits<VirtualRegister, size>::check(operand)
15965 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
15966 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
15967 }
15968
15969 template<OpcodeSize size, bool recordOpcode>
15970 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
15971 {
15972 if (size == OpcodeSize::Wide16)
15973 gen->alignWideOpcode16();
15974 else if (size == OpcodeSize::Wide32)
15975 gen->alignWideOpcode32();
15976 if (checkImpl<size>(gen, dst, operand)) {
15977 if (recordOpcode)
15978 gen->recordOpcode(opcodeID);
15979 if (size == OpcodeSize::Wide16)
15980 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
15981 else if (size == OpcodeSize::Wide32)
15982 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
15983 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
15984 gen->write(Fits<VirtualRegister, size>::convert(dst));
15985 gen->write(Fits<VirtualRegister, size>::convert(operand));
15986 return true;
15987 }
15988 return false;
15989 }
15990
15991public:
15992 template<typename Block>
15993 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
15994 {
15995 dumper->printLocationAndOp(__location, &"**to_string"[2 - __sizeShiftAmount]);
15996 dumper->dumpOperand(m_dst, true);
15997 dumper->dumpOperand(m_operand, false);
15998 }
15999
16000 OpToString(const uint8_t* stream)
16001 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
16002 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
16003 {
16004 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16005 }
16006
16007 OpToString(const uint16_t* stream)
16008 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
16009 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
16010 {
16011 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16012 }
16013
16014
16015 OpToString(const uint32_t* stream)
16016 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
16017 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
16018 {
16019 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16020 }
16021
16022 static OpToString decode(const uint8_t* stream)
16023 {
16024 if (*stream == op_wide32)
16025 return { bitwise_cast<const uint32_t*>(stream + 1) };
16026 if (*stream == op_wide16)
16027 return { bitwise_cast<const uint16_t*>(stream + 1) };
16028 return { stream };
16029 }
16030
16031 template<typename Functor>
16032 void setDst(VirtualRegister value, Functor func)
16033 {
16034 if (isWide32())
16035 setDst<OpcodeSize::Wide32>(value, func);
16036 else if (isWide16())
16037 setDst<OpcodeSize::Wide16>(value, func);
16038 else
16039 setDst<OpcodeSize::Narrow>(value, func);
16040 }
16041
16042 template <OpcodeSize size, typename Functor>
16043 void setDst(VirtualRegister value, Functor func)
16044 {
16045 if (!Fits<VirtualRegister, size>::check(value))
16046 value = func();
16047 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
16048 *stream = Fits<VirtualRegister, size>::convert(value);
16049 }
16050
16051 template<typename Functor>
16052 void setOperand(VirtualRegister value, Functor func)
16053 {
16054 if (isWide32())
16055 setOperand<OpcodeSize::Wide32>(value, func);
16056 else if (isWide16())
16057 setOperand<OpcodeSize::Wide16>(value, func);
16058 else
16059 setOperand<OpcodeSize::Narrow>(value, func);
16060 }
16061
16062 template <OpcodeSize size, typename Functor>
16063 void setOperand(VirtualRegister value, Functor func)
16064 {
16065 if (!Fits<VirtualRegister, size>::check(value))
16066 value = func();
16067 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
16068 *stream = Fits<VirtualRegister, size>::convert(value);
16069 }
16070
16071 VirtualRegister m_dst;
16072 VirtualRegister m_operand;
16073};
16074
16075struct OpUnsigned : public Instruction {
16076 static constexpr OpcodeID opcodeID = op_unsigned;
16077
16078 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16079 {
16080 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
16081 }
16082
16083 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
16084 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16085 {
16086 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
16087 if (shouldAssert == Assert)
16088 ASSERT(didEmit);
16089 return didEmit;
16090 }
16091
16092 template<OpcodeSize size>
16093 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16094 {
16095
16096 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
16097 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
16098 return;
16099 }
16100 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
16101 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
16102 return;
16103 }
16104 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
16105 }
16106
16107private:
16108 template<OpcodeSize size>
16109 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
16110 {
16111 UNUSED_PARAM(gen);
16112#if OS(WINDOWS) && ENABLE(C_LOOP)
16113 // FIXME: Disable wide16 optimization for Windows CLoop
16114 // https://bugs.webkit.org/show_bug.cgi?id=198283
16115 if (size == OpcodeSize::Wide16)
16116 return false;
16117#endif
16118 return Fits<OpcodeID, size>::check(opcodeID)
16119 && Fits<VirtualRegister, size>::check(dst)
16120 && Fits<VirtualRegister, size>::check(operand)
16121 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
16122 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
16123 }
16124
16125 template<OpcodeSize size, bool recordOpcode>
16126 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16127 {
16128 if (size == OpcodeSize::Wide16)
16129 gen->alignWideOpcode16();
16130 else if (size == OpcodeSize::Wide32)
16131 gen->alignWideOpcode32();
16132 if (checkImpl<size>(gen, dst, operand)) {
16133 if (recordOpcode)
16134 gen->recordOpcode(opcodeID);
16135 if (size == OpcodeSize::Wide16)
16136 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
16137 else if (size == OpcodeSize::Wide32)
16138 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
16139 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
16140 gen->write(Fits<VirtualRegister, size>::convert(dst));
16141 gen->write(Fits<VirtualRegister, size>::convert(operand));
16142 return true;
16143 }
16144 return false;
16145 }
16146
16147public:
16148 template<typename Block>
16149 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
16150 {
16151 dumper->printLocationAndOp(__location, &"**unsigned"[2 - __sizeShiftAmount]);
16152 dumper->dumpOperand(m_dst, true);
16153 dumper->dumpOperand(m_operand, false);
16154 }
16155
16156 OpUnsigned(const uint8_t* stream)
16157 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
16158 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
16159 {
16160 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16161 }
16162
16163 OpUnsigned(const uint16_t* stream)
16164 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
16165 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
16166 {
16167 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16168 }
16169
16170
16171 OpUnsigned(const uint32_t* stream)
16172 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
16173 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
16174 {
16175 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16176 }
16177
16178 static OpUnsigned decode(const uint8_t* stream)
16179 {
16180 if (*stream == op_wide32)
16181 return { bitwise_cast<const uint32_t*>(stream + 1) };
16182 if (*stream == op_wide16)
16183 return { bitwise_cast<const uint16_t*>(stream + 1) };
16184 return { stream };
16185 }
16186
16187 template<typename Functor>
16188 void setDst(VirtualRegister value, Functor func)
16189 {
16190 if (isWide32())
16191 setDst<OpcodeSize::Wide32>(value, func);
16192 else if (isWide16())
16193 setDst<OpcodeSize::Wide16>(value, func);
16194 else
16195 setDst<OpcodeSize::Narrow>(value, func);
16196 }
16197
16198 template <OpcodeSize size, typename Functor>
16199 void setDst(VirtualRegister value, Functor func)
16200 {
16201 if (!Fits<VirtualRegister, size>::check(value))
16202 value = func();
16203 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
16204 *stream = Fits<VirtualRegister, size>::convert(value);
16205 }
16206
16207 template<typename Functor>
16208 void setOperand(VirtualRegister value, Functor func)
16209 {
16210 if (isWide32())
16211 setOperand<OpcodeSize::Wide32>(value, func);
16212 else if (isWide16())
16213 setOperand<OpcodeSize::Wide16>(value, func);
16214 else
16215 setOperand<OpcodeSize::Narrow>(value, func);
16216 }
16217
16218 template <OpcodeSize size, typename Functor>
16219 void setOperand(VirtualRegister value, Functor func)
16220 {
16221 if (!Fits<VirtualRegister, size>::check(value))
16222 value = func();
16223 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
16224 *stream = Fits<VirtualRegister, size>::convert(value);
16225 }
16226
16227 VirtualRegister m_dst;
16228 VirtualRegister m_operand;
16229};
16230
16231struct OpIsEmpty : public Instruction {
16232 static constexpr OpcodeID opcodeID = op_is_empty;
16233
16234 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16235 {
16236 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
16237 }
16238
16239 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
16240 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16241 {
16242 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
16243 if (shouldAssert == Assert)
16244 ASSERT(didEmit);
16245 return didEmit;
16246 }
16247
16248 template<OpcodeSize size>
16249 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16250 {
16251
16252 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
16253 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
16254 return;
16255 }
16256 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
16257 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
16258 return;
16259 }
16260 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
16261 }
16262
16263private:
16264 template<OpcodeSize size>
16265 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
16266 {
16267 UNUSED_PARAM(gen);
16268#if OS(WINDOWS) && ENABLE(C_LOOP)
16269 // FIXME: Disable wide16 optimization for Windows CLoop
16270 // https://bugs.webkit.org/show_bug.cgi?id=198283
16271 if (size == OpcodeSize::Wide16)
16272 return false;
16273#endif
16274 return Fits<OpcodeID, size>::check(opcodeID)
16275 && Fits<VirtualRegister, size>::check(dst)
16276 && Fits<VirtualRegister, size>::check(operand)
16277 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
16278 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
16279 }
16280
16281 template<OpcodeSize size, bool recordOpcode>
16282 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16283 {
16284 if (size == OpcodeSize::Wide16)
16285 gen->alignWideOpcode16();
16286 else if (size == OpcodeSize::Wide32)
16287 gen->alignWideOpcode32();
16288 if (checkImpl<size>(gen, dst, operand)) {
16289 if (recordOpcode)
16290 gen->recordOpcode(opcodeID);
16291 if (size == OpcodeSize::Wide16)
16292 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
16293 else if (size == OpcodeSize::Wide32)
16294 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
16295 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
16296 gen->write(Fits<VirtualRegister, size>::convert(dst));
16297 gen->write(Fits<VirtualRegister, size>::convert(operand));
16298 return true;
16299 }
16300 return false;
16301 }
16302
16303public:
16304 template<typename Block>
16305 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
16306 {
16307 dumper->printLocationAndOp(__location, &"**is_empty"[2 - __sizeShiftAmount]);
16308 dumper->dumpOperand(m_dst, true);
16309 dumper->dumpOperand(m_operand, false);
16310 }
16311
16312 OpIsEmpty(const uint8_t* stream)
16313 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
16314 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
16315 {
16316 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16317 }
16318
16319 OpIsEmpty(const uint16_t* stream)
16320 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
16321 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
16322 {
16323 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16324 }
16325
16326
16327 OpIsEmpty(const uint32_t* stream)
16328 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
16329 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
16330 {
16331 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16332 }
16333
16334 static OpIsEmpty decode(const uint8_t* stream)
16335 {
16336 if (*stream == op_wide32)
16337 return { bitwise_cast<const uint32_t*>(stream + 1) };
16338 if (*stream == op_wide16)
16339 return { bitwise_cast<const uint16_t*>(stream + 1) };
16340 return { stream };
16341 }
16342
16343 template<typename Functor>
16344 void setDst(VirtualRegister value, Functor func)
16345 {
16346 if (isWide32())
16347 setDst<OpcodeSize::Wide32>(value, func);
16348 else if (isWide16())
16349 setDst<OpcodeSize::Wide16>(value, func);
16350 else
16351 setDst<OpcodeSize::Narrow>(value, func);
16352 }
16353
16354 template <OpcodeSize size, typename Functor>
16355 void setDst(VirtualRegister value, Functor func)
16356 {
16357 if (!Fits<VirtualRegister, size>::check(value))
16358 value = func();
16359 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
16360 *stream = Fits<VirtualRegister, size>::convert(value);
16361 }
16362
16363 template<typename Functor>
16364 void setOperand(VirtualRegister value, Functor func)
16365 {
16366 if (isWide32())
16367 setOperand<OpcodeSize::Wide32>(value, func);
16368 else if (isWide16())
16369 setOperand<OpcodeSize::Wide16>(value, func);
16370 else
16371 setOperand<OpcodeSize::Narrow>(value, func);
16372 }
16373
16374 template <OpcodeSize size, typename Functor>
16375 void setOperand(VirtualRegister value, Functor func)
16376 {
16377 if (!Fits<VirtualRegister, size>::check(value))
16378 value = func();
16379 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
16380 *stream = Fits<VirtualRegister, size>::convert(value);
16381 }
16382
16383 VirtualRegister m_dst;
16384 VirtualRegister m_operand;
16385};
16386
16387struct OpIsUndefined : public Instruction {
16388 static constexpr OpcodeID opcodeID = op_is_undefined;
16389
16390 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16391 {
16392 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
16393 }
16394
16395 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
16396 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16397 {
16398 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
16399 if (shouldAssert == Assert)
16400 ASSERT(didEmit);
16401 return didEmit;
16402 }
16403
16404 template<OpcodeSize size>
16405 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16406 {
16407
16408 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
16409 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
16410 return;
16411 }
16412 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
16413 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
16414 return;
16415 }
16416 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
16417 }
16418
16419private:
16420 template<OpcodeSize size>
16421 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
16422 {
16423 UNUSED_PARAM(gen);
16424#if OS(WINDOWS) && ENABLE(C_LOOP)
16425 // FIXME: Disable wide16 optimization for Windows CLoop
16426 // https://bugs.webkit.org/show_bug.cgi?id=198283
16427 if (size == OpcodeSize::Wide16)
16428 return false;
16429#endif
16430 return Fits<OpcodeID, size>::check(opcodeID)
16431 && Fits<VirtualRegister, size>::check(dst)
16432 && Fits<VirtualRegister, size>::check(operand)
16433 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
16434 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
16435 }
16436
16437 template<OpcodeSize size, bool recordOpcode>
16438 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16439 {
16440 if (size == OpcodeSize::Wide16)
16441 gen->alignWideOpcode16();
16442 else if (size == OpcodeSize::Wide32)
16443 gen->alignWideOpcode32();
16444 if (checkImpl<size>(gen, dst, operand)) {
16445 if (recordOpcode)
16446 gen->recordOpcode(opcodeID);
16447 if (size == OpcodeSize::Wide16)
16448 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
16449 else if (size == OpcodeSize::Wide32)
16450 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
16451 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
16452 gen->write(Fits<VirtualRegister, size>::convert(dst));
16453 gen->write(Fits<VirtualRegister, size>::convert(operand));
16454 return true;
16455 }
16456 return false;
16457 }
16458
16459public:
16460 template<typename Block>
16461 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
16462 {
16463 dumper->printLocationAndOp(__location, &"**is_undefined"[2 - __sizeShiftAmount]);
16464 dumper->dumpOperand(m_dst, true);
16465 dumper->dumpOperand(m_operand, false);
16466 }
16467
16468 OpIsUndefined(const uint8_t* stream)
16469 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
16470 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
16471 {
16472 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16473 }
16474
16475 OpIsUndefined(const uint16_t* stream)
16476 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
16477 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
16478 {
16479 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16480 }
16481
16482
16483 OpIsUndefined(const uint32_t* stream)
16484 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
16485 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
16486 {
16487 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16488 }
16489
16490 static OpIsUndefined decode(const uint8_t* stream)
16491 {
16492 if (*stream == op_wide32)
16493 return { bitwise_cast<const uint32_t*>(stream + 1) };
16494 if (*stream == op_wide16)
16495 return { bitwise_cast<const uint16_t*>(stream + 1) };
16496 return { stream };
16497 }
16498
16499 template<typename Functor>
16500 void setDst(VirtualRegister value, Functor func)
16501 {
16502 if (isWide32())
16503 setDst<OpcodeSize::Wide32>(value, func);
16504 else if (isWide16())
16505 setDst<OpcodeSize::Wide16>(value, func);
16506 else
16507 setDst<OpcodeSize::Narrow>(value, func);
16508 }
16509
16510 template <OpcodeSize size, typename Functor>
16511 void setDst(VirtualRegister value, Functor func)
16512 {
16513 if (!Fits<VirtualRegister, size>::check(value))
16514 value = func();
16515 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
16516 *stream = Fits<VirtualRegister, size>::convert(value);
16517 }
16518
16519 template<typename Functor>
16520 void setOperand(VirtualRegister value, Functor func)
16521 {
16522 if (isWide32())
16523 setOperand<OpcodeSize::Wide32>(value, func);
16524 else if (isWide16())
16525 setOperand<OpcodeSize::Wide16>(value, func);
16526 else
16527 setOperand<OpcodeSize::Narrow>(value, func);
16528 }
16529
16530 template <OpcodeSize size, typename Functor>
16531 void setOperand(VirtualRegister value, Functor func)
16532 {
16533 if (!Fits<VirtualRegister, size>::check(value))
16534 value = func();
16535 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
16536 *stream = Fits<VirtualRegister, size>::convert(value);
16537 }
16538
16539 VirtualRegister m_dst;
16540 VirtualRegister m_operand;
16541};
16542
16543struct OpIsUndefinedOrNull : public Instruction {
16544 static constexpr OpcodeID opcodeID = op_is_undefined_or_null;
16545
16546 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16547 {
16548 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
16549 }
16550
16551 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
16552 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16553 {
16554 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
16555 if (shouldAssert == Assert)
16556 ASSERT(didEmit);
16557 return didEmit;
16558 }
16559
16560 template<OpcodeSize size>
16561 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16562 {
16563
16564 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
16565 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
16566 return;
16567 }
16568 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
16569 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
16570 return;
16571 }
16572 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
16573 }
16574
16575private:
16576 template<OpcodeSize size>
16577 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
16578 {
16579 UNUSED_PARAM(gen);
16580#if OS(WINDOWS) && ENABLE(C_LOOP)
16581 // FIXME: Disable wide16 optimization for Windows CLoop
16582 // https://bugs.webkit.org/show_bug.cgi?id=198283
16583 if (size == OpcodeSize::Wide16)
16584 return false;
16585#endif
16586 return Fits<OpcodeID, size>::check(opcodeID)
16587 && Fits<VirtualRegister, size>::check(dst)
16588 && Fits<VirtualRegister, size>::check(operand)
16589 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
16590 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
16591 }
16592
16593 template<OpcodeSize size, bool recordOpcode>
16594 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16595 {
16596 if (size == OpcodeSize::Wide16)
16597 gen->alignWideOpcode16();
16598 else if (size == OpcodeSize::Wide32)
16599 gen->alignWideOpcode32();
16600 if (checkImpl<size>(gen, dst, operand)) {
16601 if (recordOpcode)
16602 gen->recordOpcode(opcodeID);
16603 if (size == OpcodeSize::Wide16)
16604 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
16605 else if (size == OpcodeSize::Wide32)
16606 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
16607 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
16608 gen->write(Fits<VirtualRegister, size>::convert(dst));
16609 gen->write(Fits<VirtualRegister, size>::convert(operand));
16610 return true;
16611 }
16612 return false;
16613 }
16614
16615public:
16616 template<typename Block>
16617 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
16618 {
16619 dumper->printLocationAndOp(__location, &"**is_undefined_or_null"[2 - __sizeShiftAmount]);
16620 dumper->dumpOperand(m_dst, true);
16621 dumper->dumpOperand(m_operand, false);
16622 }
16623
16624 OpIsUndefinedOrNull(const uint8_t* stream)
16625 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
16626 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
16627 {
16628 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16629 }
16630
16631 OpIsUndefinedOrNull(const uint16_t* stream)
16632 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
16633 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
16634 {
16635 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16636 }
16637
16638
16639 OpIsUndefinedOrNull(const uint32_t* stream)
16640 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
16641 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
16642 {
16643 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16644 }
16645
16646 static OpIsUndefinedOrNull decode(const uint8_t* stream)
16647 {
16648 if (*stream == op_wide32)
16649 return { bitwise_cast<const uint32_t*>(stream + 1) };
16650 if (*stream == op_wide16)
16651 return { bitwise_cast<const uint16_t*>(stream + 1) };
16652 return { stream };
16653 }
16654
16655 template<typename Functor>
16656 void setDst(VirtualRegister value, Functor func)
16657 {
16658 if (isWide32())
16659 setDst<OpcodeSize::Wide32>(value, func);
16660 else if (isWide16())
16661 setDst<OpcodeSize::Wide16>(value, func);
16662 else
16663 setDst<OpcodeSize::Narrow>(value, func);
16664 }
16665
16666 template <OpcodeSize size, typename Functor>
16667 void setDst(VirtualRegister value, Functor func)
16668 {
16669 if (!Fits<VirtualRegister, size>::check(value))
16670 value = func();
16671 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
16672 *stream = Fits<VirtualRegister, size>::convert(value);
16673 }
16674
16675 template<typename Functor>
16676 void setOperand(VirtualRegister value, Functor func)
16677 {
16678 if (isWide32())
16679 setOperand<OpcodeSize::Wide32>(value, func);
16680 else if (isWide16())
16681 setOperand<OpcodeSize::Wide16>(value, func);
16682 else
16683 setOperand<OpcodeSize::Narrow>(value, func);
16684 }
16685
16686 template <OpcodeSize size, typename Functor>
16687 void setOperand(VirtualRegister value, Functor func)
16688 {
16689 if (!Fits<VirtualRegister, size>::check(value))
16690 value = func();
16691 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
16692 *stream = Fits<VirtualRegister, size>::convert(value);
16693 }
16694
16695 VirtualRegister m_dst;
16696 VirtualRegister m_operand;
16697};
16698
16699struct OpIsBoolean : public Instruction {
16700 static constexpr OpcodeID opcodeID = op_is_boolean;
16701
16702 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16703 {
16704 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
16705 }
16706
16707 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
16708 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16709 {
16710 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
16711 if (shouldAssert == Assert)
16712 ASSERT(didEmit);
16713 return didEmit;
16714 }
16715
16716 template<OpcodeSize size>
16717 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16718 {
16719
16720 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
16721 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
16722 return;
16723 }
16724 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
16725 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
16726 return;
16727 }
16728 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
16729 }
16730
16731private:
16732 template<OpcodeSize size>
16733 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
16734 {
16735 UNUSED_PARAM(gen);
16736#if OS(WINDOWS) && ENABLE(C_LOOP)
16737 // FIXME: Disable wide16 optimization for Windows CLoop
16738 // https://bugs.webkit.org/show_bug.cgi?id=198283
16739 if (size == OpcodeSize::Wide16)
16740 return false;
16741#endif
16742 return Fits<OpcodeID, size>::check(opcodeID)
16743 && Fits<VirtualRegister, size>::check(dst)
16744 && Fits<VirtualRegister, size>::check(operand)
16745 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
16746 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
16747 }
16748
16749 template<OpcodeSize size, bool recordOpcode>
16750 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16751 {
16752 if (size == OpcodeSize::Wide16)
16753 gen->alignWideOpcode16();
16754 else if (size == OpcodeSize::Wide32)
16755 gen->alignWideOpcode32();
16756 if (checkImpl<size>(gen, dst, operand)) {
16757 if (recordOpcode)
16758 gen->recordOpcode(opcodeID);
16759 if (size == OpcodeSize::Wide16)
16760 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
16761 else if (size == OpcodeSize::Wide32)
16762 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
16763 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
16764 gen->write(Fits<VirtualRegister, size>::convert(dst));
16765 gen->write(Fits<VirtualRegister, size>::convert(operand));
16766 return true;
16767 }
16768 return false;
16769 }
16770
16771public:
16772 template<typename Block>
16773 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
16774 {
16775 dumper->printLocationAndOp(__location, &"**is_boolean"[2 - __sizeShiftAmount]);
16776 dumper->dumpOperand(m_dst, true);
16777 dumper->dumpOperand(m_operand, false);
16778 }
16779
16780 OpIsBoolean(const uint8_t* stream)
16781 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
16782 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
16783 {
16784 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16785 }
16786
16787 OpIsBoolean(const uint16_t* stream)
16788 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
16789 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
16790 {
16791 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16792 }
16793
16794
16795 OpIsBoolean(const uint32_t* stream)
16796 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
16797 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
16798 {
16799 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16800 }
16801
16802 static OpIsBoolean decode(const uint8_t* stream)
16803 {
16804 if (*stream == op_wide32)
16805 return { bitwise_cast<const uint32_t*>(stream + 1) };
16806 if (*stream == op_wide16)
16807 return { bitwise_cast<const uint16_t*>(stream + 1) };
16808 return { stream };
16809 }
16810
16811 template<typename Functor>
16812 void setDst(VirtualRegister value, Functor func)
16813 {
16814 if (isWide32())
16815 setDst<OpcodeSize::Wide32>(value, func);
16816 else if (isWide16())
16817 setDst<OpcodeSize::Wide16>(value, func);
16818 else
16819 setDst<OpcodeSize::Narrow>(value, func);
16820 }
16821
16822 template <OpcodeSize size, typename Functor>
16823 void setDst(VirtualRegister value, Functor func)
16824 {
16825 if (!Fits<VirtualRegister, size>::check(value))
16826 value = func();
16827 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
16828 *stream = Fits<VirtualRegister, size>::convert(value);
16829 }
16830
16831 template<typename Functor>
16832 void setOperand(VirtualRegister value, Functor func)
16833 {
16834 if (isWide32())
16835 setOperand<OpcodeSize::Wide32>(value, func);
16836 else if (isWide16())
16837 setOperand<OpcodeSize::Wide16>(value, func);
16838 else
16839 setOperand<OpcodeSize::Narrow>(value, func);
16840 }
16841
16842 template <OpcodeSize size, typename Functor>
16843 void setOperand(VirtualRegister value, Functor func)
16844 {
16845 if (!Fits<VirtualRegister, size>::check(value))
16846 value = func();
16847 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
16848 *stream = Fits<VirtualRegister, size>::convert(value);
16849 }
16850
16851 VirtualRegister m_dst;
16852 VirtualRegister m_operand;
16853};
16854
16855struct OpIsNumber : public Instruction {
16856 static constexpr OpcodeID opcodeID = op_is_number;
16857
16858 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16859 {
16860 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
16861 }
16862
16863 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
16864 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16865 {
16866 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
16867 if (shouldAssert == Assert)
16868 ASSERT(didEmit);
16869 return didEmit;
16870 }
16871
16872 template<OpcodeSize size>
16873 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16874 {
16875
16876 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
16877 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
16878 return;
16879 }
16880 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
16881 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
16882 return;
16883 }
16884 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
16885 }
16886
16887private:
16888 template<OpcodeSize size>
16889 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
16890 {
16891 UNUSED_PARAM(gen);
16892#if OS(WINDOWS) && ENABLE(C_LOOP)
16893 // FIXME: Disable wide16 optimization for Windows CLoop
16894 // https://bugs.webkit.org/show_bug.cgi?id=198283
16895 if (size == OpcodeSize::Wide16)
16896 return false;
16897#endif
16898 return Fits<OpcodeID, size>::check(opcodeID)
16899 && Fits<VirtualRegister, size>::check(dst)
16900 && Fits<VirtualRegister, size>::check(operand)
16901 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
16902 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
16903 }
16904
16905 template<OpcodeSize size, bool recordOpcode>
16906 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
16907 {
16908 if (size == OpcodeSize::Wide16)
16909 gen->alignWideOpcode16();
16910 else if (size == OpcodeSize::Wide32)
16911 gen->alignWideOpcode32();
16912 if (checkImpl<size>(gen, dst, operand)) {
16913 if (recordOpcode)
16914 gen->recordOpcode(opcodeID);
16915 if (size == OpcodeSize::Wide16)
16916 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
16917 else if (size == OpcodeSize::Wide32)
16918 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
16919 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
16920 gen->write(Fits<VirtualRegister, size>::convert(dst));
16921 gen->write(Fits<VirtualRegister, size>::convert(operand));
16922 return true;
16923 }
16924 return false;
16925 }
16926
16927public:
16928 template<typename Block>
16929 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
16930 {
16931 dumper->printLocationAndOp(__location, &"**is_number"[2 - __sizeShiftAmount]);
16932 dumper->dumpOperand(m_dst, true);
16933 dumper->dumpOperand(m_operand, false);
16934 }
16935
16936 OpIsNumber(const uint8_t* stream)
16937 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
16938 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
16939 {
16940 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16941 }
16942
16943 OpIsNumber(const uint16_t* stream)
16944 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
16945 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
16946 {
16947 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16948 }
16949
16950
16951 OpIsNumber(const uint32_t* stream)
16952 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
16953 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
16954 {
16955 ASSERT_UNUSED(stream, stream[0] == opcodeID);
16956 }
16957
16958 static OpIsNumber decode(const uint8_t* stream)
16959 {
16960 if (*stream == op_wide32)
16961 return { bitwise_cast<const uint32_t*>(stream + 1) };
16962 if (*stream == op_wide16)
16963 return { bitwise_cast<const uint16_t*>(stream + 1) };
16964 return { stream };
16965 }
16966
16967 template<typename Functor>
16968 void setDst(VirtualRegister value, Functor func)
16969 {
16970 if (isWide32())
16971 setDst<OpcodeSize::Wide32>(value, func);
16972 else if (isWide16())
16973 setDst<OpcodeSize::Wide16>(value, func);
16974 else
16975 setDst<OpcodeSize::Narrow>(value, func);
16976 }
16977
16978 template <OpcodeSize size, typename Functor>
16979 void setDst(VirtualRegister value, Functor func)
16980 {
16981 if (!Fits<VirtualRegister, size>::check(value))
16982 value = func();
16983 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
16984 *stream = Fits<VirtualRegister, size>::convert(value);
16985 }
16986
16987 template<typename Functor>
16988 void setOperand(VirtualRegister value, Functor func)
16989 {
16990 if (isWide32())
16991 setOperand<OpcodeSize::Wide32>(value, func);
16992 else if (isWide16())
16993 setOperand<OpcodeSize::Wide16>(value, func);
16994 else
16995 setOperand<OpcodeSize::Narrow>(value, func);
16996 }
16997
16998 template <OpcodeSize size, typename Functor>
16999 void setOperand(VirtualRegister value, Functor func)
17000 {
17001 if (!Fits<VirtualRegister, size>::check(value))
17002 value = func();
17003 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
17004 *stream = Fits<VirtualRegister, size>::convert(value);
17005 }
17006
17007 VirtualRegister m_dst;
17008 VirtualRegister m_operand;
17009};
17010
17011struct OpIsObject : public Instruction {
17012 static constexpr OpcodeID opcodeID = op_is_object;
17013
17014 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17015 {
17016 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
17017 }
17018
17019 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
17020 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17021 {
17022 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
17023 if (shouldAssert == Assert)
17024 ASSERT(didEmit);
17025 return didEmit;
17026 }
17027
17028 template<OpcodeSize size>
17029 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17030 {
17031
17032 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
17033 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
17034 return;
17035 }
17036 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
17037 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
17038 return;
17039 }
17040 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
17041 }
17042
17043private:
17044 template<OpcodeSize size>
17045 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
17046 {
17047 UNUSED_PARAM(gen);
17048#if OS(WINDOWS) && ENABLE(C_LOOP)
17049 // FIXME: Disable wide16 optimization for Windows CLoop
17050 // https://bugs.webkit.org/show_bug.cgi?id=198283
17051 if (size == OpcodeSize::Wide16)
17052 return false;
17053#endif
17054 return Fits<OpcodeID, size>::check(opcodeID)
17055 && Fits<VirtualRegister, size>::check(dst)
17056 && Fits<VirtualRegister, size>::check(operand)
17057 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
17058 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
17059 }
17060
17061 template<OpcodeSize size, bool recordOpcode>
17062 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17063 {
17064 if (size == OpcodeSize::Wide16)
17065 gen->alignWideOpcode16();
17066 else if (size == OpcodeSize::Wide32)
17067 gen->alignWideOpcode32();
17068 if (checkImpl<size>(gen, dst, operand)) {
17069 if (recordOpcode)
17070 gen->recordOpcode(opcodeID);
17071 if (size == OpcodeSize::Wide16)
17072 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
17073 else if (size == OpcodeSize::Wide32)
17074 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
17075 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
17076 gen->write(Fits<VirtualRegister, size>::convert(dst));
17077 gen->write(Fits<VirtualRegister, size>::convert(operand));
17078 return true;
17079 }
17080 return false;
17081 }
17082
17083public:
17084 template<typename Block>
17085 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
17086 {
17087 dumper->printLocationAndOp(__location, &"**is_object"[2 - __sizeShiftAmount]);
17088 dumper->dumpOperand(m_dst, true);
17089 dumper->dumpOperand(m_operand, false);
17090 }
17091
17092 OpIsObject(const uint8_t* stream)
17093 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
17094 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
17095 {
17096 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17097 }
17098
17099 OpIsObject(const uint16_t* stream)
17100 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
17101 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
17102 {
17103 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17104 }
17105
17106
17107 OpIsObject(const uint32_t* stream)
17108 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
17109 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
17110 {
17111 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17112 }
17113
17114 static OpIsObject decode(const uint8_t* stream)
17115 {
17116 if (*stream == op_wide32)
17117 return { bitwise_cast<const uint32_t*>(stream + 1) };
17118 if (*stream == op_wide16)
17119 return { bitwise_cast<const uint16_t*>(stream + 1) };
17120 return { stream };
17121 }
17122
17123 template<typename Functor>
17124 void setDst(VirtualRegister value, Functor func)
17125 {
17126 if (isWide32())
17127 setDst<OpcodeSize::Wide32>(value, func);
17128 else if (isWide16())
17129 setDst<OpcodeSize::Wide16>(value, func);
17130 else
17131 setDst<OpcodeSize::Narrow>(value, func);
17132 }
17133
17134 template <OpcodeSize size, typename Functor>
17135 void setDst(VirtualRegister value, Functor func)
17136 {
17137 if (!Fits<VirtualRegister, size>::check(value))
17138 value = func();
17139 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
17140 *stream = Fits<VirtualRegister, size>::convert(value);
17141 }
17142
17143 template<typename Functor>
17144 void setOperand(VirtualRegister value, Functor func)
17145 {
17146 if (isWide32())
17147 setOperand<OpcodeSize::Wide32>(value, func);
17148 else if (isWide16())
17149 setOperand<OpcodeSize::Wide16>(value, func);
17150 else
17151 setOperand<OpcodeSize::Narrow>(value, func);
17152 }
17153
17154 template <OpcodeSize size, typename Functor>
17155 void setOperand(VirtualRegister value, Functor func)
17156 {
17157 if (!Fits<VirtualRegister, size>::check(value))
17158 value = func();
17159 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
17160 *stream = Fits<VirtualRegister, size>::convert(value);
17161 }
17162
17163 VirtualRegister m_dst;
17164 VirtualRegister m_operand;
17165};
17166
17167struct OpIsObjectOrNull : public Instruction {
17168 static constexpr OpcodeID opcodeID = op_is_object_or_null;
17169
17170 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17171 {
17172 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
17173 }
17174
17175 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
17176 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17177 {
17178 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
17179 if (shouldAssert == Assert)
17180 ASSERT(didEmit);
17181 return didEmit;
17182 }
17183
17184 template<OpcodeSize size>
17185 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17186 {
17187
17188 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
17189 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
17190 return;
17191 }
17192 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
17193 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
17194 return;
17195 }
17196 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
17197 }
17198
17199private:
17200 template<OpcodeSize size>
17201 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
17202 {
17203 UNUSED_PARAM(gen);
17204#if OS(WINDOWS) && ENABLE(C_LOOP)
17205 // FIXME: Disable wide16 optimization for Windows CLoop
17206 // https://bugs.webkit.org/show_bug.cgi?id=198283
17207 if (size == OpcodeSize::Wide16)
17208 return false;
17209#endif
17210 return Fits<OpcodeID, size>::check(opcodeID)
17211 && Fits<VirtualRegister, size>::check(dst)
17212 && Fits<VirtualRegister, size>::check(operand)
17213 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
17214 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
17215 }
17216
17217 template<OpcodeSize size, bool recordOpcode>
17218 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17219 {
17220 if (size == OpcodeSize::Wide16)
17221 gen->alignWideOpcode16();
17222 else if (size == OpcodeSize::Wide32)
17223 gen->alignWideOpcode32();
17224 if (checkImpl<size>(gen, dst, operand)) {
17225 if (recordOpcode)
17226 gen->recordOpcode(opcodeID);
17227 if (size == OpcodeSize::Wide16)
17228 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
17229 else if (size == OpcodeSize::Wide32)
17230 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
17231 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
17232 gen->write(Fits<VirtualRegister, size>::convert(dst));
17233 gen->write(Fits<VirtualRegister, size>::convert(operand));
17234 return true;
17235 }
17236 return false;
17237 }
17238
17239public:
17240 template<typename Block>
17241 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
17242 {
17243 dumper->printLocationAndOp(__location, &"**is_object_or_null"[2 - __sizeShiftAmount]);
17244 dumper->dumpOperand(m_dst, true);
17245 dumper->dumpOperand(m_operand, false);
17246 }
17247
17248 OpIsObjectOrNull(const uint8_t* stream)
17249 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
17250 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
17251 {
17252 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17253 }
17254
17255 OpIsObjectOrNull(const uint16_t* stream)
17256 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
17257 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
17258 {
17259 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17260 }
17261
17262
17263 OpIsObjectOrNull(const uint32_t* stream)
17264 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
17265 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
17266 {
17267 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17268 }
17269
17270 static OpIsObjectOrNull decode(const uint8_t* stream)
17271 {
17272 if (*stream == op_wide32)
17273 return { bitwise_cast<const uint32_t*>(stream + 1) };
17274 if (*stream == op_wide16)
17275 return { bitwise_cast<const uint16_t*>(stream + 1) };
17276 return { stream };
17277 }
17278
17279 template<typename Functor>
17280 void setDst(VirtualRegister value, Functor func)
17281 {
17282 if (isWide32())
17283 setDst<OpcodeSize::Wide32>(value, func);
17284 else if (isWide16())
17285 setDst<OpcodeSize::Wide16>(value, func);
17286 else
17287 setDst<OpcodeSize::Narrow>(value, func);
17288 }
17289
17290 template <OpcodeSize size, typename Functor>
17291 void setDst(VirtualRegister value, Functor func)
17292 {
17293 if (!Fits<VirtualRegister, size>::check(value))
17294 value = func();
17295 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
17296 *stream = Fits<VirtualRegister, size>::convert(value);
17297 }
17298
17299 template<typename Functor>
17300 void setOperand(VirtualRegister value, Functor func)
17301 {
17302 if (isWide32())
17303 setOperand<OpcodeSize::Wide32>(value, func);
17304 else if (isWide16())
17305 setOperand<OpcodeSize::Wide16>(value, func);
17306 else
17307 setOperand<OpcodeSize::Narrow>(value, func);
17308 }
17309
17310 template <OpcodeSize size, typename Functor>
17311 void setOperand(VirtualRegister value, Functor func)
17312 {
17313 if (!Fits<VirtualRegister, size>::check(value))
17314 value = func();
17315 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
17316 *stream = Fits<VirtualRegister, size>::convert(value);
17317 }
17318
17319 VirtualRegister m_dst;
17320 VirtualRegister m_operand;
17321};
17322
17323struct OpIsFunction : public Instruction {
17324 static constexpr OpcodeID opcodeID = op_is_function;
17325
17326 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17327 {
17328 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
17329 }
17330
17331 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
17332 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17333 {
17334 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
17335 if (shouldAssert == Assert)
17336 ASSERT(didEmit);
17337 return didEmit;
17338 }
17339
17340 template<OpcodeSize size>
17341 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17342 {
17343
17344 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
17345 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
17346 return;
17347 }
17348 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
17349 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
17350 return;
17351 }
17352 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
17353 }
17354
17355private:
17356 template<OpcodeSize size>
17357 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
17358 {
17359 UNUSED_PARAM(gen);
17360#if OS(WINDOWS) && ENABLE(C_LOOP)
17361 // FIXME: Disable wide16 optimization for Windows CLoop
17362 // https://bugs.webkit.org/show_bug.cgi?id=198283
17363 if (size == OpcodeSize::Wide16)
17364 return false;
17365#endif
17366 return Fits<OpcodeID, size>::check(opcodeID)
17367 && Fits<VirtualRegister, size>::check(dst)
17368 && Fits<VirtualRegister, size>::check(operand)
17369 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
17370 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
17371 }
17372
17373 template<OpcodeSize size, bool recordOpcode>
17374 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17375 {
17376 if (size == OpcodeSize::Wide16)
17377 gen->alignWideOpcode16();
17378 else if (size == OpcodeSize::Wide32)
17379 gen->alignWideOpcode32();
17380 if (checkImpl<size>(gen, dst, operand)) {
17381 if (recordOpcode)
17382 gen->recordOpcode(opcodeID);
17383 if (size == OpcodeSize::Wide16)
17384 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
17385 else if (size == OpcodeSize::Wide32)
17386 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
17387 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
17388 gen->write(Fits<VirtualRegister, size>::convert(dst));
17389 gen->write(Fits<VirtualRegister, size>::convert(operand));
17390 return true;
17391 }
17392 return false;
17393 }
17394
17395public:
17396 template<typename Block>
17397 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
17398 {
17399 dumper->printLocationAndOp(__location, &"**is_function"[2 - __sizeShiftAmount]);
17400 dumper->dumpOperand(m_dst, true);
17401 dumper->dumpOperand(m_operand, false);
17402 }
17403
17404 OpIsFunction(const uint8_t* stream)
17405 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
17406 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
17407 {
17408 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17409 }
17410
17411 OpIsFunction(const uint16_t* stream)
17412 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
17413 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
17414 {
17415 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17416 }
17417
17418
17419 OpIsFunction(const uint32_t* stream)
17420 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
17421 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
17422 {
17423 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17424 }
17425
17426 static OpIsFunction decode(const uint8_t* stream)
17427 {
17428 if (*stream == op_wide32)
17429 return { bitwise_cast<const uint32_t*>(stream + 1) };
17430 if (*stream == op_wide16)
17431 return { bitwise_cast<const uint16_t*>(stream + 1) };
17432 return { stream };
17433 }
17434
17435 template<typename Functor>
17436 void setDst(VirtualRegister value, Functor func)
17437 {
17438 if (isWide32())
17439 setDst<OpcodeSize::Wide32>(value, func);
17440 else if (isWide16())
17441 setDst<OpcodeSize::Wide16>(value, func);
17442 else
17443 setDst<OpcodeSize::Narrow>(value, func);
17444 }
17445
17446 template <OpcodeSize size, typename Functor>
17447 void setDst(VirtualRegister value, Functor func)
17448 {
17449 if (!Fits<VirtualRegister, size>::check(value))
17450 value = func();
17451 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(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 setOperand(VirtualRegister value, Functor func)
17457 {
17458 if (isWide32())
17459 setOperand<OpcodeSize::Wide32>(value, func);
17460 else if (isWide16())
17461 setOperand<OpcodeSize::Wide16>(value, func);
17462 else
17463 setOperand<OpcodeSize::Narrow>(value, func);
17464 }
17465
17466 template <OpcodeSize size, typename Functor>
17467 void setOperand(VirtualRegister value, Functor func)
17468 {
17469 if (!Fits<VirtualRegister, size>::check(value))
17470 value = func();
17471 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
17472 *stream = Fits<VirtualRegister, size>::convert(value);
17473 }
17474
17475 VirtualRegister m_dst;
17476 VirtualRegister m_operand;
17477};
17478
17479struct OpInc : public Instruction {
17480 static constexpr OpcodeID opcodeID = op_inc;
17481
17482 static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
17483 {
17484 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst);
17485 }
17486
17487 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
17488 static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst)
17489 {
17490 bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst);
17491 if (shouldAssert == Assert)
17492 ASSERT(didEmit);
17493 return didEmit;
17494 }
17495
17496 template<OpcodeSize size>
17497 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst)
17498 {
17499
17500 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
17501 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst))
17502 return;
17503 }
17504 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
17505 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst))
17506 return;
17507 }
17508 emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst);
17509 }
17510
17511private:
17512 template<OpcodeSize size>
17513 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst)
17514 {
17515 UNUSED_PARAM(gen);
17516#if OS(WINDOWS) && ENABLE(C_LOOP)
17517 // FIXME: Disable wide16 optimization for Windows CLoop
17518 // https://bugs.webkit.org/show_bug.cgi?id=198283
17519 if (size == OpcodeSize::Wide16)
17520 return false;
17521#endif
17522 return Fits<OpcodeID, size>::check(opcodeID)
17523 && Fits<VirtualRegister, size>::check(srcDst)
17524 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
17525 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
17526 }
17527
17528 template<OpcodeSize size, bool recordOpcode>
17529 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst)
17530 {
17531 if (size == OpcodeSize::Wide16)
17532 gen->alignWideOpcode16();
17533 else if (size == OpcodeSize::Wide32)
17534 gen->alignWideOpcode32();
17535 if (checkImpl<size>(gen, srcDst)) {
17536 if (recordOpcode)
17537 gen->recordOpcode(opcodeID);
17538 if (size == OpcodeSize::Wide16)
17539 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
17540 else if (size == OpcodeSize::Wide32)
17541 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
17542 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
17543 gen->write(Fits<VirtualRegister, size>::convert(srcDst));
17544 return true;
17545 }
17546 return false;
17547 }
17548
17549public:
17550 template<typename Block>
17551 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
17552 {
17553 dumper->printLocationAndOp(__location, &"**inc"[2 - __sizeShiftAmount]);
17554 dumper->dumpOperand(m_srcDst, true);
17555 }
17556
17557 OpInc(const uint8_t* stream)
17558 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
17559 {
17560 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17561 }
17562
17563 OpInc(const uint16_t* stream)
17564 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
17565 {
17566 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17567 }
17568
17569
17570 OpInc(const uint32_t* stream)
17571 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
17572 {
17573 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17574 }
17575
17576 static OpInc decode(const uint8_t* stream)
17577 {
17578 if (*stream == op_wide32)
17579 return { bitwise_cast<const uint32_t*>(stream + 1) };
17580 if (*stream == op_wide16)
17581 return { bitwise_cast<const uint16_t*>(stream + 1) };
17582 return { stream };
17583 }
17584
17585 template<typename Functor>
17586 void setSrcDst(VirtualRegister value, Functor func)
17587 {
17588 if (isWide32())
17589 setSrcDst<OpcodeSize::Wide32>(value, func);
17590 else if (isWide16())
17591 setSrcDst<OpcodeSize::Wide16>(value, func);
17592 else
17593 setSrcDst<OpcodeSize::Narrow>(value, func);
17594 }
17595
17596 template <OpcodeSize size, typename Functor>
17597 void setSrcDst(VirtualRegister value, Functor func)
17598 {
17599 if (!Fits<VirtualRegister, size>::check(value))
17600 value = func();
17601 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
17602 *stream = Fits<VirtualRegister, size>::convert(value);
17603 }
17604
17605 VirtualRegister m_srcDst;
17606};
17607
17608struct OpDec : public Instruction {
17609 static constexpr OpcodeID opcodeID = op_dec;
17610
17611 static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
17612 {
17613 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst);
17614 }
17615
17616 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
17617 static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst)
17618 {
17619 bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst);
17620 if (shouldAssert == Assert)
17621 ASSERT(didEmit);
17622 return didEmit;
17623 }
17624
17625 template<OpcodeSize size>
17626 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst)
17627 {
17628
17629 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
17630 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst))
17631 return;
17632 }
17633 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
17634 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst))
17635 return;
17636 }
17637 emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst);
17638 }
17639
17640private:
17641 template<OpcodeSize size>
17642 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst)
17643 {
17644 UNUSED_PARAM(gen);
17645#if OS(WINDOWS) && ENABLE(C_LOOP)
17646 // FIXME: Disable wide16 optimization for Windows CLoop
17647 // https://bugs.webkit.org/show_bug.cgi?id=198283
17648 if (size == OpcodeSize::Wide16)
17649 return false;
17650#endif
17651 return Fits<OpcodeID, size>::check(opcodeID)
17652 && Fits<VirtualRegister, size>::check(srcDst)
17653 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
17654 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
17655 }
17656
17657 template<OpcodeSize size, bool recordOpcode>
17658 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst)
17659 {
17660 if (size == OpcodeSize::Wide16)
17661 gen->alignWideOpcode16();
17662 else if (size == OpcodeSize::Wide32)
17663 gen->alignWideOpcode32();
17664 if (checkImpl<size>(gen, srcDst)) {
17665 if (recordOpcode)
17666 gen->recordOpcode(opcodeID);
17667 if (size == OpcodeSize::Wide16)
17668 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
17669 else if (size == OpcodeSize::Wide32)
17670 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
17671 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
17672 gen->write(Fits<VirtualRegister, size>::convert(srcDst));
17673 return true;
17674 }
17675 return false;
17676 }
17677
17678public:
17679 template<typename Block>
17680 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
17681 {
17682 dumper->printLocationAndOp(__location, &"**dec"[2 - __sizeShiftAmount]);
17683 dumper->dumpOperand(m_srcDst, true);
17684 }
17685
17686 OpDec(const uint8_t* stream)
17687 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
17688 {
17689 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17690 }
17691
17692 OpDec(const uint16_t* stream)
17693 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
17694 {
17695 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17696 }
17697
17698
17699 OpDec(const uint32_t* stream)
17700 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
17701 {
17702 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17703 }
17704
17705 static OpDec decode(const uint8_t* stream)
17706 {
17707 if (*stream == op_wide32)
17708 return { bitwise_cast<const uint32_t*>(stream + 1) };
17709 if (*stream == op_wide16)
17710 return { bitwise_cast<const uint16_t*>(stream + 1) };
17711 return { stream };
17712 }
17713
17714 template<typename Functor>
17715 void setSrcDst(VirtualRegister value, Functor func)
17716 {
17717 if (isWide32())
17718 setSrcDst<OpcodeSize::Wide32>(value, func);
17719 else if (isWide16())
17720 setSrcDst<OpcodeSize::Wide16>(value, func);
17721 else
17722 setSrcDst<OpcodeSize::Narrow>(value, func);
17723 }
17724
17725 template <OpcodeSize size, typename Functor>
17726 void setSrcDst(VirtualRegister value, Functor func)
17727 {
17728 if (!Fits<VirtualRegister, size>::check(value))
17729 value = func();
17730 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
17731 *stream = Fits<VirtualRegister, size>::convert(value);
17732 }
17733
17734 VirtualRegister m_srcDst;
17735};
17736
17737struct OpNot : public Instruction {
17738 static constexpr OpcodeID opcodeID = op_not;
17739
17740 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17741 {
17742 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
17743 }
17744
17745 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
17746 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17747 {
17748 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand);
17749 if (shouldAssert == Assert)
17750 ASSERT(didEmit);
17751 return didEmit;
17752 }
17753
17754 template<OpcodeSize size>
17755 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17756 {
17757
17758 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
17759 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
17760 return;
17761 }
17762 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
17763 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
17764 return;
17765 }
17766 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
17767 }
17768
17769private:
17770 template<OpcodeSize size>
17771 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
17772 {
17773 UNUSED_PARAM(gen);
17774#if OS(WINDOWS) && ENABLE(C_LOOP)
17775 // FIXME: Disable wide16 optimization for Windows CLoop
17776 // https://bugs.webkit.org/show_bug.cgi?id=198283
17777 if (size == OpcodeSize::Wide16)
17778 return false;
17779#endif
17780 return Fits<OpcodeID, size>::check(opcodeID)
17781 && Fits<VirtualRegister, size>::check(dst)
17782 && Fits<VirtualRegister, size>::check(operand)
17783 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
17784 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
17785 }
17786
17787 template<OpcodeSize size, bool recordOpcode>
17788 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
17789 {
17790 if (size == OpcodeSize::Wide16)
17791 gen->alignWideOpcode16();
17792 else if (size == OpcodeSize::Wide32)
17793 gen->alignWideOpcode32();
17794 if (checkImpl<size>(gen, dst, operand)) {
17795 if (recordOpcode)
17796 gen->recordOpcode(opcodeID);
17797 if (size == OpcodeSize::Wide16)
17798 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
17799 else if (size == OpcodeSize::Wide32)
17800 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
17801 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
17802 gen->write(Fits<VirtualRegister, size>::convert(dst));
17803 gen->write(Fits<VirtualRegister, size>::convert(operand));
17804 return true;
17805 }
17806 return false;
17807 }
17808
17809public:
17810 template<typename Block>
17811 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
17812 {
17813 dumper->printLocationAndOp(__location, &"**not"[2 - __sizeShiftAmount]);
17814 dumper->dumpOperand(m_dst, true);
17815 dumper->dumpOperand(m_operand, false);
17816 }
17817
17818 OpNot(const uint8_t* stream)
17819 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
17820 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
17821 {
17822 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17823 }
17824
17825 OpNot(const uint16_t* stream)
17826 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
17827 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
17828 {
17829 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17830 }
17831
17832
17833 OpNot(const uint32_t* stream)
17834 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
17835 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
17836 {
17837 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17838 }
17839
17840 static OpNot decode(const uint8_t* stream)
17841 {
17842 if (*stream == op_wide32)
17843 return { bitwise_cast<const uint32_t*>(stream + 1) };
17844 if (*stream == op_wide16)
17845 return { bitwise_cast<const uint16_t*>(stream + 1) };
17846 return { stream };
17847 }
17848
17849 template<typename Functor>
17850 void setDst(VirtualRegister value, Functor func)
17851 {
17852 if (isWide32())
17853 setDst<OpcodeSize::Wide32>(value, func);
17854 else if (isWide16())
17855 setDst<OpcodeSize::Wide16>(value, func);
17856 else
17857 setDst<OpcodeSize::Narrow>(value, func);
17858 }
17859
17860 template <OpcodeSize size, typename Functor>
17861 void setDst(VirtualRegister value, Functor func)
17862 {
17863 if (!Fits<VirtualRegister, size>::check(value))
17864 value = func();
17865 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
17866 *stream = Fits<VirtualRegister, size>::convert(value);
17867 }
17868
17869 template<typename Functor>
17870 void setOperand(VirtualRegister value, Functor func)
17871 {
17872 if (isWide32())
17873 setOperand<OpcodeSize::Wide32>(value, func);
17874 else if (isWide16())
17875 setOperand<OpcodeSize::Wide16>(value, func);
17876 else
17877 setOperand<OpcodeSize::Narrow>(value, func);
17878 }
17879
17880 template <OpcodeSize size, typename Functor>
17881 void setOperand(VirtualRegister value, Functor func)
17882 {
17883 if (!Fits<VirtualRegister, size>::check(value))
17884 value = func();
17885 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
17886 *stream = Fits<VirtualRegister, size>::convert(value);
17887 }
17888
17889 VirtualRegister m_dst;
17890 VirtualRegister m_operand;
17891};
17892
17893struct OpIdentityWithProfile : public Instruction {
17894 static constexpr OpcodeID opcodeID = op_identity_with_profile;
17895
17896 static void emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
17897 {
17898 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst, topProfile, bottomProfile);
17899 }
17900
17901 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
17902 static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
17903 {
17904 bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst, topProfile, bottomProfile);
17905 if (shouldAssert == Assert)
17906 ASSERT(didEmit);
17907 return didEmit;
17908 }
17909
17910 template<OpcodeSize size>
17911 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
17912 {
17913
17914 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
17915 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst, topProfile, bottomProfile))
17916 return;
17917 }
17918 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
17919 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst, topProfile, bottomProfile))
17920 return;
17921 }
17922 emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst, topProfile, bottomProfile);
17923 }
17924
17925private:
17926 template<OpcodeSize size>
17927 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst, unsigned& topProfile, unsigned& bottomProfile)
17928 {
17929 UNUSED_PARAM(gen);
17930#if OS(WINDOWS) && ENABLE(C_LOOP)
17931 // FIXME: Disable wide16 optimization for Windows CLoop
17932 // https://bugs.webkit.org/show_bug.cgi?id=198283
17933 if (size == OpcodeSize::Wide16)
17934 return false;
17935#endif
17936 return Fits<OpcodeID, size>::check(opcodeID)
17937 && Fits<VirtualRegister, size>::check(srcDst)
17938 && Fits<unsigned, size>::check(topProfile)
17939 && Fits<unsigned, size>::check(bottomProfile)
17940 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
17941 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
17942 }
17943
17944 template<OpcodeSize size, bool recordOpcode>
17945 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
17946 {
17947 if (size == OpcodeSize::Wide16)
17948 gen->alignWideOpcode16();
17949 else if (size == OpcodeSize::Wide32)
17950 gen->alignWideOpcode32();
17951 if (checkImpl<size>(gen, srcDst, topProfile, bottomProfile)) {
17952 if (recordOpcode)
17953 gen->recordOpcode(opcodeID);
17954 if (size == OpcodeSize::Wide16)
17955 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
17956 else if (size == OpcodeSize::Wide32)
17957 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
17958 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
17959 gen->write(Fits<VirtualRegister, size>::convert(srcDst));
17960 gen->write(Fits<unsigned, size>::convert(topProfile));
17961 gen->write(Fits<unsigned, size>::convert(bottomProfile));
17962 return true;
17963 }
17964 return false;
17965 }
17966
17967public:
17968 template<typename Block>
17969 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
17970 {
17971 dumper->printLocationAndOp(__location, &"**identity_with_profile"[2 - __sizeShiftAmount]);
17972 dumper->dumpOperand(m_srcDst, true);
17973 dumper->dumpOperand(m_topProfile, false);
17974 dumper->dumpOperand(m_bottomProfile, false);
17975 }
17976
17977 OpIdentityWithProfile(const uint8_t* stream)
17978 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
17979 , m_topProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
17980 , m_bottomProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
17981 {
17982 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17983 }
17984
17985 OpIdentityWithProfile(const uint16_t* stream)
17986 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
17987 , m_topProfile(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
17988 , m_bottomProfile(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
17989 {
17990 ASSERT_UNUSED(stream, stream[0] == opcodeID);
17991 }
17992
17993
17994 OpIdentityWithProfile(const uint32_t* stream)
17995 : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
17996 , m_topProfile(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
17997 , m_bottomProfile(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
17998 {
17999 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18000 }
18001
18002 static OpIdentityWithProfile decode(const uint8_t* stream)
18003 {
18004 if (*stream == op_wide32)
18005 return { bitwise_cast<const uint32_t*>(stream + 1) };
18006 if (*stream == op_wide16)
18007 return { bitwise_cast<const uint16_t*>(stream + 1) };
18008 return { stream };
18009 }
18010
18011 template<typename Functor>
18012 void setSrcDst(VirtualRegister value, Functor func)
18013 {
18014 if (isWide32())
18015 setSrcDst<OpcodeSize::Wide32>(value, func);
18016 else if (isWide16())
18017 setSrcDst<OpcodeSize::Wide16>(value, func);
18018 else
18019 setSrcDst<OpcodeSize::Narrow>(value, func);
18020 }
18021
18022 template <OpcodeSize size, typename Functor>
18023 void setSrcDst(VirtualRegister value, Functor func)
18024 {
18025 if (!Fits<VirtualRegister, size>::check(value))
18026 value = func();
18027 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
18028 *stream = Fits<VirtualRegister, size>::convert(value);
18029 }
18030
18031 template<typename Functor>
18032 void setTopProfile(unsigned value, Functor func)
18033 {
18034 if (isWide32())
18035 setTopProfile<OpcodeSize::Wide32>(value, func);
18036 else if (isWide16())
18037 setTopProfile<OpcodeSize::Wide16>(value, func);
18038 else
18039 setTopProfile<OpcodeSize::Narrow>(value, func);
18040 }
18041
18042 template <OpcodeSize size, typename Functor>
18043 void setTopProfile(unsigned value, Functor func)
18044 {
18045 if (!Fits<unsigned, size>::check(value))
18046 value = func();
18047 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
18048 *stream = Fits<unsigned, size>::convert(value);
18049 }
18050
18051 template<typename Functor>
18052 void setBottomProfile(unsigned value, Functor func)
18053 {
18054 if (isWide32())
18055 setBottomProfile<OpcodeSize::Wide32>(value, func);
18056 else if (isWide16())
18057 setBottomProfile<OpcodeSize::Wide16>(value, func);
18058 else
18059 setBottomProfile<OpcodeSize::Narrow>(value, func);
18060 }
18061
18062 template <OpcodeSize size, typename Functor>
18063 void setBottomProfile(unsigned value, Functor func)
18064 {
18065 if (!Fits<unsigned, size>::check(value))
18066 value = func();
18067 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
18068 *stream = Fits<unsigned, size>::convert(value);
18069 }
18070
18071 VirtualRegister m_srcDst;
18072 unsigned m_topProfile;
18073 unsigned m_bottomProfile;
18074};
18075
18076struct OpOverridesHasInstance : public Instruction {
18077 static constexpr OpcodeID opcodeID = op_overrides_has_instance;
18078
18079 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18080 {
18081 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, constructor, hasInstanceValue);
18082 }
18083
18084 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
18085 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18086 {
18087 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, constructor, hasInstanceValue);
18088 if (shouldAssert == Assert)
18089 ASSERT(didEmit);
18090 return didEmit;
18091 }
18092
18093 template<OpcodeSize size>
18094 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18095 {
18096
18097 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
18098 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, constructor, hasInstanceValue))
18099 return;
18100 }
18101 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
18102 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, constructor, hasInstanceValue))
18103 return;
18104 }
18105 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, constructor, hasInstanceValue);
18106 }
18107
18108private:
18109 template<OpcodeSize size>
18110 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& constructor, VirtualRegister& hasInstanceValue)
18111 {
18112 UNUSED_PARAM(gen);
18113#if OS(WINDOWS) && ENABLE(C_LOOP)
18114 // FIXME: Disable wide16 optimization for Windows CLoop
18115 // https://bugs.webkit.org/show_bug.cgi?id=198283
18116 if (size == OpcodeSize::Wide16)
18117 return false;
18118#endif
18119 return Fits<OpcodeID, size>::check(opcodeID)
18120 && Fits<VirtualRegister, size>::check(dst)
18121 && Fits<VirtualRegister, size>::check(constructor)
18122 && Fits<VirtualRegister, size>::check(hasInstanceValue)
18123 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
18124 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
18125 }
18126
18127 template<OpcodeSize size, bool recordOpcode>
18128 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18129 {
18130 if (size == OpcodeSize::Wide16)
18131 gen->alignWideOpcode16();
18132 else if (size == OpcodeSize::Wide32)
18133 gen->alignWideOpcode32();
18134 if (checkImpl<size>(gen, dst, constructor, hasInstanceValue)) {
18135 if (recordOpcode)
18136 gen->recordOpcode(opcodeID);
18137 if (size == OpcodeSize::Wide16)
18138 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
18139 else if (size == OpcodeSize::Wide32)
18140 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
18141 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
18142 gen->write(Fits<VirtualRegister, size>::convert(dst));
18143 gen->write(Fits<VirtualRegister, size>::convert(constructor));
18144 gen->write(Fits<VirtualRegister, size>::convert(hasInstanceValue));
18145 return true;
18146 }
18147 return false;
18148 }
18149
18150public:
18151 template<typename Block>
18152 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
18153 {
18154 dumper->printLocationAndOp(__location, &"**overrides_has_instance"[2 - __sizeShiftAmount]);
18155 dumper->dumpOperand(m_dst, true);
18156 dumper->dumpOperand(m_constructor, false);
18157 dumper->dumpOperand(m_hasInstanceValue, false);
18158 }
18159
18160 OpOverridesHasInstance(const uint8_t* stream)
18161 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
18162 , m_constructor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
18163 , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
18164 {
18165 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18166 }
18167
18168 OpOverridesHasInstance(const uint16_t* stream)
18169 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
18170 , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
18171 , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
18172 {
18173 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18174 }
18175
18176
18177 OpOverridesHasInstance(const uint32_t* stream)
18178 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
18179 , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
18180 , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
18181 {
18182 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18183 }
18184
18185 static OpOverridesHasInstance decode(const uint8_t* stream)
18186 {
18187 if (*stream == op_wide32)
18188 return { bitwise_cast<const uint32_t*>(stream + 1) };
18189 if (*stream == op_wide16)
18190 return { bitwise_cast<const uint16_t*>(stream + 1) };
18191 return { stream };
18192 }
18193
18194 template<typename Functor>
18195 void setDst(VirtualRegister value, Functor func)
18196 {
18197 if (isWide32())
18198 setDst<OpcodeSize::Wide32>(value, func);
18199 else if (isWide16())
18200 setDst<OpcodeSize::Wide16>(value, func);
18201 else
18202 setDst<OpcodeSize::Narrow>(value, func);
18203 }
18204
18205 template <OpcodeSize size, typename Functor>
18206 void setDst(VirtualRegister value, Functor func)
18207 {
18208 if (!Fits<VirtualRegister, size>::check(value))
18209 value = func();
18210 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
18211 *stream = Fits<VirtualRegister, size>::convert(value);
18212 }
18213
18214 template<typename Functor>
18215 void setConstructor(VirtualRegister value, Functor func)
18216 {
18217 if (isWide32())
18218 setConstructor<OpcodeSize::Wide32>(value, func);
18219 else if (isWide16())
18220 setConstructor<OpcodeSize::Wide16>(value, func);
18221 else
18222 setConstructor<OpcodeSize::Narrow>(value, func);
18223 }
18224
18225 template <OpcodeSize size, typename Functor>
18226 void setConstructor(VirtualRegister value, Functor func)
18227 {
18228 if (!Fits<VirtualRegister, size>::check(value))
18229 value = func();
18230 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
18231 *stream = Fits<VirtualRegister, size>::convert(value);
18232 }
18233
18234 template<typename Functor>
18235 void setHasInstanceValue(VirtualRegister value, Functor func)
18236 {
18237 if (isWide32())
18238 setHasInstanceValue<OpcodeSize::Wide32>(value, func);
18239 else if (isWide16())
18240 setHasInstanceValue<OpcodeSize::Wide16>(value, func);
18241 else
18242 setHasInstanceValue<OpcodeSize::Narrow>(value, func);
18243 }
18244
18245 template <OpcodeSize size, typename Functor>
18246 void setHasInstanceValue(VirtualRegister value, Functor func)
18247 {
18248 if (!Fits<VirtualRegister, size>::check(value))
18249 value = func();
18250 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
18251 *stream = Fits<VirtualRegister, size>::convert(value);
18252 }
18253
18254 VirtualRegister m_dst;
18255 VirtualRegister m_constructor;
18256 VirtualRegister m_hasInstanceValue;
18257};
18258
18259struct OpInstanceof : public Instruction {
18260 static constexpr OpcodeID opcodeID = op_instanceof;
18261
18262 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
18263 {
18264 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, value, prototype);
18265 }
18266
18267 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
18268 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
18269 {
18270 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, value, prototype);
18271 if (shouldAssert == Assert)
18272 ASSERT(didEmit);
18273 return didEmit;
18274 }
18275
18276 template<OpcodeSize size>
18277 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
18278 {
18279
18280 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
18281 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, value, prototype))
18282 return;
18283 }
18284 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
18285 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, value, prototype))
18286 return;
18287 }
18288 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, value, prototype);
18289 }
18290
18291private:
18292 template<OpcodeSize size>
18293 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& value, VirtualRegister& prototype)
18294 {
18295 UNUSED_PARAM(gen);
18296#if OS(WINDOWS) && ENABLE(C_LOOP)
18297 // FIXME: Disable wide16 optimization for Windows CLoop
18298 // https://bugs.webkit.org/show_bug.cgi?id=198283
18299 if (size == OpcodeSize::Wide16)
18300 return false;
18301#endif
18302 return Fits<OpcodeID, size>::check(opcodeID)
18303 && Fits<VirtualRegister, size>::check(dst)
18304 && Fits<VirtualRegister, size>::check(value)
18305 && Fits<VirtualRegister, size>::check(prototype)
18306 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
18307 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
18308 }
18309
18310 template<OpcodeSize size, bool recordOpcode>
18311 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
18312 {
18313 if (size == OpcodeSize::Wide16)
18314 gen->alignWideOpcode16();
18315 else if (size == OpcodeSize::Wide32)
18316 gen->alignWideOpcode32();
18317 if (checkImpl<size>(gen, dst, value, prototype)) {
18318 if (recordOpcode)
18319 gen->recordOpcode(opcodeID);
18320 if (size == OpcodeSize::Wide16)
18321 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
18322 else if (size == OpcodeSize::Wide32)
18323 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
18324 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
18325 gen->write(Fits<VirtualRegister, size>::convert(dst));
18326 gen->write(Fits<VirtualRegister, size>::convert(value));
18327 gen->write(Fits<VirtualRegister, size>::convert(prototype));
18328 return true;
18329 }
18330 return false;
18331 }
18332
18333public:
18334 template<typename Block>
18335 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
18336 {
18337 dumper->printLocationAndOp(__location, &"**instanceof"[2 - __sizeShiftAmount]);
18338 dumper->dumpOperand(m_dst, true);
18339 dumper->dumpOperand(m_value, false);
18340 dumper->dumpOperand(m_prototype, false);
18341 }
18342
18343 OpInstanceof(const uint8_t* stream)
18344 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
18345 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
18346 , m_prototype(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
18347 {
18348 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18349 }
18350
18351 OpInstanceof(const uint16_t* stream)
18352 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
18353 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
18354 , m_prototype(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
18355 {
18356 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18357 }
18358
18359
18360 OpInstanceof(const uint32_t* stream)
18361 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
18362 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
18363 , m_prototype(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
18364 {
18365 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18366 }
18367
18368 static OpInstanceof decode(const uint8_t* stream)
18369 {
18370 if (*stream == op_wide32)
18371 return { bitwise_cast<const uint32_t*>(stream + 1) };
18372 if (*stream == op_wide16)
18373 return { bitwise_cast<const uint16_t*>(stream + 1) };
18374 return { stream };
18375 }
18376
18377 template<typename Functor>
18378 void setDst(VirtualRegister value, Functor func)
18379 {
18380 if (isWide32())
18381 setDst<OpcodeSize::Wide32>(value, func);
18382 else if (isWide16())
18383 setDst<OpcodeSize::Wide16>(value, func);
18384 else
18385 setDst<OpcodeSize::Narrow>(value, func);
18386 }
18387
18388 template <OpcodeSize size, typename Functor>
18389 void setDst(VirtualRegister value, Functor func)
18390 {
18391 if (!Fits<VirtualRegister, size>::check(value))
18392 value = func();
18393 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
18394 *stream = Fits<VirtualRegister, size>::convert(value);
18395 }
18396
18397 template<typename Functor>
18398 void setValue(VirtualRegister value, Functor func)
18399 {
18400 if (isWide32())
18401 setValue<OpcodeSize::Wide32>(value, func);
18402 else if (isWide16())
18403 setValue<OpcodeSize::Wide16>(value, func);
18404 else
18405 setValue<OpcodeSize::Narrow>(value, func);
18406 }
18407
18408 template <OpcodeSize size, typename Functor>
18409 void setValue(VirtualRegister value, Functor func)
18410 {
18411 if (!Fits<VirtualRegister, size>::check(value))
18412 value = func();
18413 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
18414 *stream = Fits<VirtualRegister, size>::convert(value);
18415 }
18416
18417 template<typename Functor>
18418 void setPrototype(VirtualRegister value, Functor func)
18419 {
18420 if (isWide32())
18421 setPrototype<OpcodeSize::Wide32>(value, func);
18422 else if (isWide16())
18423 setPrototype<OpcodeSize::Wide16>(value, func);
18424 else
18425 setPrototype<OpcodeSize::Narrow>(value, func);
18426 }
18427
18428 template <OpcodeSize size, typename Functor>
18429 void setPrototype(VirtualRegister value, Functor func)
18430 {
18431 if (!Fits<VirtualRegister, size>::check(value))
18432 value = func();
18433 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
18434 *stream = Fits<VirtualRegister, size>::convert(value);
18435 }
18436
18437 VirtualRegister m_dst;
18438 VirtualRegister m_value;
18439 VirtualRegister m_prototype;
18440};
18441
18442struct OpInstanceofCustom : public Instruction {
18443 static constexpr OpcodeID opcodeID = op_instanceof_custom;
18444
18445 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18446 {
18447 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, value, constructor, hasInstanceValue);
18448 }
18449
18450 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
18451 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18452 {
18453 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, value, constructor, hasInstanceValue);
18454 if (shouldAssert == Assert)
18455 ASSERT(didEmit);
18456 return didEmit;
18457 }
18458
18459 template<OpcodeSize size>
18460 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18461 {
18462
18463 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
18464 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, value, constructor, hasInstanceValue))
18465 return;
18466 }
18467 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
18468 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, value, constructor, hasInstanceValue))
18469 return;
18470 }
18471 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, value, constructor, hasInstanceValue);
18472 }
18473
18474private:
18475 template<OpcodeSize size>
18476 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& value, VirtualRegister& constructor, VirtualRegister& hasInstanceValue)
18477 {
18478 UNUSED_PARAM(gen);
18479#if OS(WINDOWS) && ENABLE(C_LOOP)
18480 // FIXME: Disable wide16 optimization for Windows CLoop
18481 // https://bugs.webkit.org/show_bug.cgi?id=198283
18482 if (size == OpcodeSize::Wide16)
18483 return false;
18484#endif
18485 return Fits<OpcodeID, size>::check(opcodeID)
18486 && Fits<VirtualRegister, size>::check(dst)
18487 && Fits<VirtualRegister, size>::check(value)
18488 && Fits<VirtualRegister, size>::check(constructor)
18489 && Fits<VirtualRegister, size>::check(hasInstanceValue)
18490 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
18491 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
18492 }
18493
18494 template<OpcodeSize size, bool recordOpcode>
18495 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
18496 {
18497 if (size == OpcodeSize::Wide16)
18498 gen->alignWideOpcode16();
18499 else if (size == OpcodeSize::Wide32)
18500 gen->alignWideOpcode32();
18501 if (checkImpl<size>(gen, dst, value, constructor, hasInstanceValue)) {
18502 if (recordOpcode)
18503 gen->recordOpcode(opcodeID);
18504 if (size == OpcodeSize::Wide16)
18505 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
18506 else if (size == OpcodeSize::Wide32)
18507 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
18508 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
18509 gen->write(Fits<VirtualRegister, size>::convert(dst));
18510 gen->write(Fits<VirtualRegister, size>::convert(value));
18511 gen->write(Fits<VirtualRegister, size>::convert(constructor));
18512 gen->write(Fits<VirtualRegister, size>::convert(hasInstanceValue));
18513 return true;
18514 }
18515 return false;
18516 }
18517
18518public:
18519 template<typename Block>
18520 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
18521 {
18522 dumper->printLocationAndOp(__location, &"**instanceof_custom"[2 - __sizeShiftAmount]);
18523 dumper->dumpOperand(m_dst, true);
18524 dumper->dumpOperand(m_value, false);
18525 dumper->dumpOperand(m_constructor, false);
18526 dumper->dumpOperand(m_hasInstanceValue, false);
18527 }
18528
18529 OpInstanceofCustom(const uint8_t* stream)
18530 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
18531 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
18532 , m_constructor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
18533 , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
18534 {
18535 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18536 }
18537
18538 OpInstanceofCustom(const uint16_t* stream)
18539 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
18540 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
18541 , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
18542 , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
18543 {
18544 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18545 }
18546
18547
18548 OpInstanceofCustom(const uint32_t* stream)
18549 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
18550 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
18551 , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
18552 , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
18553 {
18554 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18555 }
18556
18557 static OpInstanceofCustom decode(const uint8_t* stream)
18558 {
18559 if (*stream == op_wide32)
18560 return { bitwise_cast<const uint32_t*>(stream + 1) };
18561 if (*stream == op_wide16)
18562 return { bitwise_cast<const uint16_t*>(stream + 1) };
18563 return { stream };
18564 }
18565
18566 template<typename Functor>
18567 void setDst(VirtualRegister value, Functor func)
18568 {
18569 if (isWide32())
18570 setDst<OpcodeSize::Wide32>(value, func);
18571 else if (isWide16())
18572 setDst<OpcodeSize::Wide16>(value, func);
18573 else
18574 setDst<OpcodeSize::Narrow>(value, func);
18575 }
18576
18577 template <OpcodeSize size, typename Functor>
18578 void setDst(VirtualRegister value, Functor func)
18579 {
18580 if (!Fits<VirtualRegister, size>::check(value))
18581 value = func();
18582 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
18583 *stream = Fits<VirtualRegister, size>::convert(value);
18584 }
18585
18586 template<typename Functor>
18587 void setValue(VirtualRegister value, Functor func)
18588 {
18589 if (isWide32())
18590 setValue<OpcodeSize::Wide32>(value, func);
18591 else if (isWide16())
18592 setValue<OpcodeSize::Wide16>(value, func);
18593 else
18594 setValue<OpcodeSize::Narrow>(value, func);
18595 }
18596
18597 template <OpcodeSize size, typename Functor>
18598 void setValue(VirtualRegister value, Functor func)
18599 {
18600 if (!Fits<VirtualRegister, size>::check(value))
18601 value = func();
18602 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
18603 *stream = Fits<VirtualRegister, size>::convert(value);
18604 }
18605
18606 template<typename Functor>
18607 void setConstructor(VirtualRegister value, Functor func)
18608 {
18609 if (isWide32())
18610 setConstructor<OpcodeSize::Wide32>(value, func);
18611 else if (isWide16())
18612 setConstructor<OpcodeSize::Wide16>(value, func);
18613 else
18614 setConstructor<OpcodeSize::Narrow>(value, func);
18615 }
18616
18617 template <OpcodeSize size, typename Functor>
18618 void setConstructor(VirtualRegister value, Functor func)
18619 {
18620 if (!Fits<VirtualRegister, size>::check(value))
18621 value = func();
18622 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
18623 *stream = Fits<VirtualRegister, size>::convert(value);
18624 }
18625
18626 template<typename Functor>
18627 void setHasInstanceValue(VirtualRegister value, Functor func)
18628 {
18629 if (isWide32())
18630 setHasInstanceValue<OpcodeSize::Wide32>(value, func);
18631 else if (isWide16())
18632 setHasInstanceValue<OpcodeSize::Wide16>(value, func);
18633 else
18634 setHasInstanceValue<OpcodeSize::Narrow>(value, func);
18635 }
18636
18637 template <OpcodeSize size, typename Functor>
18638 void setHasInstanceValue(VirtualRegister value, Functor func)
18639 {
18640 if (!Fits<VirtualRegister, size>::check(value))
18641 value = func();
18642 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
18643 *stream = Fits<VirtualRegister, size>::convert(value);
18644 }
18645
18646 VirtualRegister m_dst;
18647 VirtualRegister m_value;
18648 VirtualRegister m_constructor;
18649 VirtualRegister m_hasInstanceValue;
18650};
18651
18652struct OpTypeof : public Instruction {
18653 static constexpr OpcodeID opcodeID = op_typeof;
18654
18655 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
18656 {
18657 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, value);
18658 }
18659
18660 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
18661 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
18662 {
18663 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, value);
18664 if (shouldAssert == Assert)
18665 ASSERT(didEmit);
18666 return didEmit;
18667 }
18668
18669 template<OpcodeSize size>
18670 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
18671 {
18672
18673 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
18674 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, value))
18675 return;
18676 }
18677 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
18678 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, value))
18679 return;
18680 }
18681 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, value);
18682 }
18683
18684private:
18685 template<OpcodeSize size>
18686 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& value)
18687 {
18688 UNUSED_PARAM(gen);
18689#if OS(WINDOWS) && ENABLE(C_LOOP)
18690 // FIXME: Disable wide16 optimization for Windows CLoop
18691 // https://bugs.webkit.org/show_bug.cgi?id=198283
18692 if (size == OpcodeSize::Wide16)
18693 return false;
18694#endif
18695 return Fits<OpcodeID, size>::check(opcodeID)
18696 && Fits<VirtualRegister, size>::check(dst)
18697 && Fits<VirtualRegister, size>::check(value)
18698 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
18699 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
18700 }
18701
18702 template<OpcodeSize size, bool recordOpcode>
18703 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
18704 {
18705 if (size == OpcodeSize::Wide16)
18706 gen->alignWideOpcode16();
18707 else if (size == OpcodeSize::Wide32)
18708 gen->alignWideOpcode32();
18709 if (checkImpl<size>(gen, dst, value)) {
18710 if (recordOpcode)
18711 gen->recordOpcode(opcodeID);
18712 if (size == OpcodeSize::Wide16)
18713 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
18714 else if (size == OpcodeSize::Wide32)
18715 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
18716 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
18717 gen->write(Fits<VirtualRegister, size>::convert(dst));
18718 gen->write(Fits<VirtualRegister, size>::convert(value));
18719 return true;
18720 }
18721 return false;
18722 }
18723
18724public:
18725 template<typename Block>
18726 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
18727 {
18728 dumper->printLocationAndOp(__location, &"**typeof"[2 - __sizeShiftAmount]);
18729 dumper->dumpOperand(m_dst, true);
18730 dumper->dumpOperand(m_value, false);
18731 }
18732
18733 OpTypeof(const uint8_t* stream)
18734 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
18735 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
18736 {
18737 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18738 }
18739
18740 OpTypeof(const uint16_t* stream)
18741 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
18742 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
18743 {
18744 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18745 }
18746
18747
18748 OpTypeof(const uint32_t* stream)
18749 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
18750 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
18751 {
18752 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18753 }
18754
18755 static OpTypeof decode(const uint8_t* stream)
18756 {
18757 if (*stream == op_wide32)
18758 return { bitwise_cast<const uint32_t*>(stream + 1) };
18759 if (*stream == op_wide16)
18760 return { bitwise_cast<const uint16_t*>(stream + 1) };
18761 return { stream };
18762 }
18763
18764 template<typename Functor>
18765 void setDst(VirtualRegister value, Functor func)
18766 {
18767 if (isWide32())
18768 setDst<OpcodeSize::Wide32>(value, func);
18769 else if (isWide16())
18770 setDst<OpcodeSize::Wide16>(value, func);
18771 else
18772 setDst<OpcodeSize::Narrow>(value, func);
18773 }
18774
18775 template <OpcodeSize size, typename Functor>
18776 void setDst(VirtualRegister value, Functor func)
18777 {
18778 if (!Fits<VirtualRegister, size>::check(value))
18779 value = func();
18780 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
18781 *stream = Fits<VirtualRegister, size>::convert(value);
18782 }
18783
18784 template<typename Functor>
18785 void setValue(VirtualRegister value, Functor func)
18786 {
18787 if (isWide32())
18788 setValue<OpcodeSize::Wide32>(value, func);
18789 else if (isWide16())
18790 setValue<OpcodeSize::Wide16>(value, func);
18791 else
18792 setValue<OpcodeSize::Narrow>(value, func);
18793 }
18794
18795 template <OpcodeSize size, typename Functor>
18796 void setValue(VirtualRegister value, Functor func)
18797 {
18798 if (!Fits<VirtualRegister, size>::check(value))
18799 value = func();
18800 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
18801 *stream = Fits<VirtualRegister, size>::convert(value);
18802 }
18803
18804 VirtualRegister m_dst;
18805 VirtualRegister m_value;
18806};
18807
18808struct OpIsCellWithType : public Instruction {
18809 static constexpr OpcodeID opcodeID = op_is_cell_with_type;
18810
18811 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
18812 {
18813 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand, type);
18814 }
18815
18816 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
18817 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
18818 {
18819 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, type);
18820 if (shouldAssert == Assert)
18821 ASSERT(didEmit);
18822 return didEmit;
18823 }
18824
18825 template<OpcodeSize size>
18826 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
18827 {
18828
18829 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
18830 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand, type))
18831 return;
18832 }
18833 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
18834 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, type))
18835 return;
18836 }
18837 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, type);
18838 }
18839
18840private:
18841 template<OpcodeSize size>
18842 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, JSType& type)
18843 {
18844 UNUSED_PARAM(gen);
18845#if OS(WINDOWS) && ENABLE(C_LOOP)
18846 // FIXME: Disable wide16 optimization for Windows CLoop
18847 // https://bugs.webkit.org/show_bug.cgi?id=198283
18848 if (size == OpcodeSize::Wide16)
18849 return false;
18850#endif
18851 return Fits<OpcodeID, size>::check(opcodeID)
18852 && Fits<VirtualRegister, size>::check(dst)
18853 && Fits<VirtualRegister, size>::check(operand)
18854 && Fits<JSType, size>::check(type)
18855 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
18856 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
18857 }
18858
18859 template<OpcodeSize size, bool recordOpcode>
18860 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
18861 {
18862 if (size == OpcodeSize::Wide16)
18863 gen->alignWideOpcode16();
18864 else if (size == OpcodeSize::Wide32)
18865 gen->alignWideOpcode32();
18866 if (checkImpl<size>(gen, dst, operand, type)) {
18867 if (recordOpcode)
18868 gen->recordOpcode(opcodeID);
18869 if (size == OpcodeSize::Wide16)
18870 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
18871 else if (size == OpcodeSize::Wide32)
18872 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
18873 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
18874 gen->write(Fits<VirtualRegister, size>::convert(dst));
18875 gen->write(Fits<VirtualRegister, size>::convert(operand));
18876 gen->write(Fits<JSType, size>::convert(type));
18877 return true;
18878 }
18879 return false;
18880 }
18881
18882public:
18883 template<typename Block>
18884 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
18885 {
18886 dumper->printLocationAndOp(__location, &"**is_cell_with_type"[2 - __sizeShiftAmount]);
18887 dumper->dumpOperand(m_dst, true);
18888 dumper->dumpOperand(m_operand, false);
18889 dumper->dumpOperand(m_type, false);
18890 }
18891
18892 OpIsCellWithType(const uint8_t* stream)
18893 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
18894 , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
18895 , m_type(Fits<JSType, OpcodeSize::Narrow>::convert(stream[3]))
18896 {
18897 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18898 }
18899
18900 OpIsCellWithType(const uint16_t* stream)
18901 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
18902 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
18903 , m_type(Fits<JSType, OpcodeSize::Wide16>::convert(stream[3]))
18904 {
18905 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18906 }
18907
18908
18909 OpIsCellWithType(const uint32_t* stream)
18910 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
18911 , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
18912 , m_type(Fits<JSType, OpcodeSize::Wide32>::convert(stream[3]))
18913 {
18914 ASSERT_UNUSED(stream, stream[0] == opcodeID);
18915 }
18916
18917 static OpIsCellWithType decode(const uint8_t* stream)
18918 {
18919 if (*stream == op_wide32)
18920 return { bitwise_cast<const uint32_t*>(stream + 1) };
18921 if (*stream == op_wide16)
18922 return { bitwise_cast<const uint16_t*>(stream + 1) };
18923 return { stream };
18924 }
18925
18926 template<typename Functor>
18927 void setDst(VirtualRegister value, Functor func)
18928 {
18929 if (isWide32())
18930 setDst<OpcodeSize::Wide32>(value, func);
18931 else if (isWide16())
18932 setDst<OpcodeSize::Wide16>(value, func);
18933 else
18934 setDst<OpcodeSize::Narrow>(value, func);
18935 }
18936
18937 template <OpcodeSize size, typename Functor>
18938 void setDst(VirtualRegister value, Functor func)
18939 {
18940 if (!Fits<VirtualRegister, size>::check(value))
18941 value = func();
18942 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
18943 *stream = Fits<VirtualRegister, size>::convert(value);
18944 }
18945
18946 template<typename Functor>
18947 void setOperand(VirtualRegister value, Functor func)
18948 {
18949 if (isWide32())
18950 setOperand<OpcodeSize::Wide32>(value, func);
18951 else if (isWide16())
18952 setOperand<OpcodeSize::Wide16>(value, func);
18953 else
18954 setOperand<OpcodeSize::Narrow>(value, func);
18955 }
18956
18957 template <OpcodeSize size, typename Functor>
18958 void setOperand(VirtualRegister value, Functor func)
18959 {
18960 if (!Fits<VirtualRegister, size>::check(value))
18961 value = func();
18962 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
18963 *stream = Fits<VirtualRegister, size>::convert(value);
18964 }
18965
18966 template<typename Functor>
18967 void setType(JSType value, Functor func)
18968 {
18969 if (isWide32())
18970 setType<OpcodeSize::Wide32>(value, func);
18971 else if (isWide16())
18972 setType<OpcodeSize::Wide16>(value, func);
18973 else
18974 setType<OpcodeSize::Narrow>(value, func);
18975 }
18976
18977 template <OpcodeSize size, typename Functor>
18978 void setType(JSType value, Functor func)
18979 {
18980 if (!Fits<JSType, size>::check(value))
18981 value = func();
18982 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
18983 *stream = Fits<JSType, size>::convert(value);
18984 }
18985
18986 VirtualRegister m_dst;
18987 VirtualRegister m_operand;
18988 JSType m_type;
18989};
18990
18991struct OpInById : public Instruction {
18992 static constexpr OpcodeID opcodeID = op_in_by_id;
18993
18994 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
18995 {
18996 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
18997 }
18998
18999 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
19000 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
19001 {
19002 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property);
19003 if (shouldAssert == Assert)
19004 ASSERT(didEmit);
19005 return didEmit;
19006 }
19007
19008 template<OpcodeSize size>
19009 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
19010 {
19011
19012 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
19013 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property))
19014 return;
19015 }
19016 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
19017 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
19018 return;
19019 }
19020 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
19021 }
19022
19023private:
19024 template<OpcodeSize size>
19025 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property)
19026 {
19027 UNUSED_PARAM(gen);
19028#if OS(WINDOWS) && ENABLE(C_LOOP)
19029 // FIXME: Disable wide16 optimization for Windows CLoop
19030 // https://bugs.webkit.org/show_bug.cgi?id=198283
19031 if (size == OpcodeSize::Wide16)
19032 return false;
19033#endif
19034 return Fits<OpcodeID, size>::check(opcodeID)
19035 && Fits<VirtualRegister, size>::check(dst)
19036 && Fits<VirtualRegister, size>::check(base)
19037 && Fits<unsigned, size>::check(property)
19038 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
19039 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
19040 }
19041
19042 template<OpcodeSize size, bool recordOpcode>
19043 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
19044 {
19045 if (size == OpcodeSize::Wide16)
19046 gen->alignWideOpcode16();
19047 else if (size == OpcodeSize::Wide32)
19048 gen->alignWideOpcode32();
19049 if (checkImpl<size>(gen, dst, base, property)) {
19050 if (recordOpcode)
19051 gen->recordOpcode(opcodeID);
19052 if (size == OpcodeSize::Wide16)
19053 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
19054 else if (size == OpcodeSize::Wide32)
19055 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
19056 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
19057 gen->write(Fits<VirtualRegister, size>::convert(dst));
19058 gen->write(Fits<VirtualRegister, size>::convert(base));
19059 gen->write(Fits<unsigned, size>::convert(property));
19060 return true;
19061 }
19062 return false;
19063 }
19064
19065public:
19066 template<typename Block>
19067 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
19068 {
19069 dumper->printLocationAndOp(__location, &"**in_by_id"[2 - __sizeShiftAmount]);
19070 dumper->dumpOperand(m_dst, true);
19071 dumper->dumpOperand(m_base, false);
19072 dumper->dumpOperand(m_property, false);
19073 }
19074
19075 OpInById(const uint8_t* stream)
19076 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
19077 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
19078 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
19079 {
19080 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19081 }
19082
19083 OpInById(const uint16_t* stream)
19084 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
19085 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
19086 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
19087 {
19088 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19089 }
19090
19091
19092 OpInById(const uint32_t* stream)
19093 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
19094 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
19095 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
19096 {
19097 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19098 }
19099
19100 static OpInById decode(const uint8_t* stream)
19101 {
19102 if (*stream == op_wide32)
19103 return { bitwise_cast<const uint32_t*>(stream + 1) };
19104 if (*stream == op_wide16)
19105 return { bitwise_cast<const uint16_t*>(stream + 1) };
19106 return { stream };
19107 }
19108
19109 template<typename Functor>
19110 void setDst(VirtualRegister value, Functor func)
19111 {
19112 if (isWide32())
19113 setDst<OpcodeSize::Wide32>(value, func);
19114 else if (isWide16())
19115 setDst<OpcodeSize::Wide16>(value, func);
19116 else
19117 setDst<OpcodeSize::Narrow>(value, func);
19118 }
19119
19120 template <OpcodeSize size, typename Functor>
19121 void setDst(VirtualRegister value, Functor func)
19122 {
19123 if (!Fits<VirtualRegister, size>::check(value))
19124 value = func();
19125 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
19126 *stream = Fits<VirtualRegister, size>::convert(value);
19127 }
19128
19129 template<typename Functor>
19130 void setBase(VirtualRegister value, Functor func)
19131 {
19132 if (isWide32())
19133 setBase<OpcodeSize::Wide32>(value, func);
19134 else if (isWide16())
19135 setBase<OpcodeSize::Wide16>(value, func);
19136 else
19137 setBase<OpcodeSize::Narrow>(value, func);
19138 }
19139
19140 template <OpcodeSize size, typename Functor>
19141 void setBase(VirtualRegister value, Functor func)
19142 {
19143 if (!Fits<VirtualRegister, size>::check(value))
19144 value = func();
19145 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
19146 *stream = Fits<VirtualRegister, size>::convert(value);
19147 }
19148
19149 template<typename Functor>
19150 void setProperty(unsigned value, Functor func)
19151 {
19152 if (isWide32())
19153 setProperty<OpcodeSize::Wide32>(value, func);
19154 else if (isWide16())
19155 setProperty<OpcodeSize::Wide16>(value, func);
19156 else
19157 setProperty<OpcodeSize::Narrow>(value, func);
19158 }
19159
19160 template <OpcodeSize size, typename Functor>
19161 void setProperty(unsigned value, Functor func)
19162 {
19163 if (!Fits<unsigned, size>::check(value))
19164 value = func();
19165 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
19166 *stream = Fits<unsigned, size>::convert(value);
19167 }
19168
19169 VirtualRegister m_dst;
19170 VirtualRegister m_base;
19171 unsigned m_property;
19172};
19173
19174struct OpPutByIdWithThis : public Instruction {
19175 static constexpr OpcodeID opcodeID = op_put_by_id_with_this;
19176
19177 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value)
19178 {
19179 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, thisValue, property, value);
19180 }
19181
19182 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
19183 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value)
19184 {
19185 bool didEmit = emitImpl<size, recordOpcode>(gen, base, thisValue, property, value);
19186 if (shouldAssert == Assert)
19187 ASSERT(didEmit);
19188 return didEmit;
19189 }
19190
19191 template<OpcodeSize size>
19192 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value)
19193 {
19194
19195 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
19196 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, thisValue, property, value))
19197 return;
19198 }
19199 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
19200 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, thisValue, property, value))
19201 return;
19202 }
19203 emit<OpcodeSize::Wide32, Assert, true>(gen, base, thisValue, property, value);
19204 }
19205
19206private:
19207 template<OpcodeSize size>
19208 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& thisValue, unsigned& property, VirtualRegister& value)
19209 {
19210 UNUSED_PARAM(gen);
19211#if OS(WINDOWS) && ENABLE(C_LOOP)
19212 // FIXME: Disable wide16 optimization for Windows CLoop
19213 // https://bugs.webkit.org/show_bug.cgi?id=198283
19214 if (size == OpcodeSize::Wide16)
19215 return false;
19216#endif
19217 return Fits<OpcodeID, size>::check(opcodeID)
19218 && Fits<VirtualRegister, size>::check(base)
19219 && Fits<VirtualRegister, size>::check(thisValue)
19220 && Fits<unsigned, size>::check(property)
19221 && Fits<VirtualRegister, size>::check(value)
19222 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
19223 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
19224 }
19225
19226 template<OpcodeSize size, bool recordOpcode>
19227 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value)
19228 {
19229 if (size == OpcodeSize::Wide16)
19230 gen->alignWideOpcode16();
19231 else if (size == OpcodeSize::Wide32)
19232 gen->alignWideOpcode32();
19233 if (checkImpl<size>(gen, base, thisValue, property, value)) {
19234 if (recordOpcode)
19235 gen->recordOpcode(opcodeID);
19236 if (size == OpcodeSize::Wide16)
19237 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
19238 else if (size == OpcodeSize::Wide32)
19239 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
19240 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
19241 gen->write(Fits<VirtualRegister, size>::convert(base));
19242 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
19243 gen->write(Fits<unsigned, size>::convert(property));
19244 gen->write(Fits<VirtualRegister, size>::convert(value));
19245 return true;
19246 }
19247 return false;
19248 }
19249
19250public:
19251 template<typename Block>
19252 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
19253 {
19254 dumper->printLocationAndOp(__location, &"**put_by_id_with_this"[2 - __sizeShiftAmount]);
19255 dumper->dumpOperand(m_base, true);
19256 dumper->dumpOperand(m_thisValue, false);
19257 dumper->dumpOperand(m_property, false);
19258 dumper->dumpOperand(m_value, false);
19259 }
19260
19261 OpPutByIdWithThis(const uint8_t* stream)
19262 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
19263 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
19264 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
19265 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
19266 {
19267 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19268 }
19269
19270 OpPutByIdWithThis(const uint16_t* stream)
19271 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
19272 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
19273 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
19274 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
19275 {
19276 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19277 }
19278
19279
19280 OpPutByIdWithThis(const uint32_t* stream)
19281 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
19282 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
19283 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
19284 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
19285 {
19286 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19287 }
19288
19289 static OpPutByIdWithThis decode(const uint8_t* stream)
19290 {
19291 if (*stream == op_wide32)
19292 return { bitwise_cast<const uint32_t*>(stream + 1) };
19293 if (*stream == op_wide16)
19294 return { bitwise_cast<const uint16_t*>(stream + 1) };
19295 return { stream };
19296 }
19297
19298 template<typename Functor>
19299 void setBase(VirtualRegister value, Functor func)
19300 {
19301 if (isWide32())
19302 setBase<OpcodeSize::Wide32>(value, func);
19303 else if (isWide16())
19304 setBase<OpcodeSize::Wide16>(value, func);
19305 else
19306 setBase<OpcodeSize::Narrow>(value, func);
19307 }
19308
19309 template <OpcodeSize size, typename Functor>
19310 void setBase(VirtualRegister value, Functor func)
19311 {
19312 if (!Fits<VirtualRegister, size>::check(value))
19313 value = func();
19314 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
19315 *stream = Fits<VirtualRegister, size>::convert(value);
19316 }
19317
19318 template<typename Functor>
19319 void setThisValue(VirtualRegister value, Functor func)
19320 {
19321 if (isWide32())
19322 setThisValue<OpcodeSize::Wide32>(value, func);
19323 else if (isWide16())
19324 setThisValue<OpcodeSize::Wide16>(value, func);
19325 else
19326 setThisValue<OpcodeSize::Narrow>(value, func);
19327 }
19328
19329 template <OpcodeSize size, typename Functor>
19330 void setThisValue(VirtualRegister value, Functor func)
19331 {
19332 if (!Fits<VirtualRegister, size>::check(value))
19333 value = func();
19334 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
19335 *stream = Fits<VirtualRegister, size>::convert(value);
19336 }
19337
19338 template<typename Functor>
19339 void setProperty(unsigned value, Functor func)
19340 {
19341 if (isWide32())
19342 setProperty<OpcodeSize::Wide32>(value, func);
19343 else if (isWide16())
19344 setProperty<OpcodeSize::Wide16>(value, func);
19345 else
19346 setProperty<OpcodeSize::Narrow>(value, func);
19347 }
19348
19349 template <OpcodeSize size, typename Functor>
19350 void setProperty(unsigned value, Functor func)
19351 {
19352 if (!Fits<unsigned, size>::check(value))
19353 value = func();
19354 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
19355 *stream = Fits<unsigned, size>::convert(value);
19356 }
19357
19358 template<typename Functor>
19359 void setValue(VirtualRegister value, Functor func)
19360 {
19361 if (isWide32())
19362 setValue<OpcodeSize::Wide32>(value, func);
19363 else if (isWide16())
19364 setValue<OpcodeSize::Wide16>(value, func);
19365 else
19366 setValue<OpcodeSize::Narrow>(value, func);
19367 }
19368
19369 template <OpcodeSize size, typename Functor>
19370 void setValue(VirtualRegister value, Functor func)
19371 {
19372 if (!Fits<VirtualRegister, size>::check(value))
19373 value = func();
19374 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
19375 *stream = Fits<VirtualRegister, size>::convert(value);
19376 }
19377
19378 VirtualRegister m_base;
19379 VirtualRegister m_thisValue;
19380 unsigned m_property;
19381 VirtualRegister m_value;
19382};
19383
19384struct OpDelById : public Instruction {
19385 static constexpr OpcodeID opcodeID = op_del_by_id;
19386
19387 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
19388 {
19389 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
19390 }
19391
19392 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
19393 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
19394 {
19395 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property);
19396 if (shouldAssert == Assert)
19397 ASSERT(didEmit);
19398 return didEmit;
19399 }
19400
19401 template<OpcodeSize size>
19402 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
19403 {
19404
19405 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
19406 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property))
19407 return;
19408 }
19409 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
19410 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
19411 return;
19412 }
19413 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
19414 }
19415
19416private:
19417 template<OpcodeSize size>
19418 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property)
19419 {
19420 UNUSED_PARAM(gen);
19421#if OS(WINDOWS) && ENABLE(C_LOOP)
19422 // FIXME: Disable wide16 optimization for Windows CLoop
19423 // https://bugs.webkit.org/show_bug.cgi?id=198283
19424 if (size == OpcodeSize::Wide16)
19425 return false;
19426#endif
19427 return Fits<OpcodeID, size>::check(opcodeID)
19428 && Fits<VirtualRegister, size>::check(dst)
19429 && Fits<VirtualRegister, size>::check(base)
19430 && Fits<unsigned, size>::check(property)
19431 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
19432 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
19433 }
19434
19435 template<OpcodeSize size, bool recordOpcode>
19436 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
19437 {
19438 if (size == OpcodeSize::Wide16)
19439 gen->alignWideOpcode16();
19440 else if (size == OpcodeSize::Wide32)
19441 gen->alignWideOpcode32();
19442 if (checkImpl<size>(gen, dst, base, property)) {
19443 if (recordOpcode)
19444 gen->recordOpcode(opcodeID);
19445 if (size == OpcodeSize::Wide16)
19446 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
19447 else if (size == OpcodeSize::Wide32)
19448 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
19449 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
19450 gen->write(Fits<VirtualRegister, size>::convert(dst));
19451 gen->write(Fits<VirtualRegister, size>::convert(base));
19452 gen->write(Fits<unsigned, size>::convert(property));
19453 return true;
19454 }
19455 return false;
19456 }
19457
19458public:
19459 template<typename Block>
19460 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
19461 {
19462 dumper->printLocationAndOp(__location, &"**del_by_id"[2 - __sizeShiftAmount]);
19463 dumper->dumpOperand(m_dst, true);
19464 dumper->dumpOperand(m_base, false);
19465 dumper->dumpOperand(m_property, false);
19466 }
19467
19468 OpDelById(const uint8_t* stream)
19469 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
19470 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
19471 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
19472 {
19473 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19474 }
19475
19476 OpDelById(const uint16_t* stream)
19477 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
19478 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
19479 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
19480 {
19481 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19482 }
19483
19484
19485 OpDelById(const uint32_t* stream)
19486 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
19487 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
19488 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
19489 {
19490 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19491 }
19492
19493 static OpDelById decode(const uint8_t* stream)
19494 {
19495 if (*stream == op_wide32)
19496 return { bitwise_cast<const uint32_t*>(stream + 1) };
19497 if (*stream == op_wide16)
19498 return { bitwise_cast<const uint16_t*>(stream + 1) };
19499 return { stream };
19500 }
19501
19502 template<typename Functor>
19503 void setDst(VirtualRegister value, Functor func)
19504 {
19505 if (isWide32())
19506 setDst<OpcodeSize::Wide32>(value, func);
19507 else if (isWide16())
19508 setDst<OpcodeSize::Wide16>(value, func);
19509 else
19510 setDst<OpcodeSize::Narrow>(value, func);
19511 }
19512
19513 template <OpcodeSize size, typename Functor>
19514 void setDst(VirtualRegister value, Functor func)
19515 {
19516 if (!Fits<VirtualRegister, size>::check(value))
19517 value = func();
19518 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
19519 *stream = Fits<VirtualRegister, size>::convert(value);
19520 }
19521
19522 template<typename Functor>
19523 void setBase(VirtualRegister value, Functor func)
19524 {
19525 if (isWide32())
19526 setBase<OpcodeSize::Wide32>(value, func);
19527 else if (isWide16())
19528 setBase<OpcodeSize::Wide16>(value, func);
19529 else
19530 setBase<OpcodeSize::Narrow>(value, func);
19531 }
19532
19533 template <OpcodeSize size, typename Functor>
19534 void setBase(VirtualRegister value, Functor func)
19535 {
19536 if (!Fits<VirtualRegister, size>::check(value))
19537 value = func();
19538 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
19539 *stream = Fits<VirtualRegister, size>::convert(value);
19540 }
19541
19542 template<typename Functor>
19543 void setProperty(unsigned value, Functor func)
19544 {
19545 if (isWide32())
19546 setProperty<OpcodeSize::Wide32>(value, func);
19547 else if (isWide16())
19548 setProperty<OpcodeSize::Wide16>(value, func);
19549 else
19550 setProperty<OpcodeSize::Narrow>(value, func);
19551 }
19552
19553 template <OpcodeSize size, typename Functor>
19554 void setProperty(unsigned value, Functor func)
19555 {
19556 if (!Fits<unsigned, size>::check(value))
19557 value = func();
19558 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
19559 *stream = Fits<unsigned, size>::convert(value);
19560 }
19561
19562 VirtualRegister m_dst;
19563 VirtualRegister m_base;
19564 unsigned m_property;
19565};
19566
19567struct OpPutByValWithThis : public Instruction {
19568 static constexpr OpcodeID opcodeID = op_put_by_val_with_this;
19569
19570 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value)
19571 {
19572 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, thisValue, property, value);
19573 }
19574
19575 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
19576 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value)
19577 {
19578 bool didEmit = emitImpl<size, recordOpcode>(gen, base, thisValue, property, value);
19579 if (shouldAssert == Assert)
19580 ASSERT(didEmit);
19581 return didEmit;
19582 }
19583
19584 template<OpcodeSize size>
19585 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value)
19586 {
19587
19588 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
19589 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, thisValue, property, value))
19590 return;
19591 }
19592 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
19593 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, thisValue, property, value))
19594 return;
19595 }
19596 emit<OpcodeSize::Wide32, Assert, true>(gen, base, thisValue, property, value);
19597 }
19598
19599private:
19600 template<OpcodeSize size>
19601 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& thisValue, VirtualRegister& property, VirtualRegister& value)
19602 {
19603 UNUSED_PARAM(gen);
19604#if OS(WINDOWS) && ENABLE(C_LOOP)
19605 // FIXME: Disable wide16 optimization for Windows CLoop
19606 // https://bugs.webkit.org/show_bug.cgi?id=198283
19607 if (size == OpcodeSize::Wide16)
19608 return false;
19609#endif
19610 return Fits<OpcodeID, size>::check(opcodeID)
19611 && Fits<VirtualRegister, size>::check(base)
19612 && Fits<VirtualRegister, size>::check(thisValue)
19613 && Fits<VirtualRegister, size>::check(property)
19614 && Fits<VirtualRegister, size>::check(value)
19615 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
19616 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
19617 }
19618
19619 template<OpcodeSize size, bool recordOpcode>
19620 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value)
19621 {
19622 if (size == OpcodeSize::Wide16)
19623 gen->alignWideOpcode16();
19624 else if (size == OpcodeSize::Wide32)
19625 gen->alignWideOpcode32();
19626 if (checkImpl<size>(gen, base, thisValue, property, value)) {
19627 if (recordOpcode)
19628 gen->recordOpcode(opcodeID);
19629 if (size == OpcodeSize::Wide16)
19630 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
19631 else if (size == OpcodeSize::Wide32)
19632 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
19633 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
19634 gen->write(Fits<VirtualRegister, size>::convert(base));
19635 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
19636 gen->write(Fits<VirtualRegister, size>::convert(property));
19637 gen->write(Fits<VirtualRegister, size>::convert(value));
19638 return true;
19639 }
19640 return false;
19641 }
19642
19643public:
19644 template<typename Block>
19645 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
19646 {
19647 dumper->printLocationAndOp(__location, &"**put_by_val_with_this"[2 - __sizeShiftAmount]);
19648 dumper->dumpOperand(m_base, true);
19649 dumper->dumpOperand(m_thisValue, false);
19650 dumper->dumpOperand(m_property, false);
19651 dumper->dumpOperand(m_value, false);
19652 }
19653
19654 OpPutByValWithThis(const uint8_t* stream)
19655 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
19656 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
19657 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
19658 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
19659 {
19660 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19661 }
19662
19663 OpPutByValWithThis(const uint16_t* stream)
19664 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
19665 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
19666 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
19667 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
19668 {
19669 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19670 }
19671
19672
19673 OpPutByValWithThis(const uint32_t* stream)
19674 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
19675 , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
19676 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
19677 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
19678 {
19679 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19680 }
19681
19682 static OpPutByValWithThis decode(const uint8_t* stream)
19683 {
19684 if (*stream == op_wide32)
19685 return { bitwise_cast<const uint32_t*>(stream + 1) };
19686 if (*stream == op_wide16)
19687 return { bitwise_cast<const uint16_t*>(stream + 1) };
19688 return { stream };
19689 }
19690
19691 template<typename Functor>
19692 void setBase(VirtualRegister value, Functor func)
19693 {
19694 if (isWide32())
19695 setBase<OpcodeSize::Wide32>(value, func);
19696 else if (isWide16())
19697 setBase<OpcodeSize::Wide16>(value, func);
19698 else
19699 setBase<OpcodeSize::Narrow>(value, func);
19700 }
19701
19702 template <OpcodeSize size, typename Functor>
19703 void setBase(VirtualRegister value, Functor func)
19704 {
19705 if (!Fits<VirtualRegister, size>::check(value))
19706 value = func();
19707 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
19708 *stream = Fits<VirtualRegister, size>::convert(value);
19709 }
19710
19711 template<typename Functor>
19712 void setThisValue(VirtualRegister value, Functor func)
19713 {
19714 if (isWide32())
19715 setThisValue<OpcodeSize::Wide32>(value, func);
19716 else if (isWide16())
19717 setThisValue<OpcodeSize::Wide16>(value, func);
19718 else
19719 setThisValue<OpcodeSize::Narrow>(value, func);
19720 }
19721
19722 template <OpcodeSize size, typename Functor>
19723 void setThisValue(VirtualRegister value, Functor func)
19724 {
19725 if (!Fits<VirtualRegister, size>::check(value))
19726 value = func();
19727 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
19728 *stream = Fits<VirtualRegister, size>::convert(value);
19729 }
19730
19731 template<typename Functor>
19732 void setProperty(VirtualRegister value, Functor func)
19733 {
19734 if (isWide32())
19735 setProperty<OpcodeSize::Wide32>(value, func);
19736 else if (isWide16())
19737 setProperty<OpcodeSize::Wide16>(value, func);
19738 else
19739 setProperty<OpcodeSize::Narrow>(value, func);
19740 }
19741
19742 template <OpcodeSize size, typename Functor>
19743 void setProperty(VirtualRegister value, Functor func)
19744 {
19745 if (!Fits<VirtualRegister, size>::check(value))
19746 value = func();
19747 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
19748 *stream = Fits<VirtualRegister, size>::convert(value);
19749 }
19750
19751 template<typename Functor>
19752 void setValue(VirtualRegister value, Functor func)
19753 {
19754 if (isWide32())
19755 setValue<OpcodeSize::Wide32>(value, func);
19756 else if (isWide16())
19757 setValue<OpcodeSize::Wide16>(value, func);
19758 else
19759 setValue<OpcodeSize::Narrow>(value, func);
19760 }
19761
19762 template <OpcodeSize size, typename Functor>
19763 void setValue(VirtualRegister value, Functor func)
19764 {
19765 if (!Fits<VirtualRegister, size>::check(value))
19766 value = func();
19767 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
19768 *stream = Fits<VirtualRegister, size>::convert(value);
19769 }
19770
19771 VirtualRegister m_base;
19772 VirtualRegister m_thisValue;
19773 VirtualRegister m_property;
19774 VirtualRegister m_value;
19775};
19776
19777struct OpDelByVal : public Instruction {
19778 static constexpr OpcodeID opcodeID = op_del_by_val;
19779
19780 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
19781 {
19782 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
19783 }
19784
19785 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
19786 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
19787 {
19788 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property);
19789 if (shouldAssert == Assert)
19790 ASSERT(didEmit);
19791 return didEmit;
19792 }
19793
19794 template<OpcodeSize size>
19795 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
19796 {
19797
19798 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
19799 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property))
19800 return;
19801 }
19802 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
19803 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
19804 return;
19805 }
19806 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
19807 }
19808
19809private:
19810 template<OpcodeSize size>
19811 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property)
19812 {
19813 UNUSED_PARAM(gen);
19814#if OS(WINDOWS) && ENABLE(C_LOOP)
19815 // FIXME: Disable wide16 optimization for Windows CLoop
19816 // https://bugs.webkit.org/show_bug.cgi?id=198283
19817 if (size == OpcodeSize::Wide16)
19818 return false;
19819#endif
19820 return Fits<OpcodeID, size>::check(opcodeID)
19821 && Fits<VirtualRegister, size>::check(dst)
19822 && Fits<VirtualRegister, size>::check(base)
19823 && Fits<VirtualRegister, size>::check(property)
19824 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
19825 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
19826 }
19827
19828 template<OpcodeSize size, bool recordOpcode>
19829 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
19830 {
19831 if (size == OpcodeSize::Wide16)
19832 gen->alignWideOpcode16();
19833 else if (size == OpcodeSize::Wide32)
19834 gen->alignWideOpcode32();
19835 if (checkImpl<size>(gen, dst, base, property)) {
19836 if (recordOpcode)
19837 gen->recordOpcode(opcodeID);
19838 if (size == OpcodeSize::Wide16)
19839 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
19840 else if (size == OpcodeSize::Wide32)
19841 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
19842 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
19843 gen->write(Fits<VirtualRegister, size>::convert(dst));
19844 gen->write(Fits<VirtualRegister, size>::convert(base));
19845 gen->write(Fits<VirtualRegister, size>::convert(property));
19846 return true;
19847 }
19848 return false;
19849 }
19850
19851public:
19852 template<typename Block>
19853 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
19854 {
19855 dumper->printLocationAndOp(__location, &"**del_by_val"[2 - __sizeShiftAmount]);
19856 dumper->dumpOperand(m_dst, true);
19857 dumper->dumpOperand(m_base, false);
19858 dumper->dumpOperand(m_property, false);
19859 }
19860
19861 OpDelByVal(const uint8_t* stream)
19862 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
19863 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
19864 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
19865 {
19866 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19867 }
19868
19869 OpDelByVal(const uint16_t* stream)
19870 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
19871 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
19872 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
19873 {
19874 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19875 }
19876
19877
19878 OpDelByVal(const uint32_t* stream)
19879 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
19880 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
19881 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
19882 {
19883 ASSERT_UNUSED(stream, stream[0] == opcodeID);
19884 }
19885
19886 static OpDelByVal decode(const uint8_t* stream)
19887 {
19888 if (*stream == op_wide32)
19889 return { bitwise_cast<const uint32_t*>(stream + 1) };
19890 if (*stream == op_wide16)
19891 return { bitwise_cast<const uint16_t*>(stream + 1) };
19892 return { stream };
19893 }
19894
19895 template<typename Functor>
19896 void setDst(VirtualRegister value, Functor func)
19897 {
19898 if (isWide32())
19899 setDst<OpcodeSize::Wide32>(value, func);
19900 else if (isWide16())
19901 setDst<OpcodeSize::Wide16>(value, func);
19902 else
19903 setDst<OpcodeSize::Narrow>(value, func);
19904 }
19905
19906 template <OpcodeSize size, typename Functor>
19907 void setDst(VirtualRegister value, Functor func)
19908 {
19909 if (!Fits<VirtualRegister, size>::check(value))
19910 value = func();
19911 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
19912 *stream = Fits<VirtualRegister, size>::convert(value);
19913 }
19914
19915 template<typename Functor>
19916 void setBase(VirtualRegister value, Functor func)
19917 {
19918 if (isWide32())
19919 setBase<OpcodeSize::Wide32>(value, func);
19920 else if (isWide16())
19921 setBase<OpcodeSize::Wide16>(value, func);
19922 else
19923 setBase<OpcodeSize::Narrow>(value, func);
19924 }
19925
19926 template <OpcodeSize size, typename Functor>
19927 void setBase(VirtualRegister value, Functor func)
19928 {
19929 if (!Fits<VirtualRegister, size>::check(value))
19930 value = func();
19931 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
19932 *stream = Fits<VirtualRegister, size>::convert(value);
19933 }
19934
19935 template<typename Functor>
19936 void setProperty(VirtualRegister value, Functor func)
19937 {
19938 if (isWide32())
19939 setProperty<OpcodeSize::Wide32>(value, func);
19940 else if (isWide16())
19941 setProperty<OpcodeSize::Wide16>(value, func);
19942 else
19943 setProperty<OpcodeSize::Narrow>(value, func);
19944 }
19945
19946 template <OpcodeSize size, typename Functor>
19947 void setProperty(VirtualRegister value, Functor func)
19948 {
19949 if (!Fits<VirtualRegister, size>::check(value))
19950 value = func();
19951 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
19952 *stream = Fits<VirtualRegister, size>::convert(value);
19953 }
19954
19955 VirtualRegister m_dst;
19956 VirtualRegister m_base;
19957 VirtualRegister m_property;
19958};
19959
19960struct OpPutGetterById : public Instruction {
19961 static constexpr OpcodeID opcodeID = op_put_getter_by_id;
19962
19963 static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
19964 {
19965 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, accessor);
19966 }
19967
19968 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
19969 static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
19970 {
19971 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor);
19972 if (shouldAssert == Assert)
19973 ASSERT(didEmit);
19974 return didEmit;
19975 }
19976
19977 template<OpcodeSize size>
19978 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
19979 {
19980
19981 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
19982 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor))
19983 return;
19984 }
19985 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
19986 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
19987 return;
19988 }
19989 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
19990 }
19991
19992private:
19993 template<OpcodeSize size>
19994 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, unsigned& attributes, VirtualRegister& accessor)
19995 {
19996 UNUSED_PARAM(gen);
19997#if OS(WINDOWS) && ENABLE(C_LOOP)
19998 // FIXME: Disable wide16 optimization for Windows CLoop
19999 // https://bugs.webkit.org/show_bug.cgi?id=198283
20000 if (size == OpcodeSize::Wide16)
20001 return false;
20002#endif
20003 return Fits<OpcodeID, size>::check(opcodeID)
20004 && Fits<VirtualRegister, size>::check(base)
20005 && Fits<unsigned, size>::check(property)
20006 && Fits<unsigned, size>::check(attributes)
20007 && Fits<VirtualRegister, size>::check(accessor)
20008 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
20009 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
20010 }
20011
20012 template<OpcodeSize size, bool recordOpcode>
20013 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
20014 {
20015 if (size == OpcodeSize::Wide16)
20016 gen->alignWideOpcode16();
20017 else if (size == OpcodeSize::Wide32)
20018 gen->alignWideOpcode32();
20019 if (checkImpl<size>(gen, base, property, attributes, accessor)) {
20020 if (recordOpcode)
20021 gen->recordOpcode(opcodeID);
20022 if (size == OpcodeSize::Wide16)
20023 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
20024 else if (size == OpcodeSize::Wide32)
20025 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
20026 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
20027 gen->write(Fits<VirtualRegister, size>::convert(base));
20028 gen->write(Fits<unsigned, size>::convert(property));
20029 gen->write(Fits<unsigned, size>::convert(attributes));
20030 gen->write(Fits<VirtualRegister, size>::convert(accessor));
20031 return true;
20032 }
20033 return false;
20034 }
20035
20036public:
20037 template<typename Block>
20038 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
20039 {
20040 dumper->printLocationAndOp(__location, &"**put_getter_by_id"[2 - __sizeShiftAmount]);
20041 dumper->dumpOperand(m_base, true);
20042 dumper->dumpOperand(m_property, false);
20043 dumper->dumpOperand(m_attributes, false);
20044 dumper->dumpOperand(m_accessor, false);
20045 }
20046
20047 OpPutGetterById(const uint8_t* stream)
20048 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
20049 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
20050 , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
20051 , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
20052 {
20053 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20054 }
20055
20056 OpPutGetterById(const uint16_t* stream)
20057 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
20058 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
20059 , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
20060 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
20061 {
20062 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20063 }
20064
20065
20066 OpPutGetterById(const uint32_t* stream)
20067 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
20068 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
20069 , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
20070 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
20071 {
20072 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20073 }
20074
20075 static OpPutGetterById decode(const uint8_t* stream)
20076 {
20077 if (*stream == op_wide32)
20078 return { bitwise_cast<const uint32_t*>(stream + 1) };
20079 if (*stream == op_wide16)
20080 return { bitwise_cast<const uint16_t*>(stream + 1) };
20081 return { stream };
20082 }
20083
20084 template<typename Functor>
20085 void setBase(VirtualRegister value, Functor func)
20086 {
20087 if (isWide32())
20088 setBase<OpcodeSize::Wide32>(value, func);
20089 else if (isWide16())
20090 setBase<OpcodeSize::Wide16>(value, func);
20091 else
20092 setBase<OpcodeSize::Narrow>(value, func);
20093 }
20094
20095 template <OpcodeSize size, typename Functor>
20096 void setBase(VirtualRegister value, Functor func)
20097 {
20098 if (!Fits<VirtualRegister, size>::check(value))
20099 value = func();
20100 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
20101 *stream = Fits<VirtualRegister, size>::convert(value);
20102 }
20103
20104 template<typename Functor>
20105 void setProperty(unsigned value, Functor func)
20106 {
20107 if (isWide32())
20108 setProperty<OpcodeSize::Wide32>(value, func);
20109 else if (isWide16())
20110 setProperty<OpcodeSize::Wide16>(value, func);
20111 else
20112 setProperty<OpcodeSize::Narrow>(value, func);
20113 }
20114
20115 template <OpcodeSize size, typename Functor>
20116 void setProperty(unsigned value, Functor func)
20117 {
20118 if (!Fits<unsigned, size>::check(value))
20119 value = func();
20120 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
20121 *stream = Fits<unsigned, size>::convert(value);
20122 }
20123
20124 template<typename Functor>
20125 void setAttributes(unsigned value, Functor func)
20126 {
20127 if (isWide32())
20128 setAttributes<OpcodeSize::Wide32>(value, func);
20129 else if (isWide16())
20130 setAttributes<OpcodeSize::Wide16>(value, func);
20131 else
20132 setAttributes<OpcodeSize::Narrow>(value, func);
20133 }
20134
20135 template <OpcodeSize size, typename Functor>
20136 void setAttributes(unsigned value, Functor func)
20137 {
20138 if (!Fits<unsigned, size>::check(value))
20139 value = func();
20140 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
20141 *stream = Fits<unsigned, size>::convert(value);
20142 }
20143
20144 template<typename Functor>
20145 void setAccessor(VirtualRegister value, Functor func)
20146 {
20147 if (isWide32())
20148 setAccessor<OpcodeSize::Wide32>(value, func);
20149 else if (isWide16())
20150 setAccessor<OpcodeSize::Wide16>(value, func);
20151 else
20152 setAccessor<OpcodeSize::Narrow>(value, func);
20153 }
20154
20155 template <OpcodeSize size, typename Functor>
20156 void setAccessor(VirtualRegister value, Functor func)
20157 {
20158 if (!Fits<VirtualRegister, size>::check(value))
20159 value = func();
20160 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
20161 *stream = Fits<VirtualRegister, size>::convert(value);
20162 }
20163
20164 VirtualRegister m_base;
20165 unsigned m_property;
20166 unsigned m_attributes;
20167 VirtualRegister m_accessor;
20168};
20169
20170struct OpPutSetterById : public Instruction {
20171 static constexpr OpcodeID opcodeID = op_put_setter_by_id;
20172
20173 static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
20174 {
20175 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, accessor);
20176 }
20177
20178 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
20179 static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
20180 {
20181 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor);
20182 if (shouldAssert == Assert)
20183 ASSERT(didEmit);
20184 return didEmit;
20185 }
20186
20187 template<OpcodeSize size>
20188 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
20189 {
20190
20191 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
20192 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor))
20193 return;
20194 }
20195 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
20196 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
20197 return;
20198 }
20199 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
20200 }
20201
20202private:
20203 template<OpcodeSize size>
20204 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, unsigned& attributes, VirtualRegister& accessor)
20205 {
20206 UNUSED_PARAM(gen);
20207#if OS(WINDOWS) && ENABLE(C_LOOP)
20208 // FIXME: Disable wide16 optimization for Windows CLoop
20209 // https://bugs.webkit.org/show_bug.cgi?id=198283
20210 if (size == OpcodeSize::Wide16)
20211 return false;
20212#endif
20213 return Fits<OpcodeID, size>::check(opcodeID)
20214 && Fits<VirtualRegister, size>::check(base)
20215 && Fits<unsigned, size>::check(property)
20216 && Fits<unsigned, size>::check(attributes)
20217 && Fits<VirtualRegister, size>::check(accessor)
20218 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
20219 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
20220 }
20221
20222 template<OpcodeSize size, bool recordOpcode>
20223 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
20224 {
20225 if (size == OpcodeSize::Wide16)
20226 gen->alignWideOpcode16();
20227 else if (size == OpcodeSize::Wide32)
20228 gen->alignWideOpcode32();
20229 if (checkImpl<size>(gen, base, property, attributes, accessor)) {
20230 if (recordOpcode)
20231 gen->recordOpcode(opcodeID);
20232 if (size == OpcodeSize::Wide16)
20233 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
20234 else if (size == OpcodeSize::Wide32)
20235 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
20236 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
20237 gen->write(Fits<VirtualRegister, size>::convert(base));
20238 gen->write(Fits<unsigned, size>::convert(property));
20239 gen->write(Fits<unsigned, size>::convert(attributes));
20240 gen->write(Fits<VirtualRegister, size>::convert(accessor));
20241 return true;
20242 }
20243 return false;
20244 }
20245
20246public:
20247 template<typename Block>
20248 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
20249 {
20250 dumper->printLocationAndOp(__location, &"**put_setter_by_id"[2 - __sizeShiftAmount]);
20251 dumper->dumpOperand(m_base, true);
20252 dumper->dumpOperand(m_property, false);
20253 dumper->dumpOperand(m_attributes, false);
20254 dumper->dumpOperand(m_accessor, false);
20255 }
20256
20257 OpPutSetterById(const uint8_t* stream)
20258 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
20259 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
20260 , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
20261 , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
20262 {
20263 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20264 }
20265
20266 OpPutSetterById(const uint16_t* stream)
20267 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
20268 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
20269 , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
20270 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
20271 {
20272 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20273 }
20274
20275
20276 OpPutSetterById(const uint32_t* stream)
20277 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
20278 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
20279 , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
20280 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
20281 {
20282 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20283 }
20284
20285 static OpPutSetterById decode(const uint8_t* stream)
20286 {
20287 if (*stream == op_wide32)
20288 return { bitwise_cast<const uint32_t*>(stream + 1) };
20289 if (*stream == op_wide16)
20290 return { bitwise_cast<const uint16_t*>(stream + 1) };
20291 return { stream };
20292 }
20293
20294 template<typename Functor>
20295 void setBase(VirtualRegister value, Functor func)
20296 {
20297 if (isWide32())
20298 setBase<OpcodeSize::Wide32>(value, func);
20299 else if (isWide16())
20300 setBase<OpcodeSize::Wide16>(value, func);
20301 else
20302 setBase<OpcodeSize::Narrow>(value, func);
20303 }
20304
20305 template <OpcodeSize size, typename Functor>
20306 void setBase(VirtualRegister value, Functor func)
20307 {
20308 if (!Fits<VirtualRegister, size>::check(value))
20309 value = func();
20310 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
20311 *stream = Fits<VirtualRegister, size>::convert(value);
20312 }
20313
20314 template<typename Functor>
20315 void setProperty(unsigned value, Functor func)
20316 {
20317 if (isWide32())
20318 setProperty<OpcodeSize::Wide32>(value, func);
20319 else if (isWide16())
20320 setProperty<OpcodeSize::Wide16>(value, func);
20321 else
20322 setProperty<OpcodeSize::Narrow>(value, func);
20323 }
20324
20325 template <OpcodeSize size, typename Functor>
20326 void setProperty(unsigned value, Functor func)
20327 {
20328 if (!Fits<unsigned, size>::check(value))
20329 value = func();
20330 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
20331 *stream = Fits<unsigned, size>::convert(value);
20332 }
20333
20334 template<typename Functor>
20335 void setAttributes(unsigned value, Functor func)
20336 {
20337 if (isWide32())
20338 setAttributes<OpcodeSize::Wide32>(value, func);
20339 else if (isWide16())
20340 setAttributes<OpcodeSize::Wide16>(value, func);
20341 else
20342 setAttributes<OpcodeSize::Narrow>(value, func);
20343 }
20344
20345 template <OpcodeSize size, typename Functor>
20346 void setAttributes(unsigned value, Functor func)
20347 {
20348 if (!Fits<unsigned, size>::check(value))
20349 value = func();
20350 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
20351 *stream = Fits<unsigned, size>::convert(value);
20352 }
20353
20354 template<typename Functor>
20355 void setAccessor(VirtualRegister value, Functor func)
20356 {
20357 if (isWide32())
20358 setAccessor<OpcodeSize::Wide32>(value, func);
20359 else if (isWide16())
20360 setAccessor<OpcodeSize::Wide16>(value, func);
20361 else
20362 setAccessor<OpcodeSize::Narrow>(value, func);
20363 }
20364
20365 template <OpcodeSize size, typename Functor>
20366 void setAccessor(VirtualRegister value, Functor func)
20367 {
20368 if (!Fits<VirtualRegister, size>::check(value))
20369 value = func();
20370 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
20371 *stream = Fits<VirtualRegister, size>::convert(value);
20372 }
20373
20374 VirtualRegister m_base;
20375 unsigned m_property;
20376 unsigned m_attributes;
20377 VirtualRegister m_accessor;
20378};
20379
20380struct OpPutGetterSetterById : public Instruction {
20381 static constexpr OpcodeID opcodeID = op_put_getter_setter_by_id;
20382
20383 static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
20384 {
20385 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, getter, setter);
20386 }
20387
20388 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
20389 static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
20390 {
20391 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, getter, setter);
20392 if (shouldAssert == Assert)
20393 ASSERT(didEmit);
20394 return didEmit;
20395 }
20396
20397 template<OpcodeSize size>
20398 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
20399 {
20400
20401 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
20402 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, getter, setter))
20403 return;
20404 }
20405 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
20406 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, getter, setter))
20407 return;
20408 }
20409 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, getter, setter);
20410 }
20411
20412private:
20413 template<OpcodeSize size>
20414 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, unsigned& attributes, VirtualRegister& getter, VirtualRegister& setter)
20415 {
20416 UNUSED_PARAM(gen);
20417#if OS(WINDOWS) && ENABLE(C_LOOP)
20418 // FIXME: Disable wide16 optimization for Windows CLoop
20419 // https://bugs.webkit.org/show_bug.cgi?id=198283
20420 if (size == OpcodeSize::Wide16)
20421 return false;
20422#endif
20423 return Fits<OpcodeID, size>::check(opcodeID)
20424 && Fits<VirtualRegister, size>::check(base)
20425 && Fits<unsigned, size>::check(property)
20426 && Fits<unsigned, size>::check(attributes)
20427 && Fits<VirtualRegister, size>::check(getter)
20428 && Fits<VirtualRegister, size>::check(setter)
20429 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
20430 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
20431 }
20432
20433 template<OpcodeSize size, bool recordOpcode>
20434 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
20435 {
20436 if (size == OpcodeSize::Wide16)
20437 gen->alignWideOpcode16();
20438 else if (size == OpcodeSize::Wide32)
20439 gen->alignWideOpcode32();
20440 if (checkImpl<size>(gen, base, property, attributes, getter, setter)) {
20441 if (recordOpcode)
20442 gen->recordOpcode(opcodeID);
20443 if (size == OpcodeSize::Wide16)
20444 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
20445 else if (size == OpcodeSize::Wide32)
20446 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
20447 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
20448 gen->write(Fits<VirtualRegister, size>::convert(base));
20449 gen->write(Fits<unsigned, size>::convert(property));
20450 gen->write(Fits<unsigned, size>::convert(attributes));
20451 gen->write(Fits<VirtualRegister, size>::convert(getter));
20452 gen->write(Fits<VirtualRegister, size>::convert(setter));
20453 return true;
20454 }
20455 return false;
20456 }
20457
20458public:
20459 template<typename Block>
20460 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
20461 {
20462 dumper->printLocationAndOp(__location, &"**put_getter_setter_by_id"[2 - __sizeShiftAmount]);
20463 dumper->dumpOperand(m_base, true);
20464 dumper->dumpOperand(m_property, false);
20465 dumper->dumpOperand(m_attributes, false);
20466 dumper->dumpOperand(m_getter, false);
20467 dumper->dumpOperand(m_setter, false);
20468 }
20469
20470 OpPutGetterSetterById(const uint8_t* stream)
20471 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
20472 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
20473 , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
20474 , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
20475 , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
20476 {
20477 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20478 }
20479
20480 OpPutGetterSetterById(const uint16_t* stream)
20481 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
20482 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
20483 , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
20484 , m_getter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
20485 , m_setter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
20486 {
20487 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20488 }
20489
20490
20491 OpPutGetterSetterById(const uint32_t* stream)
20492 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
20493 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
20494 , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
20495 , m_getter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
20496 , m_setter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
20497 {
20498 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20499 }
20500
20501 static OpPutGetterSetterById decode(const uint8_t* stream)
20502 {
20503 if (*stream == op_wide32)
20504 return { bitwise_cast<const uint32_t*>(stream + 1) };
20505 if (*stream == op_wide16)
20506 return { bitwise_cast<const uint16_t*>(stream + 1) };
20507 return { stream };
20508 }
20509
20510 template<typename Functor>
20511 void setBase(VirtualRegister value, Functor func)
20512 {
20513 if (isWide32())
20514 setBase<OpcodeSize::Wide32>(value, func);
20515 else if (isWide16())
20516 setBase<OpcodeSize::Wide16>(value, func);
20517 else
20518 setBase<OpcodeSize::Narrow>(value, func);
20519 }
20520
20521 template <OpcodeSize size, typename Functor>
20522 void setBase(VirtualRegister value, Functor func)
20523 {
20524 if (!Fits<VirtualRegister, size>::check(value))
20525 value = func();
20526 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
20527 *stream = Fits<VirtualRegister, size>::convert(value);
20528 }
20529
20530 template<typename Functor>
20531 void setProperty(unsigned value, Functor func)
20532 {
20533 if (isWide32())
20534 setProperty<OpcodeSize::Wide32>(value, func);
20535 else if (isWide16())
20536 setProperty<OpcodeSize::Wide16>(value, func);
20537 else
20538 setProperty<OpcodeSize::Narrow>(value, func);
20539 }
20540
20541 template <OpcodeSize size, typename Functor>
20542 void setProperty(unsigned value, Functor func)
20543 {
20544 if (!Fits<unsigned, size>::check(value))
20545 value = func();
20546 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
20547 *stream = Fits<unsigned, size>::convert(value);
20548 }
20549
20550 template<typename Functor>
20551 void setAttributes(unsigned value, Functor func)
20552 {
20553 if (isWide32())
20554 setAttributes<OpcodeSize::Wide32>(value, func);
20555 else if (isWide16())
20556 setAttributes<OpcodeSize::Wide16>(value, func);
20557 else
20558 setAttributes<OpcodeSize::Narrow>(value, func);
20559 }
20560
20561 template <OpcodeSize size, typename Functor>
20562 void setAttributes(unsigned value, Functor func)
20563 {
20564 if (!Fits<unsigned, size>::check(value))
20565 value = func();
20566 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
20567 *stream = Fits<unsigned, size>::convert(value);
20568 }
20569
20570 template<typename Functor>
20571 void setGetter(VirtualRegister value, Functor func)
20572 {
20573 if (isWide32())
20574 setGetter<OpcodeSize::Wide32>(value, func);
20575 else if (isWide16())
20576 setGetter<OpcodeSize::Wide16>(value, func);
20577 else
20578 setGetter<OpcodeSize::Narrow>(value, func);
20579 }
20580
20581 template <OpcodeSize size, typename Functor>
20582 void setGetter(VirtualRegister value, Functor func)
20583 {
20584 if (!Fits<VirtualRegister, size>::check(value))
20585 value = func();
20586 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
20587 *stream = Fits<VirtualRegister, size>::convert(value);
20588 }
20589
20590 template<typename Functor>
20591 void setSetter(VirtualRegister value, Functor func)
20592 {
20593 if (isWide32())
20594 setSetter<OpcodeSize::Wide32>(value, func);
20595 else if (isWide16())
20596 setSetter<OpcodeSize::Wide16>(value, func);
20597 else
20598 setSetter<OpcodeSize::Narrow>(value, func);
20599 }
20600
20601 template <OpcodeSize size, typename Functor>
20602 void setSetter(VirtualRegister value, Functor func)
20603 {
20604 if (!Fits<VirtualRegister, size>::check(value))
20605 value = func();
20606 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
20607 *stream = Fits<VirtualRegister, size>::convert(value);
20608 }
20609
20610 VirtualRegister m_base;
20611 unsigned m_property;
20612 unsigned m_attributes;
20613 VirtualRegister m_getter;
20614 VirtualRegister m_setter;
20615};
20616
20617struct OpPutGetterByVal : public Instruction {
20618 static constexpr OpcodeID opcodeID = op_put_getter_by_val;
20619
20620 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20621 {
20622 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, accessor);
20623 }
20624
20625 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
20626 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20627 {
20628 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor);
20629 if (shouldAssert == Assert)
20630 ASSERT(didEmit);
20631 return didEmit;
20632 }
20633
20634 template<OpcodeSize size>
20635 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20636 {
20637
20638 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
20639 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor))
20640 return;
20641 }
20642 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
20643 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
20644 return;
20645 }
20646 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
20647 }
20648
20649private:
20650 template<OpcodeSize size>
20651 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, unsigned& attributes, VirtualRegister& accessor)
20652 {
20653 UNUSED_PARAM(gen);
20654#if OS(WINDOWS) && ENABLE(C_LOOP)
20655 // FIXME: Disable wide16 optimization for Windows CLoop
20656 // https://bugs.webkit.org/show_bug.cgi?id=198283
20657 if (size == OpcodeSize::Wide16)
20658 return false;
20659#endif
20660 return Fits<OpcodeID, size>::check(opcodeID)
20661 && Fits<VirtualRegister, size>::check(base)
20662 && Fits<VirtualRegister, size>::check(property)
20663 && Fits<unsigned, size>::check(attributes)
20664 && Fits<VirtualRegister, size>::check(accessor)
20665 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
20666 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
20667 }
20668
20669 template<OpcodeSize size, bool recordOpcode>
20670 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20671 {
20672 if (size == OpcodeSize::Wide16)
20673 gen->alignWideOpcode16();
20674 else if (size == OpcodeSize::Wide32)
20675 gen->alignWideOpcode32();
20676 if (checkImpl<size>(gen, base, property, attributes, accessor)) {
20677 if (recordOpcode)
20678 gen->recordOpcode(opcodeID);
20679 if (size == OpcodeSize::Wide16)
20680 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
20681 else if (size == OpcodeSize::Wide32)
20682 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
20683 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
20684 gen->write(Fits<VirtualRegister, size>::convert(base));
20685 gen->write(Fits<VirtualRegister, size>::convert(property));
20686 gen->write(Fits<unsigned, size>::convert(attributes));
20687 gen->write(Fits<VirtualRegister, size>::convert(accessor));
20688 return true;
20689 }
20690 return false;
20691 }
20692
20693public:
20694 template<typename Block>
20695 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
20696 {
20697 dumper->printLocationAndOp(__location, &"**put_getter_by_val"[2 - __sizeShiftAmount]);
20698 dumper->dumpOperand(m_base, true);
20699 dumper->dumpOperand(m_property, false);
20700 dumper->dumpOperand(m_attributes, false);
20701 dumper->dumpOperand(m_accessor, false);
20702 }
20703
20704 OpPutGetterByVal(const uint8_t* stream)
20705 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
20706 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
20707 , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
20708 , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
20709 {
20710 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20711 }
20712
20713 OpPutGetterByVal(const uint16_t* stream)
20714 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
20715 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
20716 , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
20717 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
20718 {
20719 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20720 }
20721
20722
20723 OpPutGetterByVal(const uint32_t* stream)
20724 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
20725 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
20726 , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
20727 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
20728 {
20729 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20730 }
20731
20732 static OpPutGetterByVal decode(const uint8_t* stream)
20733 {
20734 if (*stream == op_wide32)
20735 return { bitwise_cast<const uint32_t*>(stream + 1) };
20736 if (*stream == op_wide16)
20737 return { bitwise_cast<const uint16_t*>(stream + 1) };
20738 return { stream };
20739 }
20740
20741 template<typename Functor>
20742 void setBase(VirtualRegister value, Functor func)
20743 {
20744 if (isWide32())
20745 setBase<OpcodeSize::Wide32>(value, func);
20746 else if (isWide16())
20747 setBase<OpcodeSize::Wide16>(value, func);
20748 else
20749 setBase<OpcodeSize::Narrow>(value, func);
20750 }
20751
20752 template <OpcodeSize size, typename Functor>
20753 void setBase(VirtualRegister value, Functor func)
20754 {
20755 if (!Fits<VirtualRegister, size>::check(value))
20756 value = func();
20757 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
20758 *stream = Fits<VirtualRegister, size>::convert(value);
20759 }
20760
20761 template<typename Functor>
20762 void setProperty(VirtualRegister value, Functor func)
20763 {
20764 if (isWide32())
20765 setProperty<OpcodeSize::Wide32>(value, func);
20766 else if (isWide16())
20767 setProperty<OpcodeSize::Wide16>(value, func);
20768 else
20769 setProperty<OpcodeSize::Narrow>(value, func);
20770 }
20771
20772 template <OpcodeSize size, typename Functor>
20773 void setProperty(VirtualRegister value, Functor func)
20774 {
20775 if (!Fits<VirtualRegister, size>::check(value))
20776 value = func();
20777 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
20778 *stream = Fits<VirtualRegister, size>::convert(value);
20779 }
20780
20781 template<typename Functor>
20782 void setAttributes(unsigned value, Functor func)
20783 {
20784 if (isWide32())
20785 setAttributes<OpcodeSize::Wide32>(value, func);
20786 else if (isWide16())
20787 setAttributes<OpcodeSize::Wide16>(value, func);
20788 else
20789 setAttributes<OpcodeSize::Narrow>(value, func);
20790 }
20791
20792 template <OpcodeSize size, typename Functor>
20793 void setAttributes(unsigned value, Functor func)
20794 {
20795 if (!Fits<unsigned, size>::check(value))
20796 value = func();
20797 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
20798 *stream = Fits<unsigned, size>::convert(value);
20799 }
20800
20801 template<typename Functor>
20802 void setAccessor(VirtualRegister value, Functor func)
20803 {
20804 if (isWide32())
20805 setAccessor<OpcodeSize::Wide32>(value, func);
20806 else if (isWide16())
20807 setAccessor<OpcodeSize::Wide16>(value, func);
20808 else
20809 setAccessor<OpcodeSize::Narrow>(value, func);
20810 }
20811
20812 template <OpcodeSize size, typename Functor>
20813 void setAccessor(VirtualRegister value, Functor func)
20814 {
20815 if (!Fits<VirtualRegister, size>::check(value))
20816 value = func();
20817 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
20818 *stream = Fits<VirtualRegister, size>::convert(value);
20819 }
20820
20821 VirtualRegister m_base;
20822 VirtualRegister m_property;
20823 unsigned m_attributes;
20824 VirtualRegister m_accessor;
20825};
20826
20827struct OpPutSetterByVal : public Instruction {
20828 static constexpr OpcodeID opcodeID = op_put_setter_by_val;
20829
20830 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20831 {
20832 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, accessor);
20833 }
20834
20835 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
20836 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20837 {
20838 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, attributes, accessor);
20839 if (shouldAssert == Assert)
20840 ASSERT(didEmit);
20841 return didEmit;
20842 }
20843
20844 template<OpcodeSize size>
20845 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20846 {
20847
20848 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
20849 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, attributes, accessor))
20850 return;
20851 }
20852 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
20853 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
20854 return;
20855 }
20856 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
20857 }
20858
20859private:
20860 template<OpcodeSize size>
20861 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, unsigned& attributes, VirtualRegister& accessor)
20862 {
20863 UNUSED_PARAM(gen);
20864#if OS(WINDOWS) && ENABLE(C_LOOP)
20865 // FIXME: Disable wide16 optimization for Windows CLoop
20866 // https://bugs.webkit.org/show_bug.cgi?id=198283
20867 if (size == OpcodeSize::Wide16)
20868 return false;
20869#endif
20870 return Fits<OpcodeID, size>::check(opcodeID)
20871 && Fits<VirtualRegister, size>::check(base)
20872 && Fits<VirtualRegister, size>::check(property)
20873 && Fits<unsigned, size>::check(attributes)
20874 && Fits<VirtualRegister, size>::check(accessor)
20875 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
20876 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
20877 }
20878
20879 template<OpcodeSize size, bool recordOpcode>
20880 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
20881 {
20882 if (size == OpcodeSize::Wide16)
20883 gen->alignWideOpcode16();
20884 else if (size == OpcodeSize::Wide32)
20885 gen->alignWideOpcode32();
20886 if (checkImpl<size>(gen, base, property, attributes, accessor)) {
20887 if (recordOpcode)
20888 gen->recordOpcode(opcodeID);
20889 if (size == OpcodeSize::Wide16)
20890 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
20891 else if (size == OpcodeSize::Wide32)
20892 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
20893 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
20894 gen->write(Fits<VirtualRegister, size>::convert(base));
20895 gen->write(Fits<VirtualRegister, size>::convert(property));
20896 gen->write(Fits<unsigned, size>::convert(attributes));
20897 gen->write(Fits<VirtualRegister, size>::convert(accessor));
20898 return true;
20899 }
20900 return false;
20901 }
20902
20903public:
20904 template<typename Block>
20905 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
20906 {
20907 dumper->printLocationAndOp(__location, &"**put_setter_by_val"[2 - __sizeShiftAmount]);
20908 dumper->dumpOperand(m_base, true);
20909 dumper->dumpOperand(m_property, false);
20910 dumper->dumpOperand(m_attributes, false);
20911 dumper->dumpOperand(m_accessor, false);
20912 }
20913
20914 OpPutSetterByVal(const uint8_t* stream)
20915 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
20916 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
20917 , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
20918 , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
20919 {
20920 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20921 }
20922
20923 OpPutSetterByVal(const uint16_t* stream)
20924 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
20925 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
20926 , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
20927 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
20928 {
20929 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20930 }
20931
20932
20933 OpPutSetterByVal(const uint32_t* stream)
20934 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
20935 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
20936 , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
20937 , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
20938 {
20939 ASSERT_UNUSED(stream, stream[0] == opcodeID);
20940 }
20941
20942 static OpPutSetterByVal decode(const uint8_t* stream)
20943 {
20944 if (*stream == op_wide32)
20945 return { bitwise_cast<const uint32_t*>(stream + 1) };
20946 if (*stream == op_wide16)
20947 return { bitwise_cast<const uint16_t*>(stream + 1) };
20948 return { stream };
20949 }
20950
20951 template<typename Functor>
20952 void setBase(VirtualRegister value, Functor func)
20953 {
20954 if (isWide32())
20955 setBase<OpcodeSize::Wide32>(value, func);
20956 else if (isWide16())
20957 setBase<OpcodeSize::Wide16>(value, func);
20958 else
20959 setBase<OpcodeSize::Narrow>(value, func);
20960 }
20961
20962 template <OpcodeSize size, typename Functor>
20963 void setBase(VirtualRegister value, Functor func)
20964 {
20965 if (!Fits<VirtualRegister, size>::check(value))
20966 value = func();
20967 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
20968 *stream = Fits<VirtualRegister, size>::convert(value);
20969 }
20970
20971 template<typename Functor>
20972 void setProperty(VirtualRegister value, Functor func)
20973 {
20974 if (isWide32())
20975 setProperty<OpcodeSize::Wide32>(value, func);
20976 else if (isWide16())
20977 setProperty<OpcodeSize::Wide16>(value, func);
20978 else
20979 setProperty<OpcodeSize::Narrow>(value, func);
20980 }
20981
20982 template <OpcodeSize size, typename Functor>
20983 void setProperty(VirtualRegister value, Functor func)
20984 {
20985 if (!Fits<VirtualRegister, size>::check(value))
20986 value = func();
20987 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
20988 *stream = Fits<VirtualRegister, size>::convert(value);
20989 }
20990
20991 template<typename Functor>
20992 void setAttributes(unsigned value, Functor func)
20993 {
20994 if (isWide32())
20995 setAttributes<OpcodeSize::Wide32>(value, func);
20996 else if (isWide16())
20997 setAttributes<OpcodeSize::Wide16>(value, func);
20998 else
20999 setAttributes<OpcodeSize::Narrow>(value, func);
21000 }
21001
21002 template <OpcodeSize size, typename Functor>
21003 void setAttributes(unsigned value, Functor func)
21004 {
21005 if (!Fits<unsigned, size>::check(value))
21006 value = func();
21007 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
21008 *stream = Fits<unsigned, size>::convert(value);
21009 }
21010
21011 template<typename Functor>
21012 void setAccessor(VirtualRegister value, Functor func)
21013 {
21014 if (isWide32())
21015 setAccessor<OpcodeSize::Wide32>(value, func);
21016 else if (isWide16())
21017 setAccessor<OpcodeSize::Wide16>(value, func);
21018 else
21019 setAccessor<OpcodeSize::Narrow>(value, func);
21020 }
21021
21022 template <OpcodeSize size, typename Functor>
21023 void setAccessor(VirtualRegister value, Functor func)
21024 {
21025 if (!Fits<VirtualRegister, size>::check(value))
21026 value = func();
21027 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
21028 *stream = Fits<VirtualRegister, size>::convert(value);
21029 }
21030
21031 VirtualRegister m_base;
21032 VirtualRegister m_property;
21033 unsigned m_attributes;
21034 VirtualRegister m_accessor;
21035};
21036
21037struct OpDefineDataProperty : public Instruction {
21038 static constexpr OpcodeID opcodeID = op_define_data_property;
21039
21040 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
21041 {
21042 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, value, attributes);
21043 }
21044
21045 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
21046 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
21047 {
21048 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, attributes);
21049 if (shouldAssert == Assert)
21050 ASSERT(didEmit);
21051 return didEmit;
21052 }
21053
21054 template<OpcodeSize size>
21055 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
21056 {
21057
21058 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
21059 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, value, attributes))
21060 return;
21061 }
21062 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
21063 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, value, attributes))
21064 return;
21065 }
21066 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, value, attributes);
21067 }
21068
21069private:
21070 template<OpcodeSize size>
21071 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& value, VirtualRegister& attributes)
21072 {
21073 UNUSED_PARAM(gen);
21074#if OS(WINDOWS) && ENABLE(C_LOOP)
21075 // FIXME: Disable wide16 optimization for Windows CLoop
21076 // https://bugs.webkit.org/show_bug.cgi?id=198283
21077 if (size == OpcodeSize::Wide16)
21078 return false;
21079#endif
21080 return Fits<OpcodeID, size>::check(opcodeID)
21081 && Fits<VirtualRegister, size>::check(base)
21082 && Fits<VirtualRegister, size>::check(property)
21083 && Fits<VirtualRegister, size>::check(value)
21084 && Fits<VirtualRegister, size>::check(attributes)
21085 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
21086 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
21087 }
21088
21089 template<OpcodeSize size, bool recordOpcode>
21090 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
21091 {
21092 if (size == OpcodeSize::Wide16)
21093 gen->alignWideOpcode16();
21094 else if (size == OpcodeSize::Wide32)
21095 gen->alignWideOpcode32();
21096 if (checkImpl<size>(gen, base, property, value, attributes)) {
21097 if (recordOpcode)
21098 gen->recordOpcode(opcodeID);
21099 if (size == OpcodeSize::Wide16)
21100 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
21101 else if (size == OpcodeSize::Wide32)
21102 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
21103 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
21104 gen->write(Fits<VirtualRegister, size>::convert(base));
21105 gen->write(Fits<VirtualRegister, size>::convert(property));
21106 gen->write(Fits<VirtualRegister, size>::convert(value));
21107 gen->write(Fits<VirtualRegister, size>::convert(attributes));
21108 return true;
21109 }
21110 return false;
21111 }
21112
21113public:
21114 template<typename Block>
21115 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
21116 {
21117 dumper->printLocationAndOp(__location, &"**define_data_property"[2 - __sizeShiftAmount]);
21118 dumper->dumpOperand(m_base, true);
21119 dumper->dumpOperand(m_property, false);
21120 dumper->dumpOperand(m_value, false);
21121 dumper->dumpOperand(m_attributes, false);
21122 }
21123
21124 OpDefineDataProperty(const uint8_t* stream)
21125 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
21126 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
21127 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
21128 , m_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
21129 {
21130 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21131 }
21132
21133 OpDefineDataProperty(const uint16_t* stream)
21134 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
21135 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
21136 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
21137 , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
21138 {
21139 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21140 }
21141
21142
21143 OpDefineDataProperty(const uint32_t* stream)
21144 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
21145 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
21146 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
21147 , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
21148 {
21149 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21150 }
21151
21152 static OpDefineDataProperty decode(const uint8_t* stream)
21153 {
21154 if (*stream == op_wide32)
21155 return { bitwise_cast<const uint32_t*>(stream + 1) };
21156 if (*stream == op_wide16)
21157 return { bitwise_cast<const uint16_t*>(stream + 1) };
21158 return { stream };
21159 }
21160
21161 template<typename Functor>
21162 void setBase(VirtualRegister value, Functor func)
21163 {
21164 if (isWide32())
21165 setBase<OpcodeSize::Wide32>(value, func);
21166 else if (isWide16())
21167 setBase<OpcodeSize::Wide16>(value, func);
21168 else
21169 setBase<OpcodeSize::Narrow>(value, func);
21170 }
21171
21172 template <OpcodeSize size, typename Functor>
21173 void setBase(VirtualRegister value, Functor func)
21174 {
21175 if (!Fits<VirtualRegister, size>::check(value))
21176 value = func();
21177 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
21178 *stream = Fits<VirtualRegister, size>::convert(value);
21179 }
21180
21181 template<typename Functor>
21182 void setProperty(VirtualRegister value, Functor func)
21183 {
21184 if (isWide32())
21185 setProperty<OpcodeSize::Wide32>(value, func);
21186 else if (isWide16())
21187 setProperty<OpcodeSize::Wide16>(value, func);
21188 else
21189 setProperty<OpcodeSize::Narrow>(value, func);
21190 }
21191
21192 template <OpcodeSize size, typename Functor>
21193 void setProperty(VirtualRegister value, Functor func)
21194 {
21195 if (!Fits<VirtualRegister, size>::check(value))
21196 value = func();
21197 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
21198 *stream = Fits<VirtualRegister, size>::convert(value);
21199 }
21200
21201 template<typename Functor>
21202 void setValue(VirtualRegister value, Functor func)
21203 {
21204 if (isWide32())
21205 setValue<OpcodeSize::Wide32>(value, func);
21206 else if (isWide16())
21207 setValue<OpcodeSize::Wide16>(value, func);
21208 else
21209 setValue<OpcodeSize::Narrow>(value, func);
21210 }
21211
21212 template <OpcodeSize size, typename Functor>
21213 void setValue(VirtualRegister value, Functor func)
21214 {
21215 if (!Fits<VirtualRegister, size>::check(value))
21216 value = func();
21217 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
21218 *stream = Fits<VirtualRegister, size>::convert(value);
21219 }
21220
21221 template<typename Functor>
21222 void setAttributes(VirtualRegister value, Functor func)
21223 {
21224 if (isWide32())
21225 setAttributes<OpcodeSize::Wide32>(value, func);
21226 else if (isWide16())
21227 setAttributes<OpcodeSize::Wide16>(value, func);
21228 else
21229 setAttributes<OpcodeSize::Narrow>(value, func);
21230 }
21231
21232 template <OpcodeSize size, typename Functor>
21233 void setAttributes(VirtualRegister value, Functor func)
21234 {
21235 if (!Fits<VirtualRegister, size>::check(value))
21236 value = func();
21237 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
21238 *stream = Fits<VirtualRegister, size>::convert(value);
21239 }
21240
21241 VirtualRegister m_base;
21242 VirtualRegister m_property;
21243 VirtualRegister m_value;
21244 VirtualRegister m_attributes;
21245};
21246
21247struct OpDefineAccessorProperty : public Instruction {
21248 static constexpr OpcodeID opcodeID = op_define_accessor_property;
21249
21250 static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
21251 {
21252 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, getter, setter, attributes);
21253 }
21254
21255 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
21256 static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
21257 {
21258 bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, getter, setter, attributes);
21259 if (shouldAssert == Assert)
21260 ASSERT(didEmit);
21261 return didEmit;
21262 }
21263
21264 template<OpcodeSize size>
21265 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
21266 {
21267
21268 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
21269 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, property, getter, setter, attributes))
21270 return;
21271 }
21272 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
21273 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, getter, setter, attributes))
21274 return;
21275 }
21276 emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, getter, setter, attributes);
21277 }
21278
21279private:
21280 template<OpcodeSize size>
21281 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& getter, VirtualRegister& setter, VirtualRegister& attributes)
21282 {
21283 UNUSED_PARAM(gen);
21284#if OS(WINDOWS) && ENABLE(C_LOOP)
21285 // FIXME: Disable wide16 optimization for Windows CLoop
21286 // https://bugs.webkit.org/show_bug.cgi?id=198283
21287 if (size == OpcodeSize::Wide16)
21288 return false;
21289#endif
21290 return Fits<OpcodeID, size>::check(opcodeID)
21291 && Fits<VirtualRegister, size>::check(base)
21292 && Fits<VirtualRegister, size>::check(property)
21293 && Fits<VirtualRegister, size>::check(getter)
21294 && Fits<VirtualRegister, size>::check(setter)
21295 && Fits<VirtualRegister, size>::check(attributes)
21296 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
21297 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
21298 }
21299
21300 template<OpcodeSize size, bool recordOpcode>
21301 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
21302 {
21303 if (size == OpcodeSize::Wide16)
21304 gen->alignWideOpcode16();
21305 else if (size == OpcodeSize::Wide32)
21306 gen->alignWideOpcode32();
21307 if (checkImpl<size>(gen, base, property, getter, setter, attributes)) {
21308 if (recordOpcode)
21309 gen->recordOpcode(opcodeID);
21310 if (size == OpcodeSize::Wide16)
21311 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
21312 else if (size == OpcodeSize::Wide32)
21313 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
21314 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
21315 gen->write(Fits<VirtualRegister, size>::convert(base));
21316 gen->write(Fits<VirtualRegister, size>::convert(property));
21317 gen->write(Fits<VirtualRegister, size>::convert(getter));
21318 gen->write(Fits<VirtualRegister, size>::convert(setter));
21319 gen->write(Fits<VirtualRegister, size>::convert(attributes));
21320 return true;
21321 }
21322 return false;
21323 }
21324
21325public:
21326 template<typename Block>
21327 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
21328 {
21329 dumper->printLocationAndOp(__location, &"**define_accessor_property"[2 - __sizeShiftAmount]);
21330 dumper->dumpOperand(m_base, true);
21331 dumper->dumpOperand(m_property, false);
21332 dumper->dumpOperand(m_getter, false);
21333 dumper->dumpOperand(m_setter, false);
21334 dumper->dumpOperand(m_attributes, false);
21335 }
21336
21337 OpDefineAccessorProperty(const uint8_t* stream)
21338 : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
21339 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
21340 , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
21341 , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
21342 , m_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
21343 {
21344 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21345 }
21346
21347 OpDefineAccessorProperty(const uint16_t* stream)
21348 : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
21349 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
21350 , m_getter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
21351 , m_setter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
21352 , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
21353 {
21354 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21355 }
21356
21357
21358 OpDefineAccessorProperty(const uint32_t* stream)
21359 : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
21360 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
21361 , m_getter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
21362 , m_setter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
21363 , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
21364 {
21365 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21366 }
21367
21368 static OpDefineAccessorProperty decode(const uint8_t* stream)
21369 {
21370 if (*stream == op_wide32)
21371 return { bitwise_cast<const uint32_t*>(stream + 1) };
21372 if (*stream == op_wide16)
21373 return { bitwise_cast<const uint16_t*>(stream + 1) };
21374 return { stream };
21375 }
21376
21377 template<typename Functor>
21378 void setBase(VirtualRegister value, Functor func)
21379 {
21380 if (isWide32())
21381 setBase<OpcodeSize::Wide32>(value, func);
21382 else if (isWide16())
21383 setBase<OpcodeSize::Wide16>(value, func);
21384 else
21385 setBase<OpcodeSize::Narrow>(value, func);
21386 }
21387
21388 template <OpcodeSize size, typename Functor>
21389 void setBase(VirtualRegister value, Functor func)
21390 {
21391 if (!Fits<VirtualRegister, size>::check(value))
21392 value = func();
21393 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
21394 *stream = Fits<VirtualRegister, size>::convert(value);
21395 }
21396
21397 template<typename Functor>
21398 void setProperty(VirtualRegister value, Functor func)
21399 {
21400 if (isWide32())
21401 setProperty<OpcodeSize::Wide32>(value, func);
21402 else if (isWide16())
21403 setProperty<OpcodeSize::Wide16>(value, func);
21404 else
21405 setProperty<OpcodeSize::Narrow>(value, func);
21406 }
21407
21408 template <OpcodeSize size, typename Functor>
21409 void setProperty(VirtualRegister value, Functor func)
21410 {
21411 if (!Fits<VirtualRegister, size>::check(value))
21412 value = func();
21413 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
21414 *stream = Fits<VirtualRegister, size>::convert(value);
21415 }
21416
21417 template<typename Functor>
21418 void setGetter(VirtualRegister value, Functor func)
21419 {
21420 if (isWide32())
21421 setGetter<OpcodeSize::Wide32>(value, func);
21422 else if (isWide16())
21423 setGetter<OpcodeSize::Wide16>(value, func);
21424 else
21425 setGetter<OpcodeSize::Narrow>(value, func);
21426 }
21427
21428 template <OpcodeSize size, typename Functor>
21429 void setGetter(VirtualRegister value, Functor func)
21430 {
21431 if (!Fits<VirtualRegister, size>::check(value))
21432 value = func();
21433 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
21434 *stream = Fits<VirtualRegister, size>::convert(value);
21435 }
21436
21437 template<typename Functor>
21438 void setSetter(VirtualRegister value, Functor func)
21439 {
21440 if (isWide32())
21441 setSetter<OpcodeSize::Wide32>(value, func);
21442 else if (isWide16())
21443 setSetter<OpcodeSize::Wide16>(value, func);
21444 else
21445 setSetter<OpcodeSize::Narrow>(value, func);
21446 }
21447
21448 template <OpcodeSize size, typename Functor>
21449 void setSetter(VirtualRegister value, Functor func)
21450 {
21451 if (!Fits<VirtualRegister, size>::check(value))
21452 value = func();
21453 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
21454 *stream = Fits<VirtualRegister, size>::convert(value);
21455 }
21456
21457 template<typename Functor>
21458 void setAttributes(VirtualRegister value, Functor func)
21459 {
21460 if (isWide32())
21461 setAttributes<OpcodeSize::Wide32>(value, func);
21462 else if (isWide16())
21463 setAttributes<OpcodeSize::Wide16>(value, func);
21464 else
21465 setAttributes<OpcodeSize::Narrow>(value, func);
21466 }
21467
21468 template <OpcodeSize size, typename Functor>
21469 void setAttributes(VirtualRegister value, Functor func)
21470 {
21471 if (!Fits<VirtualRegister, size>::check(value))
21472 value = func();
21473 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value);
21474 *stream = Fits<VirtualRegister, size>::convert(value);
21475 }
21476
21477 VirtualRegister m_base;
21478 VirtualRegister m_property;
21479 VirtualRegister m_getter;
21480 VirtualRegister m_setter;
21481 VirtualRegister m_attributes;
21482};
21483
21484struct OpJmp : public Instruction {
21485 static constexpr OpcodeID opcodeID = op_jmp;
21486
21487 static void emit(BytecodeGenerator* gen, BoundLabel targetLabel)
21488 {
21489 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, targetLabel);
21490 }
21491
21492 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
21493 static bool emit(BytecodeGenerator* gen, BoundLabel targetLabel)
21494 {
21495 bool didEmit = emitImpl<size, recordOpcode>(gen, targetLabel);
21496 if (shouldAssert == Assert)
21497 ASSERT(didEmit);
21498 return didEmit;
21499 }
21500
21501 template<OpcodeSize size>
21502 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, BoundLabel targetLabel)
21503 {
21504
21505 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
21506 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetLabel))
21507 return;
21508 }
21509 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
21510 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, targetLabel))
21511 return;
21512 }
21513 emit<OpcodeSize::Wide32, Assert, true>(gen, targetLabel);
21514 }
21515
21516private:
21517 template<OpcodeSize size>
21518 static bool checkImpl(BytecodeGenerator* gen, BoundLabel& targetLabel)
21519 {
21520 UNUSED_PARAM(gen);
21521#if OS(WINDOWS) && ENABLE(C_LOOP)
21522 // FIXME: Disable wide16 optimization for Windows CLoop
21523 // https://bugs.webkit.org/show_bug.cgi?id=198283
21524 if (size == OpcodeSize::Wide16)
21525 return false;
21526#endif
21527 return Fits<OpcodeID, size>::check(opcodeID)
21528 && Fits<BoundLabel, size>::check(targetLabel)
21529 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
21530 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
21531 }
21532
21533 template<OpcodeSize size, bool recordOpcode>
21534 static bool emitImpl(BytecodeGenerator* gen, BoundLabel targetLabel)
21535 {
21536 if (size == OpcodeSize::Wide16)
21537 gen->alignWideOpcode16();
21538 else if (size == OpcodeSize::Wide32)
21539 gen->alignWideOpcode32();
21540 if (checkImpl<size>(gen, targetLabel)) {
21541 if (recordOpcode)
21542 gen->recordOpcode(opcodeID);
21543 if (size == OpcodeSize::Wide16)
21544 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
21545 else if (size == OpcodeSize::Wide32)
21546 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
21547 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
21548 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
21549 return true;
21550 }
21551 return false;
21552 }
21553
21554public:
21555 template<typename Block>
21556 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
21557 {
21558 dumper->printLocationAndOp(__location, &"**jmp"[2 - __sizeShiftAmount]);
21559 dumper->dumpOperand(m_targetLabel, true);
21560 }
21561
21562 OpJmp(const uint8_t* stream)
21563 : m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
21564 {
21565 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21566 }
21567
21568 OpJmp(const uint16_t* stream)
21569 : m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
21570 {
21571 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21572 }
21573
21574
21575 OpJmp(const uint32_t* stream)
21576 : m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
21577 {
21578 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21579 }
21580
21581 static OpJmp decode(const uint8_t* stream)
21582 {
21583 if (*stream == op_wide32)
21584 return { bitwise_cast<const uint32_t*>(stream + 1) };
21585 if (*stream == op_wide16)
21586 return { bitwise_cast<const uint16_t*>(stream + 1) };
21587 return { stream };
21588 }
21589
21590 template<typename Functor>
21591 void setTargetLabel(BoundLabel value, Functor func)
21592 {
21593 if (isWide32())
21594 setTargetLabel<OpcodeSize::Wide32>(value, func);
21595 else if (isWide16())
21596 setTargetLabel<OpcodeSize::Wide16>(value, func);
21597 else
21598 setTargetLabel<OpcodeSize::Narrow>(value, func);
21599 }
21600
21601 template <OpcodeSize size, typename Functor>
21602 void setTargetLabel(BoundLabel value, Functor func)
21603 {
21604 if (!Fits<BoundLabel, size>::check(value))
21605 value = func();
21606 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
21607 *stream = Fits<BoundLabel, size>::convert(value);
21608 }
21609
21610 BoundLabel m_targetLabel;
21611};
21612
21613struct OpJtrue : public Instruction {
21614 static constexpr OpcodeID opcodeID = op_jtrue;
21615
21616 static void emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21617 {
21618 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, condition, targetLabel);
21619 }
21620
21621 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
21622 static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21623 {
21624 bool didEmit = emitImpl<size, recordOpcode>(gen, condition, targetLabel);
21625 if (shouldAssert == Assert)
21626 ASSERT(didEmit);
21627 return didEmit;
21628 }
21629
21630 template<OpcodeSize size>
21631 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21632 {
21633
21634 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
21635 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, condition, targetLabel))
21636 return;
21637 }
21638 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
21639 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, condition, targetLabel))
21640 return;
21641 }
21642 emit<OpcodeSize::Wide32, Assert, true>(gen, condition, targetLabel);
21643 }
21644
21645private:
21646 template<OpcodeSize size>
21647 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& condition, BoundLabel& targetLabel)
21648 {
21649 UNUSED_PARAM(gen);
21650#if OS(WINDOWS) && ENABLE(C_LOOP)
21651 // FIXME: Disable wide16 optimization for Windows CLoop
21652 // https://bugs.webkit.org/show_bug.cgi?id=198283
21653 if (size == OpcodeSize::Wide16)
21654 return false;
21655#endif
21656 return Fits<OpcodeID, size>::check(opcodeID)
21657 && Fits<VirtualRegister, size>::check(condition)
21658 && Fits<BoundLabel, size>::check(targetLabel)
21659 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
21660 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
21661 }
21662
21663 template<OpcodeSize size, bool recordOpcode>
21664 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21665 {
21666 if (size == OpcodeSize::Wide16)
21667 gen->alignWideOpcode16();
21668 else if (size == OpcodeSize::Wide32)
21669 gen->alignWideOpcode32();
21670 if (checkImpl<size>(gen, condition, targetLabel)) {
21671 if (recordOpcode)
21672 gen->recordOpcode(opcodeID);
21673 if (size == OpcodeSize::Wide16)
21674 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
21675 else if (size == OpcodeSize::Wide32)
21676 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
21677 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
21678 gen->write(Fits<VirtualRegister, size>::convert(condition));
21679 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
21680 return true;
21681 }
21682 return false;
21683 }
21684
21685public:
21686 template<typename Block>
21687 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
21688 {
21689 dumper->printLocationAndOp(__location, &"**jtrue"[2 - __sizeShiftAmount]);
21690 dumper->dumpOperand(m_condition, true);
21691 dumper->dumpOperand(m_targetLabel, false);
21692 }
21693
21694 OpJtrue(const uint8_t* stream)
21695 : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
21696 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
21697 {
21698 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21699 }
21700
21701 OpJtrue(const uint16_t* stream)
21702 : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
21703 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
21704 {
21705 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21706 }
21707
21708
21709 OpJtrue(const uint32_t* stream)
21710 : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
21711 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
21712 {
21713 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21714 }
21715
21716 static OpJtrue decode(const uint8_t* stream)
21717 {
21718 if (*stream == op_wide32)
21719 return { bitwise_cast<const uint32_t*>(stream + 1) };
21720 if (*stream == op_wide16)
21721 return { bitwise_cast<const uint16_t*>(stream + 1) };
21722 return { stream };
21723 }
21724
21725 template<typename Functor>
21726 void setCondition(VirtualRegister value, Functor func)
21727 {
21728 if (isWide32())
21729 setCondition<OpcodeSize::Wide32>(value, func);
21730 else if (isWide16())
21731 setCondition<OpcodeSize::Wide16>(value, func);
21732 else
21733 setCondition<OpcodeSize::Narrow>(value, func);
21734 }
21735
21736 template <OpcodeSize size, typename Functor>
21737 void setCondition(VirtualRegister value, Functor func)
21738 {
21739 if (!Fits<VirtualRegister, size>::check(value))
21740 value = func();
21741 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
21742 *stream = Fits<VirtualRegister, size>::convert(value);
21743 }
21744
21745 template<typename Functor>
21746 void setTargetLabel(BoundLabel value, Functor func)
21747 {
21748 if (isWide32())
21749 setTargetLabel<OpcodeSize::Wide32>(value, func);
21750 else if (isWide16())
21751 setTargetLabel<OpcodeSize::Wide16>(value, func);
21752 else
21753 setTargetLabel<OpcodeSize::Narrow>(value, func);
21754 }
21755
21756 template <OpcodeSize size, typename Functor>
21757 void setTargetLabel(BoundLabel value, Functor func)
21758 {
21759 if (!Fits<BoundLabel, size>::check(value))
21760 value = func();
21761 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
21762 *stream = Fits<BoundLabel, size>::convert(value);
21763 }
21764
21765 VirtualRegister m_condition;
21766 BoundLabel m_targetLabel;
21767};
21768
21769struct OpJfalse : public Instruction {
21770 static constexpr OpcodeID opcodeID = op_jfalse;
21771
21772 static void emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21773 {
21774 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, condition, targetLabel);
21775 }
21776
21777 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
21778 static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21779 {
21780 bool didEmit = emitImpl<size, recordOpcode>(gen, condition, targetLabel);
21781 if (shouldAssert == Assert)
21782 ASSERT(didEmit);
21783 return didEmit;
21784 }
21785
21786 template<OpcodeSize size>
21787 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21788 {
21789
21790 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
21791 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, condition, targetLabel))
21792 return;
21793 }
21794 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
21795 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, condition, targetLabel))
21796 return;
21797 }
21798 emit<OpcodeSize::Wide32, Assert, true>(gen, condition, targetLabel);
21799 }
21800
21801private:
21802 template<OpcodeSize size>
21803 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& condition, BoundLabel& targetLabel)
21804 {
21805 UNUSED_PARAM(gen);
21806#if OS(WINDOWS) && ENABLE(C_LOOP)
21807 // FIXME: Disable wide16 optimization for Windows CLoop
21808 // https://bugs.webkit.org/show_bug.cgi?id=198283
21809 if (size == OpcodeSize::Wide16)
21810 return false;
21811#endif
21812 return Fits<OpcodeID, size>::check(opcodeID)
21813 && Fits<VirtualRegister, size>::check(condition)
21814 && Fits<BoundLabel, size>::check(targetLabel)
21815 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
21816 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
21817 }
21818
21819 template<OpcodeSize size, bool recordOpcode>
21820 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
21821 {
21822 if (size == OpcodeSize::Wide16)
21823 gen->alignWideOpcode16();
21824 else if (size == OpcodeSize::Wide32)
21825 gen->alignWideOpcode32();
21826 if (checkImpl<size>(gen, condition, targetLabel)) {
21827 if (recordOpcode)
21828 gen->recordOpcode(opcodeID);
21829 if (size == OpcodeSize::Wide16)
21830 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
21831 else if (size == OpcodeSize::Wide32)
21832 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
21833 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
21834 gen->write(Fits<VirtualRegister, size>::convert(condition));
21835 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
21836 return true;
21837 }
21838 return false;
21839 }
21840
21841public:
21842 template<typename Block>
21843 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
21844 {
21845 dumper->printLocationAndOp(__location, &"**jfalse"[2 - __sizeShiftAmount]);
21846 dumper->dumpOperand(m_condition, true);
21847 dumper->dumpOperand(m_targetLabel, false);
21848 }
21849
21850 OpJfalse(const uint8_t* stream)
21851 : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
21852 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
21853 {
21854 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21855 }
21856
21857 OpJfalse(const uint16_t* stream)
21858 : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
21859 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
21860 {
21861 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21862 }
21863
21864
21865 OpJfalse(const uint32_t* stream)
21866 : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
21867 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
21868 {
21869 ASSERT_UNUSED(stream, stream[0] == opcodeID);
21870 }
21871
21872 static OpJfalse decode(const uint8_t* stream)
21873 {
21874 if (*stream == op_wide32)
21875 return { bitwise_cast<const uint32_t*>(stream + 1) };
21876 if (*stream == op_wide16)
21877 return { bitwise_cast<const uint16_t*>(stream + 1) };
21878 return { stream };
21879 }
21880
21881 template<typename Functor>
21882 void setCondition(VirtualRegister value, Functor func)
21883 {
21884 if (isWide32())
21885 setCondition<OpcodeSize::Wide32>(value, func);
21886 else if (isWide16())
21887 setCondition<OpcodeSize::Wide16>(value, func);
21888 else
21889 setCondition<OpcodeSize::Narrow>(value, func);
21890 }
21891
21892 template <OpcodeSize size, typename Functor>
21893 void setCondition(VirtualRegister value, Functor func)
21894 {
21895 if (!Fits<VirtualRegister, size>::check(value))
21896 value = func();
21897 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
21898 *stream = Fits<VirtualRegister, size>::convert(value);
21899 }
21900
21901 template<typename Functor>
21902 void setTargetLabel(BoundLabel value, Functor func)
21903 {
21904 if (isWide32())
21905 setTargetLabel<OpcodeSize::Wide32>(value, func);
21906 else if (isWide16())
21907 setTargetLabel<OpcodeSize::Wide16>(value, func);
21908 else
21909 setTargetLabel<OpcodeSize::Narrow>(value, func);
21910 }
21911
21912 template <OpcodeSize size, typename Functor>
21913 void setTargetLabel(BoundLabel value, Functor func)
21914 {
21915 if (!Fits<BoundLabel, size>::check(value))
21916 value = func();
21917 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
21918 *stream = Fits<BoundLabel, size>::convert(value);
21919 }
21920
21921 VirtualRegister m_condition;
21922 BoundLabel m_targetLabel;
21923};
21924
21925struct OpJeqNull : public Instruction {
21926 static constexpr OpcodeID opcodeID = op_jeq_null;
21927
21928 static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
21929 {
21930 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, value, targetLabel);
21931 }
21932
21933 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
21934 static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
21935 {
21936 bool didEmit = emitImpl<size, recordOpcode>(gen, value, targetLabel);
21937 if (shouldAssert == Assert)
21938 ASSERT(didEmit);
21939 return didEmit;
21940 }
21941
21942 template<OpcodeSize size>
21943 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
21944 {
21945
21946 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
21947 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, targetLabel))
21948 return;
21949 }
21950 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
21951 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value, targetLabel))
21952 return;
21953 }
21954 emit<OpcodeSize::Wide32, Assert, true>(gen, value, targetLabel);
21955 }
21956
21957private:
21958 template<OpcodeSize size>
21959 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, BoundLabel& targetLabel)
21960 {
21961 UNUSED_PARAM(gen);
21962#if OS(WINDOWS) && ENABLE(C_LOOP)
21963 // FIXME: Disable wide16 optimization for Windows CLoop
21964 // https://bugs.webkit.org/show_bug.cgi?id=198283
21965 if (size == OpcodeSize::Wide16)
21966 return false;
21967#endif
21968 return Fits<OpcodeID, size>::check(opcodeID)
21969 && Fits<VirtualRegister, size>::check(value)
21970 && Fits<BoundLabel, size>::check(targetLabel)
21971 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
21972 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
21973 }
21974
21975 template<OpcodeSize size, bool recordOpcode>
21976 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
21977 {
21978 if (size == OpcodeSize::Wide16)
21979 gen->alignWideOpcode16();
21980 else if (size == OpcodeSize::Wide32)
21981 gen->alignWideOpcode32();
21982 if (checkImpl<size>(gen, value, targetLabel)) {
21983 if (recordOpcode)
21984 gen->recordOpcode(opcodeID);
21985 if (size == OpcodeSize::Wide16)
21986 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
21987 else if (size == OpcodeSize::Wide32)
21988 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
21989 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
21990 gen->write(Fits<VirtualRegister, size>::convert(value));
21991 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
21992 return true;
21993 }
21994 return false;
21995 }
21996
21997public:
21998 template<typename Block>
21999 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
22000 {
22001 dumper->printLocationAndOp(__location, &"**jeq_null"[2 - __sizeShiftAmount]);
22002 dumper->dumpOperand(m_value, true);
22003 dumper->dumpOperand(m_targetLabel, false);
22004 }
22005
22006 OpJeqNull(const uint8_t* stream)
22007 : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
22008 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
22009 {
22010 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22011 }
22012
22013 OpJeqNull(const uint16_t* stream)
22014 : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
22015 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
22016 {
22017 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22018 }
22019
22020
22021 OpJeqNull(const uint32_t* stream)
22022 : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
22023 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
22024 {
22025 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22026 }
22027
22028 static OpJeqNull decode(const uint8_t* stream)
22029 {
22030 if (*stream == op_wide32)
22031 return { bitwise_cast<const uint32_t*>(stream + 1) };
22032 if (*stream == op_wide16)
22033 return { bitwise_cast<const uint16_t*>(stream + 1) };
22034 return { stream };
22035 }
22036
22037 template<typename Functor>
22038 void setValue(VirtualRegister value, Functor func)
22039 {
22040 if (isWide32())
22041 setValue<OpcodeSize::Wide32>(value, func);
22042 else if (isWide16())
22043 setValue<OpcodeSize::Wide16>(value, func);
22044 else
22045 setValue<OpcodeSize::Narrow>(value, func);
22046 }
22047
22048 template <OpcodeSize size, typename Functor>
22049 void setValue(VirtualRegister value, Functor func)
22050 {
22051 if (!Fits<VirtualRegister, size>::check(value))
22052 value = func();
22053 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
22054 *stream = Fits<VirtualRegister, size>::convert(value);
22055 }
22056
22057 template<typename Functor>
22058 void setTargetLabel(BoundLabel value, Functor func)
22059 {
22060 if (isWide32())
22061 setTargetLabel<OpcodeSize::Wide32>(value, func);
22062 else if (isWide16())
22063 setTargetLabel<OpcodeSize::Wide16>(value, func);
22064 else
22065 setTargetLabel<OpcodeSize::Narrow>(value, func);
22066 }
22067
22068 template <OpcodeSize size, typename Functor>
22069 void setTargetLabel(BoundLabel value, Functor func)
22070 {
22071 if (!Fits<BoundLabel, size>::check(value))
22072 value = func();
22073 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
22074 *stream = Fits<BoundLabel, size>::convert(value);
22075 }
22076
22077 VirtualRegister m_value;
22078 BoundLabel m_targetLabel;
22079};
22080
22081struct OpJneqNull : public Instruction {
22082 static constexpr OpcodeID opcodeID = op_jneq_null;
22083
22084 static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
22085 {
22086 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, value, targetLabel);
22087 }
22088
22089 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
22090 static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
22091 {
22092 bool didEmit = emitImpl<size, recordOpcode>(gen, value, targetLabel);
22093 if (shouldAssert == Assert)
22094 ASSERT(didEmit);
22095 return didEmit;
22096 }
22097
22098 template<OpcodeSize size>
22099 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
22100 {
22101
22102 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
22103 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, targetLabel))
22104 return;
22105 }
22106 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
22107 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value, targetLabel))
22108 return;
22109 }
22110 emit<OpcodeSize::Wide32, Assert, true>(gen, value, targetLabel);
22111 }
22112
22113private:
22114 template<OpcodeSize size>
22115 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, BoundLabel& targetLabel)
22116 {
22117 UNUSED_PARAM(gen);
22118#if OS(WINDOWS) && ENABLE(C_LOOP)
22119 // FIXME: Disable wide16 optimization for Windows CLoop
22120 // https://bugs.webkit.org/show_bug.cgi?id=198283
22121 if (size == OpcodeSize::Wide16)
22122 return false;
22123#endif
22124 return Fits<OpcodeID, size>::check(opcodeID)
22125 && Fits<VirtualRegister, size>::check(value)
22126 && Fits<BoundLabel, size>::check(targetLabel)
22127 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
22128 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
22129 }
22130
22131 template<OpcodeSize size, bool recordOpcode>
22132 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
22133 {
22134 if (size == OpcodeSize::Wide16)
22135 gen->alignWideOpcode16();
22136 else if (size == OpcodeSize::Wide32)
22137 gen->alignWideOpcode32();
22138 if (checkImpl<size>(gen, value, targetLabel)) {
22139 if (recordOpcode)
22140 gen->recordOpcode(opcodeID);
22141 if (size == OpcodeSize::Wide16)
22142 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
22143 else if (size == OpcodeSize::Wide32)
22144 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
22145 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
22146 gen->write(Fits<VirtualRegister, size>::convert(value));
22147 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
22148 return true;
22149 }
22150 return false;
22151 }
22152
22153public:
22154 template<typename Block>
22155 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
22156 {
22157 dumper->printLocationAndOp(__location, &"**jneq_null"[2 - __sizeShiftAmount]);
22158 dumper->dumpOperand(m_value, true);
22159 dumper->dumpOperand(m_targetLabel, false);
22160 }
22161
22162 OpJneqNull(const uint8_t* stream)
22163 : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
22164 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
22165 {
22166 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22167 }
22168
22169 OpJneqNull(const uint16_t* stream)
22170 : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
22171 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
22172 {
22173 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22174 }
22175
22176
22177 OpJneqNull(const uint32_t* stream)
22178 : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
22179 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
22180 {
22181 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22182 }
22183
22184 static OpJneqNull decode(const uint8_t* stream)
22185 {
22186 if (*stream == op_wide32)
22187 return { bitwise_cast<const uint32_t*>(stream + 1) };
22188 if (*stream == op_wide16)
22189 return { bitwise_cast<const uint16_t*>(stream + 1) };
22190 return { stream };
22191 }
22192
22193 template<typename Functor>
22194 void setValue(VirtualRegister value, Functor func)
22195 {
22196 if (isWide32())
22197 setValue<OpcodeSize::Wide32>(value, func);
22198 else if (isWide16())
22199 setValue<OpcodeSize::Wide16>(value, func);
22200 else
22201 setValue<OpcodeSize::Narrow>(value, func);
22202 }
22203
22204 template <OpcodeSize size, typename Functor>
22205 void setValue(VirtualRegister value, Functor func)
22206 {
22207 if (!Fits<VirtualRegister, size>::check(value))
22208 value = func();
22209 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
22210 *stream = Fits<VirtualRegister, size>::convert(value);
22211 }
22212
22213 template<typename Functor>
22214 void setTargetLabel(BoundLabel value, Functor func)
22215 {
22216 if (isWide32())
22217 setTargetLabel<OpcodeSize::Wide32>(value, func);
22218 else if (isWide16())
22219 setTargetLabel<OpcodeSize::Wide16>(value, func);
22220 else
22221 setTargetLabel<OpcodeSize::Narrow>(value, func);
22222 }
22223
22224 template <OpcodeSize size, typename Functor>
22225 void setTargetLabel(BoundLabel value, Functor func)
22226 {
22227 if (!Fits<BoundLabel, size>::check(value))
22228 value = func();
22229 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
22230 *stream = Fits<BoundLabel, size>::convert(value);
22231 }
22232
22233 VirtualRegister m_value;
22234 BoundLabel m_targetLabel;
22235};
22236
22237struct OpJeq : public Instruction {
22238 static constexpr OpcodeID opcodeID = op_jeq;
22239
22240 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22241 {
22242 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
22243 }
22244
22245 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
22246 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22247 {
22248 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
22249 if (shouldAssert == Assert)
22250 ASSERT(didEmit);
22251 return didEmit;
22252 }
22253
22254 template<OpcodeSize size>
22255 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22256 {
22257
22258 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
22259 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
22260 return;
22261 }
22262 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
22263 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
22264 return;
22265 }
22266 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
22267 }
22268
22269private:
22270 template<OpcodeSize size>
22271 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
22272 {
22273 UNUSED_PARAM(gen);
22274#if OS(WINDOWS) && ENABLE(C_LOOP)
22275 // FIXME: Disable wide16 optimization for Windows CLoop
22276 // https://bugs.webkit.org/show_bug.cgi?id=198283
22277 if (size == OpcodeSize::Wide16)
22278 return false;
22279#endif
22280 return Fits<OpcodeID, size>::check(opcodeID)
22281 && Fits<VirtualRegister, size>::check(lhs)
22282 && Fits<VirtualRegister, size>::check(rhs)
22283 && Fits<BoundLabel, size>::check(targetLabel)
22284 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
22285 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
22286 }
22287
22288 template<OpcodeSize size, bool recordOpcode>
22289 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22290 {
22291 if (size == OpcodeSize::Wide16)
22292 gen->alignWideOpcode16();
22293 else if (size == OpcodeSize::Wide32)
22294 gen->alignWideOpcode32();
22295 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
22296 if (recordOpcode)
22297 gen->recordOpcode(opcodeID);
22298 if (size == OpcodeSize::Wide16)
22299 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
22300 else if (size == OpcodeSize::Wide32)
22301 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
22302 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
22303 gen->write(Fits<VirtualRegister, size>::convert(lhs));
22304 gen->write(Fits<VirtualRegister, size>::convert(rhs));
22305 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
22306 return true;
22307 }
22308 return false;
22309 }
22310
22311public:
22312 template<typename Block>
22313 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
22314 {
22315 dumper->printLocationAndOp(__location, &"**jeq"[2 - __sizeShiftAmount]);
22316 dumper->dumpOperand(m_lhs, true);
22317 dumper->dumpOperand(m_rhs, false);
22318 dumper->dumpOperand(m_targetLabel, false);
22319 }
22320
22321 OpJeq(const uint8_t* stream)
22322 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
22323 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
22324 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
22325 {
22326 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22327 }
22328
22329 OpJeq(const uint16_t* stream)
22330 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
22331 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
22332 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
22333 {
22334 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22335 }
22336
22337
22338 OpJeq(const uint32_t* stream)
22339 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
22340 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
22341 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
22342 {
22343 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22344 }
22345
22346 static OpJeq decode(const uint8_t* stream)
22347 {
22348 if (*stream == op_wide32)
22349 return { bitwise_cast<const uint32_t*>(stream + 1) };
22350 if (*stream == op_wide16)
22351 return { bitwise_cast<const uint16_t*>(stream + 1) };
22352 return { stream };
22353 }
22354
22355 template<typename Functor>
22356 void setLhs(VirtualRegister value, Functor func)
22357 {
22358 if (isWide32())
22359 setLhs<OpcodeSize::Wide32>(value, func);
22360 else if (isWide16())
22361 setLhs<OpcodeSize::Wide16>(value, func);
22362 else
22363 setLhs<OpcodeSize::Narrow>(value, func);
22364 }
22365
22366 template <OpcodeSize size, typename Functor>
22367 void setLhs(VirtualRegister value, Functor func)
22368 {
22369 if (!Fits<VirtualRegister, size>::check(value))
22370 value = func();
22371 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
22372 *stream = Fits<VirtualRegister, size>::convert(value);
22373 }
22374
22375 template<typename Functor>
22376 void setRhs(VirtualRegister value, Functor func)
22377 {
22378 if (isWide32())
22379 setRhs<OpcodeSize::Wide32>(value, func);
22380 else if (isWide16())
22381 setRhs<OpcodeSize::Wide16>(value, func);
22382 else
22383 setRhs<OpcodeSize::Narrow>(value, func);
22384 }
22385
22386 template <OpcodeSize size, typename Functor>
22387 void setRhs(VirtualRegister value, Functor func)
22388 {
22389 if (!Fits<VirtualRegister, size>::check(value))
22390 value = func();
22391 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
22392 *stream = Fits<VirtualRegister, size>::convert(value);
22393 }
22394
22395 template<typename Functor>
22396 void setTargetLabel(BoundLabel value, Functor func)
22397 {
22398 if (isWide32())
22399 setTargetLabel<OpcodeSize::Wide32>(value, func);
22400 else if (isWide16())
22401 setTargetLabel<OpcodeSize::Wide16>(value, func);
22402 else
22403 setTargetLabel<OpcodeSize::Narrow>(value, func);
22404 }
22405
22406 template <OpcodeSize size, typename Functor>
22407 void setTargetLabel(BoundLabel value, Functor func)
22408 {
22409 if (!Fits<BoundLabel, size>::check(value))
22410 value = func();
22411 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
22412 *stream = Fits<BoundLabel, size>::convert(value);
22413 }
22414
22415 VirtualRegister m_lhs;
22416 VirtualRegister m_rhs;
22417 BoundLabel m_targetLabel;
22418};
22419
22420struct OpJstricteq : public Instruction {
22421 static constexpr OpcodeID opcodeID = op_jstricteq;
22422
22423 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22424 {
22425 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
22426 }
22427
22428 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
22429 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22430 {
22431 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
22432 if (shouldAssert == Assert)
22433 ASSERT(didEmit);
22434 return didEmit;
22435 }
22436
22437 template<OpcodeSize size>
22438 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22439 {
22440
22441 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
22442 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
22443 return;
22444 }
22445 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
22446 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
22447 return;
22448 }
22449 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
22450 }
22451
22452private:
22453 template<OpcodeSize size>
22454 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
22455 {
22456 UNUSED_PARAM(gen);
22457#if OS(WINDOWS) && ENABLE(C_LOOP)
22458 // FIXME: Disable wide16 optimization for Windows CLoop
22459 // https://bugs.webkit.org/show_bug.cgi?id=198283
22460 if (size == OpcodeSize::Wide16)
22461 return false;
22462#endif
22463 return Fits<OpcodeID, size>::check(opcodeID)
22464 && Fits<VirtualRegister, size>::check(lhs)
22465 && Fits<VirtualRegister, size>::check(rhs)
22466 && Fits<BoundLabel, size>::check(targetLabel)
22467 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
22468 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
22469 }
22470
22471 template<OpcodeSize size, bool recordOpcode>
22472 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22473 {
22474 if (size == OpcodeSize::Wide16)
22475 gen->alignWideOpcode16();
22476 else if (size == OpcodeSize::Wide32)
22477 gen->alignWideOpcode32();
22478 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
22479 if (recordOpcode)
22480 gen->recordOpcode(opcodeID);
22481 if (size == OpcodeSize::Wide16)
22482 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
22483 else if (size == OpcodeSize::Wide32)
22484 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
22485 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
22486 gen->write(Fits<VirtualRegister, size>::convert(lhs));
22487 gen->write(Fits<VirtualRegister, size>::convert(rhs));
22488 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
22489 return true;
22490 }
22491 return false;
22492 }
22493
22494public:
22495 template<typename Block>
22496 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
22497 {
22498 dumper->printLocationAndOp(__location, &"**jstricteq"[2 - __sizeShiftAmount]);
22499 dumper->dumpOperand(m_lhs, true);
22500 dumper->dumpOperand(m_rhs, false);
22501 dumper->dumpOperand(m_targetLabel, false);
22502 }
22503
22504 OpJstricteq(const uint8_t* stream)
22505 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
22506 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
22507 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
22508 {
22509 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22510 }
22511
22512 OpJstricteq(const uint16_t* stream)
22513 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
22514 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
22515 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
22516 {
22517 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22518 }
22519
22520
22521 OpJstricteq(const uint32_t* stream)
22522 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
22523 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
22524 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
22525 {
22526 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22527 }
22528
22529 static OpJstricteq decode(const uint8_t* stream)
22530 {
22531 if (*stream == op_wide32)
22532 return { bitwise_cast<const uint32_t*>(stream + 1) };
22533 if (*stream == op_wide16)
22534 return { bitwise_cast<const uint16_t*>(stream + 1) };
22535 return { stream };
22536 }
22537
22538 template<typename Functor>
22539 void setLhs(VirtualRegister value, Functor func)
22540 {
22541 if (isWide32())
22542 setLhs<OpcodeSize::Wide32>(value, func);
22543 else if (isWide16())
22544 setLhs<OpcodeSize::Wide16>(value, func);
22545 else
22546 setLhs<OpcodeSize::Narrow>(value, func);
22547 }
22548
22549 template <OpcodeSize size, typename Functor>
22550 void setLhs(VirtualRegister value, Functor func)
22551 {
22552 if (!Fits<VirtualRegister, size>::check(value))
22553 value = func();
22554 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
22555 *stream = Fits<VirtualRegister, size>::convert(value);
22556 }
22557
22558 template<typename Functor>
22559 void setRhs(VirtualRegister value, Functor func)
22560 {
22561 if (isWide32())
22562 setRhs<OpcodeSize::Wide32>(value, func);
22563 else if (isWide16())
22564 setRhs<OpcodeSize::Wide16>(value, func);
22565 else
22566 setRhs<OpcodeSize::Narrow>(value, func);
22567 }
22568
22569 template <OpcodeSize size, typename Functor>
22570 void setRhs(VirtualRegister value, Functor func)
22571 {
22572 if (!Fits<VirtualRegister, size>::check(value))
22573 value = func();
22574 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
22575 *stream = Fits<VirtualRegister, size>::convert(value);
22576 }
22577
22578 template<typename Functor>
22579 void setTargetLabel(BoundLabel value, Functor func)
22580 {
22581 if (isWide32())
22582 setTargetLabel<OpcodeSize::Wide32>(value, func);
22583 else if (isWide16())
22584 setTargetLabel<OpcodeSize::Wide16>(value, func);
22585 else
22586 setTargetLabel<OpcodeSize::Narrow>(value, func);
22587 }
22588
22589 template <OpcodeSize size, typename Functor>
22590 void setTargetLabel(BoundLabel value, Functor func)
22591 {
22592 if (!Fits<BoundLabel, size>::check(value))
22593 value = func();
22594 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
22595 *stream = Fits<BoundLabel, size>::convert(value);
22596 }
22597
22598 VirtualRegister m_lhs;
22599 VirtualRegister m_rhs;
22600 BoundLabel m_targetLabel;
22601};
22602
22603struct OpJneq : public Instruction {
22604 static constexpr OpcodeID opcodeID = op_jneq;
22605
22606 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22607 {
22608 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
22609 }
22610
22611 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
22612 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22613 {
22614 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
22615 if (shouldAssert == Assert)
22616 ASSERT(didEmit);
22617 return didEmit;
22618 }
22619
22620 template<OpcodeSize size>
22621 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22622 {
22623
22624 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
22625 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
22626 return;
22627 }
22628 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
22629 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
22630 return;
22631 }
22632 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
22633 }
22634
22635private:
22636 template<OpcodeSize size>
22637 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
22638 {
22639 UNUSED_PARAM(gen);
22640#if OS(WINDOWS) && ENABLE(C_LOOP)
22641 // FIXME: Disable wide16 optimization for Windows CLoop
22642 // https://bugs.webkit.org/show_bug.cgi?id=198283
22643 if (size == OpcodeSize::Wide16)
22644 return false;
22645#endif
22646 return Fits<OpcodeID, size>::check(opcodeID)
22647 && Fits<VirtualRegister, size>::check(lhs)
22648 && Fits<VirtualRegister, size>::check(rhs)
22649 && Fits<BoundLabel, size>::check(targetLabel)
22650 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
22651 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
22652 }
22653
22654 template<OpcodeSize size, bool recordOpcode>
22655 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22656 {
22657 if (size == OpcodeSize::Wide16)
22658 gen->alignWideOpcode16();
22659 else if (size == OpcodeSize::Wide32)
22660 gen->alignWideOpcode32();
22661 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
22662 if (recordOpcode)
22663 gen->recordOpcode(opcodeID);
22664 if (size == OpcodeSize::Wide16)
22665 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
22666 else if (size == OpcodeSize::Wide32)
22667 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
22668 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
22669 gen->write(Fits<VirtualRegister, size>::convert(lhs));
22670 gen->write(Fits<VirtualRegister, size>::convert(rhs));
22671 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
22672 return true;
22673 }
22674 return false;
22675 }
22676
22677public:
22678 template<typename Block>
22679 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
22680 {
22681 dumper->printLocationAndOp(__location, &"**jneq"[2 - __sizeShiftAmount]);
22682 dumper->dumpOperand(m_lhs, true);
22683 dumper->dumpOperand(m_rhs, false);
22684 dumper->dumpOperand(m_targetLabel, false);
22685 }
22686
22687 OpJneq(const uint8_t* stream)
22688 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
22689 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
22690 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
22691 {
22692 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22693 }
22694
22695 OpJneq(const uint16_t* stream)
22696 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
22697 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
22698 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
22699 {
22700 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22701 }
22702
22703
22704 OpJneq(const uint32_t* stream)
22705 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
22706 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
22707 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
22708 {
22709 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22710 }
22711
22712 static OpJneq decode(const uint8_t* stream)
22713 {
22714 if (*stream == op_wide32)
22715 return { bitwise_cast<const uint32_t*>(stream + 1) };
22716 if (*stream == op_wide16)
22717 return { bitwise_cast<const uint16_t*>(stream + 1) };
22718 return { stream };
22719 }
22720
22721 template<typename Functor>
22722 void setLhs(VirtualRegister value, Functor func)
22723 {
22724 if (isWide32())
22725 setLhs<OpcodeSize::Wide32>(value, func);
22726 else if (isWide16())
22727 setLhs<OpcodeSize::Wide16>(value, func);
22728 else
22729 setLhs<OpcodeSize::Narrow>(value, func);
22730 }
22731
22732 template <OpcodeSize size, typename Functor>
22733 void setLhs(VirtualRegister value, Functor func)
22734 {
22735 if (!Fits<VirtualRegister, size>::check(value))
22736 value = func();
22737 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
22738 *stream = Fits<VirtualRegister, size>::convert(value);
22739 }
22740
22741 template<typename Functor>
22742 void setRhs(VirtualRegister value, Functor func)
22743 {
22744 if (isWide32())
22745 setRhs<OpcodeSize::Wide32>(value, func);
22746 else if (isWide16())
22747 setRhs<OpcodeSize::Wide16>(value, func);
22748 else
22749 setRhs<OpcodeSize::Narrow>(value, func);
22750 }
22751
22752 template <OpcodeSize size, typename Functor>
22753 void setRhs(VirtualRegister value, Functor func)
22754 {
22755 if (!Fits<VirtualRegister, size>::check(value))
22756 value = func();
22757 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
22758 *stream = Fits<VirtualRegister, size>::convert(value);
22759 }
22760
22761 template<typename Functor>
22762 void setTargetLabel(BoundLabel value, Functor func)
22763 {
22764 if (isWide32())
22765 setTargetLabel<OpcodeSize::Wide32>(value, func);
22766 else if (isWide16())
22767 setTargetLabel<OpcodeSize::Wide16>(value, func);
22768 else
22769 setTargetLabel<OpcodeSize::Narrow>(value, func);
22770 }
22771
22772 template <OpcodeSize size, typename Functor>
22773 void setTargetLabel(BoundLabel value, Functor func)
22774 {
22775 if (!Fits<BoundLabel, size>::check(value))
22776 value = func();
22777 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
22778 *stream = Fits<BoundLabel, size>::convert(value);
22779 }
22780
22781 VirtualRegister m_lhs;
22782 VirtualRegister m_rhs;
22783 BoundLabel m_targetLabel;
22784};
22785
22786struct OpJnstricteq : public Instruction {
22787 static constexpr OpcodeID opcodeID = op_jnstricteq;
22788
22789 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22790 {
22791 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
22792 }
22793
22794 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
22795 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22796 {
22797 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
22798 if (shouldAssert == Assert)
22799 ASSERT(didEmit);
22800 return didEmit;
22801 }
22802
22803 template<OpcodeSize size>
22804 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22805 {
22806
22807 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
22808 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
22809 return;
22810 }
22811 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
22812 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
22813 return;
22814 }
22815 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
22816 }
22817
22818private:
22819 template<OpcodeSize size>
22820 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
22821 {
22822 UNUSED_PARAM(gen);
22823#if OS(WINDOWS) && ENABLE(C_LOOP)
22824 // FIXME: Disable wide16 optimization for Windows CLoop
22825 // https://bugs.webkit.org/show_bug.cgi?id=198283
22826 if (size == OpcodeSize::Wide16)
22827 return false;
22828#endif
22829 return Fits<OpcodeID, size>::check(opcodeID)
22830 && Fits<VirtualRegister, size>::check(lhs)
22831 && Fits<VirtualRegister, size>::check(rhs)
22832 && Fits<BoundLabel, size>::check(targetLabel)
22833 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
22834 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
22835 }
22836
22837 template<OpcodeSize size, bool recordOpcode>
22838 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22839 {
22840 if (size == OpcodeSize::Wide16)
22841 gen->alignWideOpcode16();
22842 else if (size == OpcodeSize::Wide32)
22843 gen->alignWideOpcode32();
22844 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
22845 if (recordOpcode)
22846 gen->recordOpcode(opcodeID);
22847 if (size == OpcodeSize::Wide16)
22848 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
22849 else if (size == OpcodeSize::Wide32)
22850 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
22851 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
22852 gen->write(Fits<VirtualRegister, size>::convert(lhs));
22853 gen->write(Fits<VirtualRegister, size>::convert(rhs));
22854 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
22855 return true;
22856 }
22857 return false;
22858 }
22859
22860public:
22861 template<typename Block>
22862 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
22863 {
22864 dumper->printLocationAndOp(__location, &"**jnstricteq"[2 - __sizeShiftAmount]);
22865 dumper->dumpOperand(m_lhs, true);
22866 dumper->dumpOperand(m_rhs, false);
22867 dumper->dumpOperand(m_targetLabel, false);
22868 }
22869
22870 OpJnstricteq(const uint8_t* stream)
22871 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
22872 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
22873 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
22874 {
22875 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22876 }
22877
22878 OpJnstricteq(const uint16_t* stream)
22879 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
22880 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
22881 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
22882 {
22883 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22884 }
22885
22886
22887 OpJnstricteq(const uint32_t* stream)
22888 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
22889 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
22890 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
22891 {
22892 ASSERT_UNUSED(stream, stream[0] == opcodeID);
22893 }
22894
22895 static OpJnstricteq decode(const uint8_t* stream)
22896 {
22897 if (*stream == op_wide32)
22898 return { bitwise_cast<const uint32_t*>(stream + 1) };
22899 if (*stream == op_wide16)
22900 return { bitwise_cast<const uint16_t*>(stream + 1) };
22901 return { stream };
22902 }
22903
22904 template<typename Functor>
22905 void setLhs(VirtualRegister value, Functor func)
22906 {
22907 if (isWide32())
22908 setLhs<OpcodeSize::Wide32>(value, func);
22909 else if (isWide16())
22910 setLhs<OpcodeSize::Wide16>(value, func);
22911 else
22912 setLhs<OpcodeSize::Narrow>(value, func);
22913 }
22914
22915 template <OpcodeSize size, typename Functor>
22916 void setLhs(VirtualRegister value, Functor func)
22917 {
22918 if (!Fits<VirtualRegister, size>::check(value))
22919 value = func();
22920 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
22921 *stream = Fits<VirtualRegister, size>::convert(value);
22922 }
22923
22924 template<typename Functor>
22925 void setRhs(VirtualRegister value, Functor func)
22926 {
22927 if (isWide32())
22928 setRhs<OpcodeSize::Wide32>(value, func);
22929 else if (isWide16())
22930 setRhs<OpcodeSize::Wide16>(value, func);
22931 else
22932 setRhs<OpcodeSize::Narrow>(value, func);
22933 }
22934
22935 template <OpcodeSize size, typename Functor>
22936 void setRhs(VirtualRegister value, Functor func)
22937 {
22938 if (!Fits<VirtualRegister, size>::check(value))
22939 value = func();
22940 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
22941 *stream = Fits<VirtualRegister, size>::convert(value);
22942 }
22943
22944 template<typename Functor>
22945 void setTargetLabel(BoundLabel value, Functor func)
22946 {
22947 if (isWide32())
22948 setTargetLabel<OpcodeSize::Wide32>(value, func);
22949 else if (isWide16())
22950 setTargetLabel<OpcodeSize::Wide16>(value, func);
22951 else
22952 setTargetLabel<OpcodeSize::Narrow>(value, func);
22953 }
22954
22955 template <OpcodeSize size, typename Functor>
22956 void setTargetLabel(BoundLabel value, Functor func)
22957 {
22958 if (!Fits<BoundLabel, size>::check(value))
22959 value = func();
22960 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
22961 *stream = Fits<BoundLabel, size>::convert(value);
22962 }
22963
22964 VirtualRegister m_lhs;
22965 VirtualRegister m_rhs;
22966 BoundLabel m_targetLabel;
22967};
22968
22969struct OpJless : public Instruction {
22970 static constexpr OpcodeID opcodeID = op_jless;
22971
22972 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22973 {
22974 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
22975 }
22976
22977 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
22978 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22979 {
22980 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
22981 if (shouldAssert == Assert)
22982 ASSERT(didEmit);
22983 return didEmit;
22984 }
22985
22986 template<OpcodeSize size>
22987 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
22988 {
22989
22990 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
22991 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
22992 return;
22993 }
22994 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
22995 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
22996 return;
22997 }
22998 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
22999 }
23000
23001private:
23002 template<OpcodeSize size>
23003 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
23004 {
23005 UNUSED_PARAM(gen);
23006#if OS(WINDOWS) && ENABLE(C_LOOP)
23007 // FIXME: Disable wide16 optimization for Windows CLoop
23008 // https://bugs.webkit.org/show_bug.cgi?id=198283
23009 if (size == OpcodeSize::Wide16)
23010 return false;
23011#endif
23012 return Fits<OpcodeID, size>::check(opcodeID)
23013 && Fits<VirtualRegister, size>::check(lhs)
23014 && Fits<VirtualRegister, size>::check(rhs)
23015 && Fits<BoundLabel, size>::check(targetLabel)
23016 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
23017 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
23018 }
23019
23020 template<OpcodeSize size, bool recordOpcode>
23021 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23022 {
23023 if (size == OpcodeSize::Wide16)
23024 gen->alignWideOpcode16();
23025 else if (size == OpcodeSize::Wide32)
23026 gen->alignWideOpcode32();
23027 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
23028 if (recordOpcode)
23029 gen->recordOpcode(opcodeID);
23030 if (size == OpcodeSize::Wide16)
23031 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
23032 else if (size == OpcodeSize::Wide32)
23033 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
23034 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
23035 gen->write(Fits<VirtualRegister, size>::convert(lhs));
23036 gen->write(Fits<VirtualRegister, size>::convert(rhs));
23037 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
23038 return true;
23039 }
23040 return false;
23041 }
23042
23043public:
23044 template<typename Block>
23045 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
23046 {
23047 dumper->printLocationAndOp(__location, &"**jless"[2 - __sizeShiftAmount]);
23048 dumper->dumpOperand(m_lhs, true);
23049 dumper->dumpOperand(m_rhs, false);
23050 dumper->dumpOperand(m_targetLabel, false);
23051 }
23052
23053 OpJless(const uint8_t* stream)
23054 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
23055 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
23056 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
23057 {
23058 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23059 }
23060
23061 OpJless(const uint16_t* stream)
23062 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
23063 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
23064 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
23065 {
23066 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23067 }
23068
23069
23070 OpJless(const uint32_t* stream)
23071 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
23072 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
23073 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
23074 {
23075 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23076 }
23077
23078 static OpJless decode(const uint8_t* stream)
23079 {
23080 if (*stream == op_wide32)
23081 return { bitwise_cast<const uint32_t*>(stream + 1) };
23082 if (*stream == op_wide16)
23083 return { bitwise_cast<const uint16_t*>(stream + 1) };
23084 return { stream };
23085 }
23086
23087 template<typename Functor>
23088 void setLhs(VirtualRegister value, Functor func)
23089 {
23090 if (isWide32())
23091 setLhs<OpcodeSize::Wide32>(value, func);
23092 else if (isWide16())
23093 setLhs<OpcodeSize::Wide16>(value, func);
23094 else
23095 setLhs<OpcodeSize::Narrow>(value, func);
23096 }
23097
23098 template <OpcodeSize size, typename Functor>
23099 void setLhs(VirtualRegister value, Functor func)
23100 {
23101 if (!Fits<VirtualRegister, size>::check(value))
23102 value = func();
23103 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
23104 *stream = Fits<VirtualRegister, size>::convert(value);
23105 }
23106
23107 template<typename Functor>
23108 void setRhs(VirtualRegister value, Functor func)
23109 {
23110 if (isWide32())
23111 setRhs<OpcodeSize::Wide32>(value, func);
23112 else if (isWide16())
23113 setRhs<OpcodeSize::Wide16>(value, func);
23114 else
23115 setRhs<OpcodeSize::Narrow>(value, func);
23116 }
23117
23118 template <OpcodeSize size, typename Functor>
23119 void setRhs(VirtualRegister value, Functor func)
23120 {
23121 if (!Fits<VirtualRegister, size>::check(value))
23122 value = func();
23123 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
23124 *stream = Fits<VirtualRegister, size>::convert(value);
23125 }
23126
23127 template<typename Functor>
23128 void setTargetLabel(BoundLabel value, Functor func)
23129 {
23130 if (isWide32())
23131 setTargetLabel<OpcodeSize::Wide32>(value, func);
23132 else if (isWide16())
23133 setTargetLabel<OpcodeSize::Wide16>(value, func);
23134 else
23135 setTargetLabel<OpcodeSize::Narrow>(value, func);
23136 }
23137
23138 template <OpcodeSize size, typename Functor>
23139 void setTargetLabel(BoundLabel value, Functor func)
23140 {
23141 if (!Fits<BoundLabel, size>::check(value))
23142 value = func();
23143 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
23144 *stream = Fits<BoundLabel, size>::convert(value);
23145 }
23146
23147 VirtualRegister m_lhs;
23148 VirtualRegister m_rhs;
23149 BoundLabel m_targetLabel;
23150};
23151
23152struct OpJlesseq : public Instruction {
23153 static constexpr OpcodeID opcodeID = op_jlesseq;
23154
23155 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23156 {
23157 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
23158 }
23159
23160 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
23161 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23162 {
23163 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
23164 if (shouldAssert == Assert)
23165 ASSERT(didEmit);
23166 return didEmit;
23167 }
23168
23169 template<OpcodeSize size>
23170 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23171 {
23172
23173 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
23174 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
23175 return;
23176 }
23177 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
23178 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
23179 return;
23180 }
23181 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
23182 }
23183
23184private:
23185 template<OpcodeSize size>
23186 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
23187 {
23188 UNUSED_PARAM(gen);
23189#if OS(WINDOWS) && ENABLE(C_LOOP)
23190 // FIXME: Disable wide16 optimization for Windows CLoop
23191 // https://bugs.webkit.org/show_bug.cgi?id=198283
23192 if (size == OpcodeSize::Wide16)
23193 return false;
23194#endif
23195 return Fits<OpcodeID, size>::check(opcodeID)
23196 && Fits<VirtualRegister, size>::check(lhs)
23197 && Fits<VirtualRegister, size>::check(rhs)
23198 && Fits<BoundLabel, size>::check(targetLabel)
23199 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
23200 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
23201 }
23202
23203 template<OpcodeSize size, bool recordOpcode>
23204 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23205 {
23206 if (size == OpcodeSize::Wide16)
23207 gen->alignWideOpcode16();
23208 else if (size == OpcodeSize::Wide32)
23209 gen->alignWideOpcode32();
23210 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
23211 if (recordOpcode)
23212 gen->recordOpcode(opcodeID);
23213 if (size == OpcodeSize::Wide16)
23214 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
23215 else if (size == OpcodeSize::Wide32)
23216 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
23217 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
23218 gen->write(Fits<VirtualRegister, size>::convert(lhs));
23219 gen->write(Fits<VirtualRegister, size>::convert(rhs));
23220 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
23221 return true;
23222 }
23223 return false;
23224 }
23225
23226public:
23227 template<typename Block>
23228 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
23229 {
23230 dumper->printLocationAndOp(__location, &"**jlesseq"[2 - __sizeShiftAmount]);
23231 dumper->dumpOperand(m_lhs, true);
23232 dumper->dumpOperand(m_rhs, false);
23233 dumper->dumpOperand(m_targetLabel, false);
23234 }
23235
23236 OpJlesseq(const uint8_t* stream)
23237 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
23238 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
23239 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
23240 {
23241 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23242 }
23243
23244 OpJlesseq(const uint16_t* stream)
23245 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
23246 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
23247 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
23248 {
23249 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23250 }
23251
23252
23253 OpJlesseq(const uint32_t* stream)
23254 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
23255 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
23256 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
23257 {
23258 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23259 }
23260
23261 static OpJlesseq decode(const uint8_t* stream)
23262 {
23263 if (*stream == op_wide32)
23264 return { bitwise_cast<const uint32_t*>(stream + 1) };
23265 if (*stream == op_wide16)
23266 return { bitwise_cast<const uint16_t*>(stream + 1) };
23267 return { stream };
23268 }
23269
23270 template<typename Functor>
23271 void setLhs(VirtualRegister value, Functor func)
23272 {
23273 if (isWide32())
23274 setLhs<OpcodeSize::Wide32>(value, func);
23275 else if (isWide16())
23276 setLhs<OpcodeSize::Wide16>(value, func);
23277 else
23278 setLhs<OpcodeSize::Narrow>(value, func);
23279 }
23280
23281 template <OpcodeSize size, typename Functor>
23282 void setLhs(VirtualRegister value, Functor func)
23283 {
23284 if (!Fits<VirtualRegister, size>::check(value))
23285 value = func();
23286 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
23287 *stream = Fits<VirtualRegister, size>::convert(value);
23288 }
23289
23290 template<typename Functor>
23291 void setRhs(VirtualRegister value, Functor func)
23292 {
23293 if (isWide32())
23294 setRhs<OpcodeSize::Wide32>(value, func);
23295 else if (isWide16())
23296 setRhs<OpcodeSize::Wide16>(value, func);
23297 else
23298 setRhs<OpcodeSize::Narrow>(value, func);
23299 }
23300
23301 template <OpcodeSize size, typename Functor>
23302 void setRhs(VirtualRegister value, Functor func)
23303 {
23304 if (!Fits<VirtualRegister, size>::check(value))
23305 value = func();
23306 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
23307 *stream = Fits<VirtualRegister, size>::convert(value);
23308 }
23309
23310 template<typename Functor>
23311 void setTargetLabel(BoundLabel value, Functor func)
23312 {
23313 if (isWide32())
23314 setTargetLabel<OpcodeSize::Wide32>(value, func);
23315 else if (isWide16())
23316 setTargetLabel<OpcodeSize::Wide16>(value, func);
23317 else
23318 setTargetLabel<OpcodeSize::Narrow>(value, func);
23319 }
23320
23321 template <OpcodeSize size, typename Functor>
23322 void setTargetLabel(BoundLabel value, Functor func)
23323 {
23324 if (!Fits<BoundLabel, size>::check(value))
23325 value = func();
23326 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
23327 *stream = Fits<BoundLabel, size>::convert(value);
23328 }
23329
23330 VirtualRegister m_lhs;
23331 VirtualRegister m_rhs;
23332 BoundLabel m_targetLabel;
23333};
23334
23335struct OpJgreater : public Instruction {
23336 static constexpr OpcodeID opcodeID = op_jgreater;
23337
23338 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23339 {
23340 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
23341 }
23342
23343 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
23344 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23345 {
23346 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
23347 if (shouldAssert == Assert)
23348 ASSERT(didEmit);
23349 return didEmit;
23350 }
23351
23352 template<OpcodeSize size>
23353 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23354 {
23355
23356 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
23357 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
23358 return;
23359 }
23360 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
23361 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
23362 return;
23363 }
23364 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
23365 }
23366
23367private:
23368 template<OpcodeSize size>
23369 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
23370 {
23371 UNUSED_PARAM(gen);
23372#if OS(WINDOWS) && ENABLE(C_LOOP)
23373 // FIXME: Disable wide16 optimization for Windows CLoop
23374 // https://bugs.webkit.org/show_bug.cgi?id=198283
23375 if (size == OpcodeSize::Wide16)
23376 return false;
23377#endif
23378 return Fits<OpcodeID, size>::check(opcodeID)
23379 && Fits<VirtualRegister, size>::check(lhs)
23380 && Fits<VirtualRegister, size>::check(rhs)
23381 && Fits<BoundLabel, size>::check(targetLabel)
23382 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
23383 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
23384 }
23385
23386 template<OpcodeSize size, bool recordOpcode>
23387 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23388 {
23389 if (size == OpcodeSize::Wide16)
23390 gen->alignWideOpcode16();
23391 else if (size == OpcodeSize::Wide32)
23392 gen->alignWideOpcode32();
23393 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
23394 if (recordOpcode)
23395 gen->recordOpcode(opcodeID);
23396 if (size == OpcodeSize::Wide16)
23397 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
23398 else if (size == OpcodeSize::Wide32)
23399 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
23400 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
23401 gen->write(Fits<VirtualRegister, size>::convert(lhs));
23402 gen->write(Fits<VirtualRegister, size>::convert(rhs));
23403 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
23404 return true;
23405 }
23406 return false;
23407 }
23408
23409public:
23410 template<typename Block>
23411 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
23412 {
23413 dumper->printLocationAndOp(__location, &"**jgreater"[2 - __sizeShiftAmount]);
23414 dumper->dumpOperand(m_lhs, true);
23415 dumper->dumpOperand(m_rhs, false);
23416 dumper->dumpOperand(m_targetLabel, false);
23417 }
23418
23419 OpJgreater(const uint8_t* stream)
23420 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
23421 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
23422 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
23423 {
23424 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23425 }
23426
23427 OpJgreater(const uint16_t* stream)
23428 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
23429 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
23430 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
23431 {
23432 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23433 }
23434
23435
23436 OpJgreater(const uint32_t* stream)
23437 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
23438 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
23439 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
23440 {
23441 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23442 }
23443
23444 static OpJgreater decode(const uint8_t* stream)
23445 {
23446 if (*stream == op_wide32)
23447 return { bitwise_cast<const uint32_t*>(stream + 1) };
23448 if (*stream == op_wide16)
23449 return { bitwise_cast<const uint16_t*>(stream + 1) };
23450 return { stream };
23451 }
23452
23453 template<typename Functor>
23454 void setLhs(VirtualRegister value, Functor func)
23455 {
23456 if (isWide32())
23457 setLhs<OpcodeSize::Wide32>(value, func);
23458 else if (isWide16())
23459 setLhs<OpcodeSize::Wide16>(value, func);
23460 else
23461 setLhs<OpcodeSize::Narrow>(value, func);
23462 }
23463
23464 template <OpcodeSize size, typename Functor>
23465 void setLhs(VirtualRegister value, Functor func)
23466 {
23467 if (!Fits<VirtualRegister, size>::check(value))
23468 value = func();
23469 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
23470 *stream = Fits<VirtualRegister, size>::convert(value);
23471 }
23472
23473 template<typename Functor>
23474 void setRhs(VirtualRegister value, Functor func)
23475 {
23476 if (isWide32())
23477 setRhs<OpcodeSize::Wide32>(value, func);
23478 else if (isWide16())
23479 setRhs<OpcodeSize::Wide16>(value, func);
23480 else
23481 setRhs<OpcodeSize::Narrow>(value, func);
23482 }
23483
23484 template <OpcodeSize size, typename Functor>
23485 void setRhs(VirtualRegister value, Functor func)
23486 {
23487 if (!Fits<VirtualRegister, size>::check(value))
23488 value = func();
23489 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
23490 *stream = Fits<VirtualRegister, size>::convert(value);
23491 }
23492
23493 template<typename Functor>
23494 void setTargetLabel(BoundLabel value, Functor func)
23495 {
23496 if (isWide32())
23497 setTargetLabel<OpcodeSize::Wide32>(value, func);
23498 else if (isWide16())
23499 setTargetLabel<OpcodeSize::Wide16>(value, func);
23500 else
23501 setTargetLabel<OpcodeSize::Narrow>(value, func);
23502 }
23503
23504 template <OpcodeSize size, typename Functor>
23505 void setTargetLabel(BoundLabel value, Functor func)
23506 {
23507 if (!Fits<BoundLabel, size>::check(value))
23508 value = func();
23509 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
23510 *stream = Fits<BoundLabel, size>::convert(value);
23511 }
23512
23513 VirtualRegister m_lhs;
23514 VirtualRegister m_rhs;
23515 BoundLabel m_targetLabel;
23516};
23517
23518struct OpJgreatereq : public Instruction {
23519 static constexpr OpcodeID opcodeID = op_jgreatereq;
23520
23521 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23522 {
23523 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
23524 }
23525
23526 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
23527 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23528 {
23529 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
23530 if (shouldAssert == Assert)
23531 ASSERT(didEmit);
23532 return didEmit;
23533 }
23534
23535 template<OpcodeSize size>
23536 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23537 {
23538
23539 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
23540 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
23541 return;
23542 }
23543 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
23544 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
23545 return;
23546 }
23547 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
23548 }
23549
23550private:
23551 template<OpcodeSize size>
23552 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
23553 {
23554 UNUSED_PARAM(gen);
23555#if OS(WINDOWS) && ENABLE(C_LOOP)
23556 // FIXME: Disable wide16 optimization for Windows CLoop
23557 // https://bugs.webkit.org/show_bug.cgi?id=198283
23558 if (size == OpcodeSize::Wide16)
23559 return false;
23560#endif
23561 return Fits<OpcodeID, size>::check(opcodeID)
23562 && Fits<VirtualRegister, size>::check(lhs)
23563 && Fits<VirtualRegister, size>::check(rhs)
23564 && Fits<BoundLabel, size>::check(targetLabel)
23565 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
23566 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
23567 }
23568
23569 template<OpcodeSize size, bool recordOpcode>
23570 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23571 {
23572 if (size == OpcodeSize::Wide16)
23573 gen->alignWideOpcode16();
23574 else if (size == OpcodeSize::Wide32)
23575 gen->alignWideOpcode32();
23576 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
23577 if (recordOpcode)
23578 gen->recordOpcode(opcodeID);
23579 if (size == OpcodeSize::Wide16)
23580 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
23581 else if (size == OpcodeSize::Wide32)
23582 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
23583 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
23584 gen->write(Fits<VirtualRegister, size>::convert(lhs));
23585 gen->write(Fits<VirtualRegister, size>::convert(rhs));
23586 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
23587 return true;
23588 }
23589 return false;
23590 }
23591
23592public:
23593 template<typename Block>
23594 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
23595 {
23596 dumper->printLocationAndOp(__location, &"**jgreatereq"[2 - __sizeShiftAmount]);
23597 dumper->dumpOperand(m_lhs, true);
23598 dumper->dumpOperand(m_rhs, false);
23599 dumper->dumpOperand(m_targetLabel, false);
23600 }
23601
23602 OpJgreatereq(const uint8_t* stream)
23603 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
23604 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
23605 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
23606 {
23607 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23608 }
23609
23610 OpJgreatereq(const uint16_t* stream)
23611 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
23612 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
23613 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
23614 {
23615 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23616 }
23617
23618
23619 OpJgreatereq(const uint32_t* stream)
23620 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
23621 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
23622 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
23623 {
23624 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23625 }
23626
23627 static OpJgreatereq decode(const uint8_t* stream)
23628 {
23629 if (*stream == op_wide32)
23630 return { bitwise_cast<const uint32_t*>(stream + 1) };
23631 if (*stream == op_wide16)
23632 return { bitwise_cast<const uint16_t*>(stream + 1) };
23633 return { stream };
23634 }
23635
23636 template<typename Functor>
23637 void setLhs(VirtualRegister value, Functor func)
23638 {
23639 if (isWide32())
23640 setLhs<OpcodeSize::Wide32>(value, func);
23641 else if (isWide16())
23642 setLhs<OpcodeSize::Wide16>(value, func);
23643 else
23644 setLhs<OpcodeSize::Narrow>(value, func);
23645 }
23646
23647 template <OpcodeSize size, typename Functor>
23648 void setLhs(VirtualRegister value, Functor func)
23649 {
23650 if (!Fits<VirtualRegister, size>::check(value))
23651 value = func();
23652 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
23653 *stream = Fits<VirtualRegister, size>::convert(value);
23654 }
23655
23656 template<typename Functor>
23657 void setRhs(VirtualRegister value, Functor func)
23658 {
23659 if (isWide32())
23660 setRhs<OpcodeSize::Wide32>(value, func);
23661 else if (isWide16())
23662 setRhs<OpcodeSize::Wide16>(value, func);
23663 else
23664 setRhs<OpcodeSize::Narrow>(value, func);
23665 }
23666
23667 template <OpcodeSize size, typename Functor>
23668 void setRhs(VirtualRegister value, Functor func)
23669 {
23670 if (!Fits<VirtualRegister, size>::check(value))
23671 value = func();
23672 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
23673 *stream = Fits<VirtualRegister, size>::convert(value);
23674 }
23675
23676 template<typename Functor>
23677 void setTargetLabel(BoundLabel value, Functor func)
23678 {
23679 if (isWide32())
23680 setTargetLabel<OpcodeSize::Wide32>(value, func);
23681 else if (isWide16())
23682 setTargetLabel<OpcodeSize::Wide16>(value, func);
23683 else
23684 setTargetLabel<OpcodeSize::Narrow>(value, func);
23685 }
23686
23687 template <OpcodeSize size, typename Functor>
23688 void setTargetLabel(BoundLabel value, Functor func)
23689 {
23690 if (!Fits<BoundLabel, size>::check(value))
23691 value = func();
23692 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
23693 *stream = Fits<BoundLabel, size>::convert(value);
23694 }
23695
23696 VirtualRegister m_lhs;
23697 VirtualRegister m_rhs;
23698 BoundLabel m_targetLabel;
23699};
23700
23701struct OpJnless : public Instruction {
23702 static constexpr OpcodeID opcodeID = op_jnless;
23703
23704 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23705 {
23706 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
23707 }
23708
23709 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
23710 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23711 {
23712 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
23713 if (shouldAssert == Assert)
23714 ASSERT(didEmit);
23715 return didEmit;
23716 }
23717
23718 template<OpcodeSize size>
23719 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23720 {
23721
23722 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
23723 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
23724 return;
23725 }
23726 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
23727 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
23728 return;
23729 }
23730 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
23731 }
23732
23733private:
23734 template<OpcodeSize size>
23735 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
23736 {
23737 UNUSED_PARAM(gen);
23738#if OS(WINDOWS) && ENABLE(C_LOOP)
23739 // FIXME: Disable wide16 optimization for Windows CLoop
23740 // https://bugs.webkit.org/show_bug.cgi?id=198283
23741 if (size == OpcodeSize::Wide16)
23742 return false;
23743#endif
23744 return Fits<OpcodeID, size>::check(opcodeID)
23745 && Fits<VirtualRegister, size>::check(lhs)
23746 && Fits<VirtualRegister, size>::check(rhs)
23747 && Fits<BoundLabel, size>::check(targetLabel)
23748 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
23749 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
23750 }
23751
23752 template<OpcodeSize size, bool recordOpcode>
23753 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23754 {
23755 if (size == OpcodeSize::Wide16)
23756 gen->alignWideOpcode16();
23757 else if (size == OpcodeSize::Wide32)
23758 gen->alignWideOpcode32();
23759 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
23760 if (recordOpcode)
23761 gen->recordOpcode(opcodeID);
23762 if (size == OpcodeSize::Wide16)
23763 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
23764 else if (size == OpcodeSize::Wide32)
23765 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
23766 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
23767 gen->write(Fits<VirtualRegister, size>::convert(lhs));
23768 gen->write(Fits<VirtualRegister, size>::convert(rhs));
23769 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
23770 return true;
23771 }
23772 return false;
23773 }
23774
23775public:
23776 template<typename Block>
23777 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
23778 {
23779 dumper->printLocationAndOp(__location, &"**jnless"[2 - __sizeShiftAmount]);
23780 dumper->dumpOperand(m_lhs, true);
23781 dumper->dumpOperand(m_rhs, false);
23782 dumper->dumpOperand(m_targetLabel, false);
23783 }
23784
23785 OpJnless(const uint8_t* stream)
23786 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
23787 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
23788 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
23789 {
23790 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23791 }
23792
23793 OpJnless(const uint16_t* stream)
23794 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
23795 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
23796 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
23797 {
23798 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23799 }
23800
23801
23802 OpJnless(const uint32_t* stream)
23803 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
23804 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
23805 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
23806 {
23807 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23808 }
23809
23810 static OpJnless decode(const uint8_t* stream)
23811 {
23812 if (*stream == op_wide32)
23813 return { bitwise_cast<const uint32_t*>(stream + 1) };
23814 if (*stream == op_wide16)
23815 return { bitwise_cast<const uint16_t*>(stream + 1) };
23816 return { stream };
23817 }
23818
23819 template<typename Functor>
23820 void setLhs(VirtualRegister value, Functor func)
23821 {
23822 if (isWide32())
23823 setLhs<OpcodeSize::Wide32>(value, func);
23824 else if (isWide16())
23825 setLhs<OpcodeSize::Wide16>(value, func);
23826 else
23827 setLhs<OpcodeSize::Narrow>(value, func);
23828 }
23829
23830 template <OpcodeSize size, typename Functor>
23831 void setLhs(VirtualRegister value, Functor func)
23832 {
23833 if (!Fits<VirtualRegister, size>::check(value))
23834 value = func();
23835 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
23836 *stream = Fits<VirtualRegister, size>::convert(value);
23837 }
23838
23839 template<typename Functor>
23840 void setRhs(VirtualRegister value, Functor func)
23841 {
23842 if (isWide32())
23843 setRhs<OpcodeSize::Wide32>(value, func);
23844 else if (isWide16())
23845 setRhs<OpcodeSize::Wide16>(value, func);
23846 else
23847 setRhs<OpcodeSize::Narrow>(value, func);
23848 }
23849
23850 template <OpcodeSize size, typename Functor>
23851 void setRhs(VirtualRegister value, Functor func)
23852 {
23853 if (!Fits<VirtualRegister, size>::check(value))
23854 value = func();
23855 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
23856 *stream = Fits<VirtualRegister, size>::convert(value);
23857 }
23858
23859 template<typename Functor>
23860 void setTargetLabel(BoundLabel value, Functor func)
23861 {
23862 if (isWide32())
23863 setTargetLabel<OpcodeSize::Wide32>(value, func);
23864 else if (isWide16())
23865 setTargetLabel<OpcodeSize::Wide16>(value, func);
23866 else
23867 setTargetLabel<OpcodeSize::Narrow>(value, func);
23868 }
23869
23870 template <OpcodeSize size, typename Functor>
23871 void setTargetLabel(BoundLabel value, Functor func)
23872 {
23873 if (!Fits<BoundLabel, size>::check(value))
23874 value = func();
23875 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
23876 *stream = Fits<BoundLabel, size>::convert(value);
23877 }
23878
23879 VirtualRegister m_lhs;
23880 VirtualRegister m_rhs;
23881 BoundLabel m_targetLabel;
23882};
23883
23884struct OpJnlesseq : public Instruction {
23885 static constexpr OpcodeID opcodeID = op_jnlesseq;
23886
23887 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23888 {
23889 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
23890 }
23891
23892 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
23893 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23894 {
23895 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
23896 if (shouldAssert == Assert)
23897 ASSERT(didEmit);
23898 return didEmit;
23899 }
23900
23901 template<OpcodeSize size>
23902 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23903 {
23904
23905 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
23906 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
23907 return;
23908 }
23909 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
23910 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
23911 return;
23912 }
23913 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
23914 }
23915
23916private:
23917 template<OpcodeSize size>
23918 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
23919 {
23920 UNUSED_PARAM(gen);
23921#if OS(WINDOWS) && ENABLE(C_LOOP)
23922 // FIXME: Disable wide16 optimization for Windows CLoop
23923 // https://bugs.webkit.org/show_bug.cgi?id=198283
23924 if (size == OpcodeSize::Wide16)
23925 return false;
23926#endif
23927 return Fits<OpcodeID, size>::check(opcodeID)
23928 && Fits<VirtualRegister, size>::check(lhs)
23929 && Fits<VirtualRegister, size>::check(rhs)
23930 && Fits<BoundLabel, size>::check(targetLabel)
23931 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
23932 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
23933 }
23934
23935 template<OpcodeSize size, bool recordOpcode>
23936 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
23937 {
23938 if (size == OpcodeSize::Wide16)
23939 gen->alignWideOpcode16();
23940 else if (size == OpcodeSize::Wide32)
23941 gen->alignWideOpcode32();
23942 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
23943 if (recordOpcode)
23944 gen->recordOpcode(opcodeID);
23945 if (size == OpcodeSize::Wide16)
23946 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
23947 else if (size == OpcodeSize::Wide32)
23948 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
23949 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
23950 gen->write(Fits<VirtualRegister, size>::convert(lhs));
23951 gen->write(Fits<VirtualRegister, size>::convert(rhs));
23952 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
23953 return true;
23954 }
23955 return false;
23956 }
23957
23958public:
23959 template<typename Block>
23960 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
23961 {
23962 dumper->printLocationAndOp(__location, &"**jnlesseq"[2 - __sizeShiftAmount]);
23963 dumper->dumpOperand(m_lhs, true);
23964 dumper->dumpOperand(m_rhs, false);
23965 dumper->dumpOperand(m_targetLabel, false);
23966 }
23967
23968 OpJnlesseq(const uint8_t* stream)
23969 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
23970 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
23971 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
23972 {
23973 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23974 }
23975
23976 OpJnlesseq(const uint16_t* stream)
23977 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
23978 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
23979 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
23980 {
23981 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23982 }
23983
23984
23985 OpJnlesseq(const uint32_t* stream)
23986 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
23987 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
23988 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
23989 {
23990 ASSERT_UNUSED(stream, stream[0] == opcodeID);
23991 }
23992
23993 static OpJnlesseq decode(const uint8_t* stream)
23994 {
23995 if (*stream == op_wide32)
23996 return { bitwise_cast<const uint32_t*>(stream + 1) };
23997 if (*stream == op_wide16)
23998 return { bitwise_cast<const uint16_t*>(stream + 1) };
23999 return { stream };
24000 }
24001
24002 template<typename Functor>
24003 void setLhs(VirtualRegister value, Functor func)
24004 {
24005 if (isWide32())
24006 setLhs<OpcodeSize::Wide32>(value, func);
24007 else if (isWide16())
24008 setLhs<OpcodeSize::Wide16>(value, func);
24009 else
24010 setLhs<OpcodeSize::Narrow>(value, func);
24011 }
24012
24013 template <OpcodeSize size, typename Functor>
24014 void setLhs(VirtualRegister value, Functor func)
24015 {
24016 if (!Fits<VirtualRegister, size>::check(value))
24017 value = func();
24018 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
24019 *stream = Fits<VirtualRegister, size>::convert(value);
24020 }
24021
24022 template<typename Functor>
24023 void setRhs(VirtualRegister value, Functor func)
24024 {
24025 if (isWide32())
24026 setRhs<OpcodeSize::Wide32>(value, func);
24027 else if (isWide16())
24028 setRhs<OpcodeSize::Wide16>(value, func);
24029 else
24030 setRhs<OpcodeSize::Narrow>(value, func);
24031 }
24032
24033 template <OpcodeSize size, typename Functor>
24034 void setRhs(VirtualRegister value, Functor func)
24035 {
24036 if (!Fits<VirtualRegister, size>::check(value))
24037 value = func();
24038 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
24039 *stream = Fits<VirtualRegister, size>::convert(value);
24040 }
24041
24042 template<typename Functor>
24043 void setTargetLabel(BoundLabel value, Functor func)
24044 {
24045 if (isWide32())
24046 setTargetLabel<OpcodeSize::Wide32>(value, func);
24047 else if (isWide16())
24048 setTargetLabel<OpcodeSize::Wide16>(value, func);
24049 else
24050 setTargetLabel<OpcodeSize::Narrow>(value, func);
24051 }
24052
24053 template <OpcodeSize size, typename Functor>
24054 void setTargetLabel(BoundLabel value, Functor func)
24055 {
24056 if (!Fits<BoundLabel, size>::check(value))
24057 value = func();
24058 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
24059 *stream = Fits<BoundLabel, size>::convert(value);
24060 }
24061
24062 VirtualRegister m_lhs;
24063 VirtualRegister m_rhs;
24064 BoundLabel m_targetLabel;
24065};
24066
24067struct OpJngreater : public Instruction {
24068 static constexpr OpcodeID opcodeID = op_jngreater;
24069
24070 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24071 {
24072 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
24073 }
24074
24075 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
24076 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24077 {
24078 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
24079 if (shouldAssert == Assert)
24080 ASSERT(didEmit);
24081 return didEmit;
24082 }
24083
24084 template<OpcodeSize size>
24085 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24086 {
24087
24088 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
24089 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
24090 return;
24091 }
24092 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
24093 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
24094 return;
24095 }
24096 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
24097 }
24098
24099private:
24100 template<OpcodeSize size>
24101 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
24102 {
24103 UNUSED_PARAM(gen);
24104#if OS(WINDOWS) && ENABLE(C_LOOP)
24105 // FIXME: Disable wide16 optimization for Windows CLoop
24106 // https://bugs.webkit.org/show_bug.cgi?id=198283
24107 if (size == OpcodeSize::Wide16)
24108 return false;
24109#endif
24110 return Fits<OpcodeID, size>::check(opcodeID)
24111 && Fits<VirtualRegister, size>::check(lhs)
24112 && Fits<VirtualRegister, size>::check(rhs)
24113 && Fits<BoundLabel, size>::check(targetLabel)
24114 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
24115 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
24116 }
24117
24118 template<OpcodeSize size, bool recordOpcode>
24119 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24120 {
24121 if (size == OpcodeSize::Wide16)
24122 gen->alignWideOpcode16();
24123 else if (size == OpcodeSize::Wide32)
24124 gen->alignWideOpcode32();
24125 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
24126 if (recordOpcode)
24127 gen->recordOpcode(opcodeID);
24128 if (size == OpcodeSize::Wide16)
24129 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
24130 else if (size == OpcodeSize::Wide32)
24131 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
24132 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
24133 gen->write(Fits<VirtualRegister, size>::convert(lhs));
24134 gen->write(Fits<VirtualRegister, size>::convert(rhs));
24135 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
24136 return true;
24137 }
24138 return false;
24139 }
24140
24141public:
24142 template<typename Block>
24143 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
24144 {
24145 dumper->printLocationAndOp(__location, &"**jngreater"[2 - __sizeShiftAmount]);
24146 dumper->dumpOperand(m_lhs, true);
24147 dumper->dumpOperand(m_rhs, false);
24148 dumper->dumpOperand(m_targetLabel, false);
24149 }
24150
24151 OpJngreater(const uint8_t* stream)
24152 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
24153 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
24154 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
24155 {
24156 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24157 }
24158
24159 OpJngreater(const uint16_t* stream)
24160 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
24161 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
24162 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
24163 {
24164 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24165 }
24166
24167
24168 OpJngreater(const uint32_t* stream)
24169 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
24170 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
24171 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
24172 {
24173 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24174 }
24175
24176 static OpJngreater decode(const uint8_t* stream)
24177 {
24178 if (*stream == op_wide32)
24179 return { bitwise_cast<const uint32_t*>(stream + 1) };
24180 if (*stream == op_wide16)
24181 return { bitwise_cast<const uint16_t*>(stream + 1) };
24182 return { stream };
24183 }
24184
24185 template<typename Functor>
24186 void setLhs(VirtualRegister value, Functor func)
24187 {
24188 if (isWide32())
24189 setLhs<OpcodeSize::Wide32>(value, func);
24190 else if (isWide16())
24191 setLhs<OpcodeSize::Wide16>(value, func);
24192 else
24193 setLhs<OpcodeSize::Narrow>(value, func);
24194 }
24195
24196 template <OpcodeSize size, typename Functor>
24197 void setLhs(VirtualRegister value, Functor func)
24198 {
24199 if (!Fits<VirtualRegister, size>::check(value))
24200 value = func();
24201 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
24202 *stream = Fits<VirtualRegister, size>::convert(value);
24203 }
24204
24205 template<typename Functor>
24206 void setRhs(VirtualRegister value, Functor func)
24207 {
24208 if (isWide32())
24209 setRhs<OpcodeSize::Wide32>(value, func);
24210 else if (isWide16())
24211 setRhs<OpcodeSize::Wide16>(value, func);
24212 else
24213 setRhs<OpcodeSize::Narrow>(value, func);
24214 }
24215
24216 template <OpcodeSize size, typename Functor>
24217 void setRhs(VirtualRegister value, Functor func)
24218 {
24219 if (!Fits<VirtualRegister, size>::check(value))
24220 value = func();
24221 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
24222 *stream = Fits<VirtualRegister, size>::convert(value);
24223 }
24224
24225 template<typename Functor>
24226 void setTargetLabel(BoundLabel value, Functor func)
24227 {
24228 if (isWide32())
24229 setTargetLabel<OpcodeSize::Wide32>(value, func);
24230 else if (isWide16())
24231 setTargetLabel<OpcodeSize::Wide16>(value, func);
24232 else
24233 setTargetLabel<OpcodeSize::Narrow>(value, func);
24234 }
24235
24236 template <OpcodeSize size, typename Functor>
24237 void setTargetLabel(BoundLabel value, Functor func)
24238 {
24239 if (!Fits<BoundLabel, size>::check(value))
24240 value = func();
24241 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
24242 *stream = Fits<BoundLabel, size>::convert(value);
24243 }
24244
24245 VirtualRegister m_lhs;
24246 VirtualRegister m_rhs;
24247 BoundLabel m_targetLabel;
24248};
24249
24250struct OpJngreatereq : public Instruction {
24251 static constexpr OpcodeID opcodeID = op_jngreatereq;
24252
24253 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24254 {
24255 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
24256 }
24257
24258 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
24259 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24260 {
24261 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
24262 if (shouldAssert == Assert)
24263 ASSERT(didEmit);
24264 return didEmit;
24265 }
24266
24267 template<OpcodeSize size>
24268 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24269 {
24270
24271 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
24272 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
24273 return;
24274 }
24275 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
24276 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
24277 return;
24278 }
24279 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
24280 }
24281
24282private:
24283 template<OpcodeSize size>
24284 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
24285 {
24286 UNUSED_PARAM(gen);
24287#if OS(WINDOWS) && ENABLE(C_LOOP)
24288 // FIXME: Disable wide16 optimization for Windows CLoop
24289 // https://bugs.webkit.org/show_bug.cgi?id=198283
24290 if (size == OpcodeSize::Wide16)
24291 return false;
24292#endif
24293 return Fits<OpcodeID, size>::check(opcodeID)
24294 && Fits<VirtualRegister, size>::check(lhs)
24295 && Fits<VirtualRegister, size>::check(rhs)
24296 && Fits<BoundLabel, size>::check(targetLabel)
24297 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
24298 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
24299 }
24300
24301 template<OpcodeSize size, bool recordOpcode>
24302 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24303 {
24304 if (size == OpcodeSize::Wide16)
24305 gen->alignWideOpcode16();
24306 else if (size == OpcodeSize::Wide32)
24307 gen->alignWideOpcode32();
24308 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
24309 if (recordOpcode)
24310 gen->recordOpcode(opcodeID);
24311 if (size == OpcodeSize::Wide16)
24312 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
24313 else if (size == OpcodeSize::Wide32)
24314 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
24315 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
24316 gen->write(Fits<VirtualRegister, size>::convert(lhs));
24317 gen->write(Fits<VirtualRegister, size>::convert(rhs));
24318 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
24319 return true;
24320 }
24321 return false;
24322 }
24323
24324public:
24325 template<typename Block>
24326 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
24327 {
24328 dumper->printLocationAndOp(__location, &"**jngreatereq"[2 - __sizeShiftAmount]);
24329 dumper->dumpOperand(m_lhs, true);
24330 dumper->dumpOperand(m_rhs, false);
24331 dumper->dumpOperand(m_targetLabel, false);
24332 }
24333
24334 OpJngreatereq(const uint8_t* stream)
24335 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
24336 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
24337 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
24338 {
24339 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24340 }
24341
24342 OpJngreatereq(const uint16_t* stream)
24343 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
24344 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
24345 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
24346 {
24347 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24348 }
24349
24350
24351 OpJngreatereq(const uint32_t* stream)
24352 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
24353 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
24354 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
24355 {
24356 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24357 }
24358
24359 static OpJngreatereq decode(const uint8_t* stream)
24360 {
24361 if (*stream == op_wide32)
24362 return { bitwise_cast<const uint32_t*>(stream + 1) };
24363 if (*stream == op_wide16)
24364 return { bitwise_cast<const uint16_t*>(stream + 1) };
24365 return { stream };
24366 }
24367
24368 template<typename Functor>
24369 void setLhs(VirtualRegister value, Functor func)
24370 {
24371 if (isWide32())
24372 setLhs<OpcodeSize::Wide32>(value, func);
24373 else if (isWide16())
24374 setLhs<OpcodeSize::Wide16>(value, func);
24375 else
24376 setLhs<OpcodeSize::Narrow>(value, func);
24377 }
24378
24379 template <OpcodeSize size, typename Functor>
24380 void setLhs(VirtualRegister value, Functor func)
24381 {
24382 if (!Fits<VirtualRegister, size>::check(value))
24383 value = func();
24384 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
24385 *stream = Fits<VirtualRegister, size>::convert(value);
24386 }
24387
24388 template<typename Functor>
24389 void setRhs(VirtualRegister value, Functor func)
24390 {
24391 if (isWide32())
24392 setRhs<OpcodeSize::Wide32>(value, func);
24393 else if (isWide16())
24394 setRhs<OpcodeSize::Wide16>(value, func);
24395 else
24396 setRhs<OpcodeSize::Narrow>(value, func);
24397 }
24398
24399 template <OpcodeSize size, typename Functor>
24400 void setRhs(VirtualRegister value, Functor func)
24401 {
24402 if (!Fits<VirtualRegister, size>::check(value))
24403 value = func();
24404 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
24405 *stream = Fits<VirtualRegister, size>::convert(value);
24406 }
24407
24408 template<typename Functor>
24409 void setTargetLabel(BoundLabel value, Functor func)
24410 {
24411 if (isWide32())
24412 setTargetLabel<OpcodeSize::Wide32>(value, func);
24413 else if (isWide16())
24414 setTargetLabel<OpcodeSize::Wide16>(value, func);
24415 else
24416 setTargetLabel<OpcodeSize::Narrow>(value, func);
24417 }
24418
24419 template <OpcodeSize size, typename Functor>
24420 void setTargetLabel(BoundLabel value, Functor func)
24421 {
24422 if (!Fits<BoundLabel, size>::check(value))
24423 value = func();
24424 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
24425 *stream = Fits<BoundLabel, size>::convert(value);
24426 }
24427
24428 VirtualRegister m_lhs;
24429 VirtualRegister m_rhs;
24430 BoundLabel m_targetLabel;
24431};
24432
24433struct OpJbelow : public Instruction {
24434 static constexpr OpcodeID opcodeID = op_jbelow;
24435
24436 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24437 {
24438 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
24439 }
24440
24441 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
24442 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24443 {
24444 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
24445 if (shouldAssert == Assert)
24446 ASSERT(didEmit);
24447 return didEmit;
24448 }
24449
24450 template<OpcodeSize size>
24451 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24452 {
24453
24454 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
24455 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
24456 return;
24457 }
24458 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
24459 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
24460 return;
24461 }
24462 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
24463 }
24464
24465private:
24466 template<OpcodeSize size>
24467 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
24468 {
24469 UNUSED_PARAM(gen);
24470#if OS(WINDOWS) && ENABLE(C_LOOP)
24471 // FIXME: Disable wide16 optimization for Windows CLoop
24472 // https://bugs.webkit.org/show_bug.cgi?id=198283
24473 if (size == OpcodeSize::Wide16)
24474 return false;
24475#endif
24476 return Fits<OpcodeID, size>::check(opcodeID)
24477 && Fits<VirtualRegister, size>::check(lhs)
24478 && Fits<VirtualRegister, size>::check(rhs)
24479 && Fits<BoundLabel, size>::check(targetLabel)
24480 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
24481 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
24482 }
24483
24484 template<OpcodeSize size, bool recordOpcode>
24485 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24486 {
24487 if (size == OpcodeSize::Wide16)
24488 gen->alignWideOpcode16();
24489 else if (size == OpcodeSize::Wide32)
24490 gen->alignWideOpcode32();
24491 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
24492 if (recordOpcode)
24493 gen->recordOpcode(opcodeID);
24494 if (size == OpcodeSize::Wide16)
24495 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
24496 else if (size == OpcodeSize::Wide32)
24497 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
24498 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
24499 gen->write(Fits<VirtualRegister, size>::convert(lhs));
24500 gen->write(Fits<VirtualRegister, size>::convert(rhs));
24501 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
24502 return true;
24503 }
24504 return false;
24505 }
24506
24507public:
24508 template<typename Block>
24509 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
24510 {
24511 dumper->printLocationAndOp(__location, &"**jbelow"[2 - __sizeShiftAmount]);
24512 dumper->dumpOperand(m_lhs, true);
24513 dumper->dumpOperand(m_rhs, false);
24514 dumper->dumpOperand(m_targetLabel, false);
24515 }
24516
24517 OpJbelow(const uint8_t* stream)
24518 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
24519 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
24520 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
24521 {
24522 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24523 }
24524
24525 OpJbelow(const uint16_t* stream)
24526 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
24527 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
24528 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
24529 {
24530 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24531 }
24532
24533
24534 OpJbelow(const uint32_t* stream)
24535 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
24536 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
24537 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
24538 {
24539 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24540 }
24541
24542 static OpJbelow decode(const uint8_t* stream)
24543 {
24544 if (*stream == op_wide32)
24545 return { bitwise_cast<const uint32_t*>(stream + 1) };
24546 if (*stream == op_wide16)
24547 return { bitwise_cast<const uint16_t*>(stream + 1) };
24548 return { stream };
24549 }
24550
24551 template<typename Functor>
24552 void setLhs(VirtualRegister value, Functor func)
24553 {
24554 if (isWide32())
24555 setLhs<OpcodeSize::Wide32>(value, func);
24556 else if (isWide16())
24557 setLhs<OpcodeSize::Wide16>(value, func);
24558 else
24559 setLhs<OpcodeSize::Narrow>(value, func);
24560 }
24561
24562 template <OpcodeSize size, typename Functor>
24563 void setLhs(VirtualRegister value, Functor func)
24564 {
24565 if (!Fits<VirtualRegister, size>::check(value))
24566 value = func();
24567 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
24568 *stream = Fits<VirtualRegister, size>::convert(value);
24569 }
24570
24571 template<typename Functor>
24572 void setRhs(VirtualRegister value, Functor func)
24573 {
24574 if (isWide32())
24575 setRhs<OpcodeSize::Wide32>(value, func);
24576 else if (isWide16())
24577 setRhs<OpcodeSize::Wide16>(value, func);
24578 else
24579 setRhs<OpcodeSize::Narrow>(value, func);
24580 }
24581
24582 template <OpcodeSize size, typename Functor>
24583 void setRhs(VirtualRegister value, Functor func)
24584 {
24585 if (!Fits<VirtualRegister, size>::check(value))
24586 value = func();
24587 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
24588 *stream = Fits<VirtualRegister, size>::convert(value);
24589 }
24590
24591 template<typename Functor>
24592 void setTargetLabel(BoundLabel value, Functor func)
24593 {
24594 if (isWide32())
24595 setTargetLabel<OpcodeSize::Wide32>(value, func);
24596 else if (isWide16())
24597 setTargetLabel<OpcodeSize::Wide16>(value, func);
24598 else
24599 setTargetLabel<OpcodeSize::Narrow>(value, func);
24600 }
24601
24602 template <OpcodeSize size, typename Functor>
24603 void setTargetLabel(BoundLabel value, Functor func)
24604 {
24605 if (!Fits<BoundLabel, size>::check(value))
24606 value = func();
24607 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
24608 *stream = Fits<BoundLabel, size>::convert(value);
24609 }
24610
24611 VirtualRegister m_lhs;
24612 VirtualRegister m_rhs;
24613 BoundLabel m_targetLabel;
24614};
24615
24616struct OpJbeloweq : public Instruction {
24617 static constexpr OpcodeID opcodeID = op_jbeloweq;
24618
24619 static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24620 {
24621 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
24622 }
24623
24624 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
24625 static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24626 {
24627 bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
24628 if (shouldAssert == Assert)
24629 ASSERT(didEmit);
24630 return didEmit;
24631 }
24632
24633 template<OpcodeSize size>
24634 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24635 {
24636
24637 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
24638 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, lhs, rhs, targetLabel))
24639 return;
24640 }
24641 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
24642 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
24643 return;
24644 }
24645 emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
24646 }
24647
24648private:
24649 template<OpcodeSize size>
24650 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
24651 {
24652 UNUSED_PARAM(gen);
24653#if OS(WINDOWS) && ENABLE(C_LOOP)
24654 // FIXME: Disable wide16 optimization for Windows CLoop
24655 // https://bugs.webkit.org/show_bug.cgi?id=198283
24656 if (size == OpcodeSize::Wide16)
24657 return false;
24658#endif
24659 return Fits<OpcodeID, size>::check(opcodeID)
24660 && Fits<VirtualRegister, size>::check(lhs)
24661 && Fits<VirtualRegister, size>::check(rhs)
24662 && Fits<BoundLabel, size>::check(targetLabel)
24663 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
24664 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
24665 }
24666
24667 template<OpcodeSize size, bool recordOpcode>
24668 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
24669 {
24670 if (size == OpcodeSize::Wide16)
24671 gen->alignWideOpcode16();
24672 else if (size == OpcodeSize::Wide32)
24673 gen->alignWideOpcode32();
24674 if (checkImpl<size>(gen, lhs, rhs, targetLabel)) {
24675 if (recordOpcode)
24676 gen->recordOpcode(opcodeID);
24677 if (size == OpcodeSize::Wide16)
24678 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
24679 else if (size == OpcodeSize::Wide32)
24680 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
24681 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
24682 gen->write(Fits<VirtualRegister, size>::convert(lhs));
24683 gen->write(Fits<VirtualRegister, size>::convert(rhs));
24684 gen->write(Fits<BoundLabel, size>::convert(targetLabel));
24685 return true;
24686 }
24687 return false;
24688 }
24689
24690public:
24691 template<typename Block>
24692 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
24693 {
24694 dumper->printLocationAndOp(__location, &"**jbeloweq"[2 - __sizeShiftAmount]);
24695 dumper->dumpOperand(m_lhs, true);
24696 dumper->dumpOperand(m_rhs, false);
24697 dumper->dumpOperand(m_targetLabel, false);
24698 }
24699
24700 OpJbeloweq(const uint8_t* stream)
24701 : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
24702 , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
24703 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
24704 {
24705 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24706 }
24707
24708 OpJbeloweq(const uint16_t* stream)
24709 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
24710 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
24711 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
24712 {
24713 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24714 }
24715
24716
24717 OpJbeloweq(const uint32_t* stream)
24718 : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
24719 , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
24720 , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
24721 {
24722 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24723 }
24724
24725 static OpJbeloweq decode(const uint8_t* stream)
24726 {
24727 if (*stream == op_wide32)
24728 return { bitwise_cast<const uint32_t*>(stream + 1) };
24729 if (*stream == op_wide16)
24730 return { bitwise_cast<const uint16_t*>(stream + 1) };
24731 return { stream };
24732 }
24733
24734 template<typename Functor>
24735 void setLhs(VirtualRegister value, Functor func)
24736 {
24737 if (isWide32())
24738 setLhs<OpcodeSize::Wide32>(value, func);
24739 else if (isWide16())
24740 setLhs<OpcodeSize::Wide16>(value, func);
24741 else
24742 setLhs<OpcodeSize::Narrow>(value, func);
24743 }
24744
24745 template <OpcodeSize size, typename Functor>
24746 void setLhs(VirtualRegister value, Functor func)
24747 {
24748 if (!Fits<VirtualRegister, size>::check(value))
24749 value = func();
24750 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
24751 *stream = Fits<VirtualRegister, size>::convert(value);
24752 }
24753
24754 template<typename Functor>
24755 void setRhs(VirtualRegister value, Functor func)
24756 {
24757 if (isWide32())
24758 setRhs<OpcodeSize::Wide32>(value, func);
24759 else if (isWide16())
24760 setRhs<OpcodeSize::Wide16>(value, func);
24761 else
24762 setRhs<OpcodeSize::Narrow>(value, func);
24763 }
24764
24765 template <OpcodeSize size, typename Functor>
24766 void setRhs(VirtualRegister value, Functor func)
24767 {
24768 if (!Fits<VirtualRegister, size>::check(value))
24769 value = func();
24770 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
24771 *stream = Fits<VirtualRegister, size>::convert(value);
24772 }
24773
24774 template<typename Functor>
24775 void setTargetLabel(BoundLabel value, Functor func)
24776 {
24777 if (isWide32())
24778 setTargetLabel<OpcodeSize::Wide32>(value, func);
24779 else if (isWide16())
24780 setTargetLabel<OpcodeSize::Wide16>(value, func);
24781 else
24782 setTargetLabel<OpcodeSize::Narrow>(value, func);
24783 }
24784
24785 template <OpcodeSize size, typename Functor>
24786 void setTargetLabel(BoundLabel value, Functor func)
24787 {
24788 if (!Fits<BoundLabel, size>::check(value))
24789 value = func();
24790 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
24791 *stream = Fits<BoundLabel, size>::convert(value);
24792 }
24793
24794 VirtualRegister m_lhs;
24795 VirtualRegister m_rhs;
24796 BoundLabel m_targetLabel;
24797};
24798
24799struct OpLoopHint : public Instruction {
24800 static constexpr OpcodeID opcodeID = op_loop_hint;
24801
24802 static void emit(BytecodeGenerator* gen)
24803 {
24804 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
24805 }
24806
24807 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
24808 static bool emit(BytecodeGenerator* gen)
24809 {
24810 bool didEmit = emitImpl<size, recordOpcode>(gen);
24811 if (shouldAssert == Assert)
24812 ASSERT(didEmit);
24813 return didEmit;
24814 }
24815
24816 template<OpcodeSize size>
24817 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
24818 {
24819
24820 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
24821 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
24822 return;
24823 }
24824 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
24825 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
24826 return;
24827 }
24828 emit<OpcodeSize::Wide32, Assert, true>(gen);
24829 }
24830
24831private:
24832 template<OpcodeSize size>
24833 static bool checkImpl(BytecodeGenerator* gen)
24834 {
24835 UNUSED_PARAM(gen);
24836#if OS(WINDOWS) && ENABLE(C_LOOP)
24837 // FIXME: Disable wide16 optimization for Windows CLoop
24838 // https://bugs.webkit.org/show_bug.cgi?id=198283
24839 if (size == OpcodeSize::Wide16)
24840 return false;
24841#endif
24842 return Fits<OpcodeID, size>::check(opcodeID)
24843 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
24844 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
24845 }
24846
24847 template<OpcodeSize size, bool recordOpcode>
24848 static bool emitImpl(BytecodeGenerator* gen)
24849 {
24850 if (size == OpcodeSize::Wide16)
24851 gen->alignWideOpcode16();
24852 else if (size == OpcodeSize::Wide32)
24853 gen->alignWideOpcode32();
24854 if (checkImpl<size>(gen)) {
24855 if (recordOpcode)
24856 gen->recordOpcode(opcodeID);
24857 if (size == OpcodeSize::Wide16)
24858 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
24859 else if (size == OpcodeSize::Wide32)
24860 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
24861 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
24862 return true;
24863 }
24864 return false;
24865 }
24866
24867public:
24868 template<typename Block>
24869 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
24870 {
24871 dumper->printLocationAndOp(__location, &"**loop_hint"[2 - __sizeShiftAmount]);
24872
24873 }
24874
24875 OpLoopHint(const uint8_t* stream)
24876
24877 {
24878 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24879 }
24880
24881 OpLoopHint(const uint16_t* stream)
24882
24883 {
24884 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24885 }
24886
24887
24888 OpLoopHint(const uint32_t* stream)
24889
24890 {
24891 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24892 }
24893
24894 static OpLoopHint decode(const uint8_t* stream)
24895 {
24896 if (*stream == op_wide32)
24897 return { bitwise_cast<const uint32_t*>(stream + 1) };
24898 if (*stream == op_wide16)
24899 return { bitwise_cast<const uint16_t*>(stream + 1) };
24900 return { stream };
24901 }
24902
24903
24904
24905};
24906
24907struct OpSwitchImm : public Instruction {
24908 static constexpr OpcodeID opcodeID = op_switch_imm;
24909
24910 static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
24911 {
24912 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, tableIndex, defaultOffset, scrutinee);
24913 }
24914
24915 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
24916 static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
24917 {
24918 bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee);
24919 if (shouldAssert == Assert)
24920 ASSERT(didEmit);
24921 return didEmit;
24922 }
24923
24924 template<OpcodeSize size>
24925 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
24926 {
24927
24928 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
24929 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
24930 return;
24931 }
24932 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
24933 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
24934 return;
24935 }
24936 emit<OpcodeSize::Wide32, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
24937 }
24938
24939private:
24940 template<OpcodeSize size>
24941 static bool checkImpl(BytecodeGenerator* gen, unsigned& tableIndex, BoundLabel& defaultOffset, VirtualRegister& scrutinee)
24942 {
24943 UNUSED_PARAM(gen);
24944#if OS(WINDOWS) && ENABLE(C_LOOP)
24945 // FIXME: Disable wide16 optimization for Windows CLoop
24946 // https://bugs.webkit.org/show_bug.cgi?id=198283
24947 if (size == OpcodeSize::Wide16)
24948 return false;
24949#endif
24950 return Fits<OpcodeID, size>::check(opcodeID)
24951 && Fits<unsigned, size>::check(tableIndex)
24952 && Fits<BoundLabel, size>::check(defaultOffset)
24953 && Fits<VirtualRegister, size>::check(scrutinee)
24954 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
24955 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
24956 }
24957
24958 template<OpcodeSize size, bool recordOpcode>
24959 static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
24960 {
24961 if (size == OpcodeSize::Wide16)
24962 gen->alignWideOpcode16();
24963 else if (size == OpcodeSize::Wide32)
24964 gen->alignWideOpcode32();
24965 if (checkImpl<size>(gen, tableIndex, defaultOffset, scrutinee)) {
24966 if (recordOpcode)
24967 gen->recordOpcode(opcodeID);
24968 if (size == OpcodeSize::Wide16)
24969 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
24970 else if (size == OpcodeSize::Wide32)
24971 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
24972 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
24973 gen->write(Fits<unsigned, size>::convert(tableIndex));
24974 gen->write(Fits<BoundLabel, size>::convert(defaultOffset));
24975 gen->write(Fits<VirtualRegister, size>::convert(scrutinee));
24976 return true;
24977 }
24978 return false;
24979 }
24980
24981public:
24982 template<typename Block>
24983 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
24984 {
24985 dumper->printLocationAndOp(__location, &"**switch_imm"[2 - __sizeShiftAmount]);
24986 dumper->dumpOperand(m_tableIndex, true);
24987 dumper->dumpOperand(m_defaultOffset, false);
24988 dumper->dumpOperand(m_scrutinee, false);
24989 }
24990
24991 OpSwitchImm(const uint8_t* stream)
24992 : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
24993 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
24994 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
24995 {
24996 ASSERT_UNUSED(stream, stream[0] == opcodeID);
24997 }
24998
24999 OpSwitchImm(const uint16_t* stream)
25000 : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
25001 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
25002 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
25003 {
25004 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25005 }
25006
25007
25008 OpSwitchImm(const uint32_t* stream)
25009 : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
25010 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
25011 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
25012 {
25013 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25014 }
25015
25016 static OpSwitchImm decode(const uint8_t* stream)
25017 {
25018 if (*stream == op_wide32)
25019 return { bitwise_cast<const uint32_t*>(stream + 1) };
25020 if (*stream == op_wide16)
25021 return { bitwise_cast<const uint16_t*>(stream + 1) };
25022 return { stream };
25023 }
25024
25025 template<typename Functor>
25026 void setTableIndex(unsigned value, Functor func)
25027 {
25028 if (isWide32())
25029 setTableIndex<OpcodeSize::Wide32>(value, func);
25030 else if (isWide16())
25031 setTableIndex<OpcodeSize::Wide16>(value, func);
25032 else
25033 setTableIndex<OpcodeSize::Narrow>(value, func);
25034 }
25035
25036 template <OpcodeSize size, typename Functor>
25037 void setTableIndex(unsigned value, Functor func)
25038 {
25039 if (!Fits<unsigned, size>::check(value))
25040 value = func();
25041 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
25042 *stream = Fits<unsigned, size>::convert(value);
25043 }
25044
25045 template<typename Functor>
25046 void setDefaultOffset(BoundLabel value, Functor func)
25047 {
25048 if (isWide32())
25049 setDefaultOffset<OpcodeSize::Wide32>(value, func);
25050 else if (isWide16())
25051 setDefaultOffset<OpcodeSize::Wide16>(value, func);
25052 else
25053 setDefaultOffset<OpcodeSize::Narrow>(value, func);
25054 }
25055
25056 template <OpcodeSize size, typename Functor>
25057 void setDefaultOffset(BoundLabel value, Functor func)
25058 {
25059 if (!Fits<BoundLabel, size>::check(value))
25060 value = func();
25061 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
25062 *stream = Fits<BoundLabel, size>::convert(value);
25063 }
25064
25065 template<typename Functor>
25066 void setScrutinee(VirtualRegister value, Functor func)
25067 {
25068 if (isWide32())
25069 setScrutinee<OpcodeSize::Wide32>(value, func);
25070 else if (isWide16())
25071 setScrutinee<OpcodeSize::Wide16>(value, func);
25072 else
25073 setScrutinee<OpcodeSize::Narrow>(value, func);
25074 }
25075
25076 template <OpcodeSize size, typename Functor>
25077 void setScrutinee(VirtualRegister value, Functor func)
25078 {
25079 if (!Fits<VirtualRegister, size>::check(value))
25080 value = func();
25081 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
25082 *stream = Fits<VirtualRegister, size>::convert(value);
25083 }
25084
25085 unsigned m_tableIndex;
25086 BoundLabel m_defaultOffset;
25087 VirtualRegister m_scrutinee;
25088};
25089
25090struct OpSwitchChar : public Instruction {
25091 static constexpr OpcodeID opcodeID = op_switch_char;
25092
25093 static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25094 {
25095 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, tableIndex, defaultOffset, scrutinee);
25096 }
25097
25098 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
25099 static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25100 {
25101 bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee);
25102 if (shouldAssert == Assert)
25103 ASSERT(didEmit);
25104 return didEmit;
25105 }
25106
25107 template<OpcodeSize size>
25108 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25109 {
25110
25111 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
25112 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
25113 return;
25114 }
25115 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
25116 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
25117 return;
25118 }
25119 emit<OpcodeSize::Wide32, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
25120 }
25121
25122private:
25123 template<OpcodeSize size>
25124 static bool checkImpl(BytecodeGenerator* gen, unsigned& tableIndex, BoundLabel& defaultOffset, VirtualRegister& scrutinee)
25125 {
25126 UNUSED_PARAM(gen);
25127#if OS(WINDOWS) && ENABLE(C_LOOP)
25128 // FIXME: Disable wide16 optimization for Windows CLoop
25129 // https://bugs.webkit.org/show_bug.cgi?id=198283
25130 if (size == OpcodeSize::Wide16)
25131 return false;
25132#endif
25133 return Fits<OpcodeID, size>::check(opcodeID)
25134 && Fits<unsigned, size>::check(tableIndex)
25135 && Fits<BoundLabel, size>::check(defaultOffset)
25136 && Fits<VirtualRegister, size>::check(scrutinee)
25137 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
25138 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
25139 }
25140
25141 template<OpcodeSize size, bool recordOpcode>
25142 static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25143 {
25144 if (size == OpcodeSize::Wide16)
25145 gen->alignWideOpcode16();
25146 else if (size == OpcodeSize::Wide32)
25147 gen->alignWideOpcode32();
25148 if (checkImpl<size>(gen, tableIndex, defaultOffset, scrutinee)) {
25149 if (recordOpcode)
25150 gen->recordOpcode(opcodeID);
25151 if (size == OpcodeSize::Wide16)
25152 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
25153 else if (size == OpcodeSize::Wide32)
25154 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
25155 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
25156 gen->write(Fits<unsigned, size>::convert(tableIndex));
25157 gen->write(Fits<BoundLabel, size>::convert(defaultOffset));
25158 gen->write(Fits<VirtualRegister, size>::convert(scrutinee));
25159 return true;
25160 }
25161 return false;
25162 }
25163
25164public:
25165 template<typename Block>
25166 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
25167 {
25168 dumper->printLocationAndOp(__location, &"**switch_char"[2 - __sizeShiftAmount]);
25169 dumper->dumpOperand(m_tableIndex, true);
25170 dumper->dumpOperand(m_defaultOffset, false);
25171 dumper->dumpOperand(m_scrutinee, false);
25172 }
25173
25174 OpSwitchChar(const uint8_t* stream)
25175 : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
25176 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
25177 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
25178 {
25179 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25180 }
25181
25182 OpSwitchChar(const uint16_t* stream)
25183 : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
25184 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
25185 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
25186 {
25187 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25188 }
25189
25190
25191 OpSwitchChar(const uint32_t* stream)
25192 : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
25193 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
25194 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
25195 {
25196 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25197 }
25198
25199 static OpSwitchChar decode(const uint8_t* stream)
25200 {
25201 if (*stream == op_wide32)
25202 return { bitwise_cast<const uint32_t*>(stream + 1) };
25203 if (*stream == op_wide16)
25204 return { bitwise_cast<const uint16_t*>(stream + 1) };
25205 return { stream };
25206 }
25207
25208 template<typename Functor>
25209 void setTableIndex(unsigned value, Functor func)
25210 {
25211 if (isWide32())
25212 setTableIndex<OpcodeSize::Wide32>(value, func);
25213 else if (isWide16())
25214 setTableIndex<OpcodeSize::Wide16>(value, func);
25215 else
25216 setTableIndex<OpcodeSize::Narrow>(value, func);
25217 }
25218
25219 template <OpcodeSize size, typename Functor>
25220 void setTableIndex(unsigned value, Functor func)
25221 {
25222 if (!Fits<unsigned, size>::check(value))
25223 value = func();
25224 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
25225 *stream = Fits<unsigned, size>::convert(value);
25226 }
25227
25228 template<typename Functor>
25229 void setDefaultOffset(BoundLabel value, Functor func)
25230 {
25231 if (isWide32())
25232 setDefaultOffset<OpcodeSize::Wide32>(value, func);
25233 else if (isWide16())
25234 setDefaultOffset<OpcodeSize::Wide16>(value, func);
25235 else
25236 setDefaultOffset<OpcodeSize::Narrow>(value, func);
25237 }
25238
25239 template <OpcodeSize size, typename Functor>
25240 void setDefaultOffset(BoundLabel value, Functor func)
25241 {
25242 if (!Fits<BoundLabel, size>::check(value))
25243 value = func();
25244 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
25245 *stream = Fits<BoundLabel, size>::convert(value);
25246 }
25247
25248 template<typename Functor>
25249 void setScrutinee(VirtualRegister value, Functor func)
25250 {
25251 if (isWide32())
25252 setScrutinee<OpcodeSize::Wide32>(value, func);
25253 else if (isWide16())
25254 setScrutinee<OpcodeSize::Wide16>(value, func);
25255 else
25256 setScrutinee<OpcodeSize::Narrow>(value, func);
25257 }
25258
25259 template <OpcodeSize size, typename Functor>
25260 void setScrutinee(VirtualRegister value, Functor func)
25261 {
25262 if (!Fits<VirtualRegister, size>::check(value))
25263 value = func();
25264 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
25265 *stream = Fits<VirtualRegister, size>::convert(value);
25266 }
25267
25268 unsigned m_tableIndex;
25269 BoundLabel m_defaultOffset;
25270 VirtualRegister m_scrutinee;
25271};
25272
25273struct OpSwitchString : public Instruction {
25274 static constexpr OpcodeID opcodeID = op_switch_string;
25275
25276 static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25277 {
25278 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, tableIndex, defaultOffset, scrutinee);
25279 }
25280
25281 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
25282 static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25283 {
25284 bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee);
25285 if (shouldAssert == Assert)
25286 ASSERT(didEmit);
25287 return didEmit;
25288 }
25289
25290 template<OpcodeSize size>
25291 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25292 {
25293
25294 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
25295 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
25296 return;
25297 }
25298 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
25299 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
25300 return;
25301 }
25302 emit<OpcodeSize::Wide32, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
25303 }
25304
25305private:
25306 template<OpcodeSize size>
25307 static bool checkImpl(BytecodeGenerator* gen, unsigned& tableIndex, BoundLabel& defaultOffset, VirtualRegister& scrutinee)
25308 {
25309 UNUSED_PARAM(gen);
25310#if OS(WINDOWS) && ENABLE(C_LOOP)
25311 // FIXME: Disable wide16 optimization for Windows CLoop
25312 // https://bugs.webkit.org/show_bug.cgi?id=198283
25313 if (size == OpcodeSize::Wide16)
25314 return false;
25315#endif
25316 return Fits<OpcodeID, size>::check(opcodeID)
25317 && Fits<unsigned, size>::check(tableIndex)
25318 && Fits<BoundLabel, size>::check(defaultOffset)
25319 && Fits<VirtualRegister, size>::check(scrutinee)
25320 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
25321 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
25322 }
25323
25324 template<OpcodeSize size, bool recordOpcode>
25325 static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
25326 {
25327 if (size == OpcodeSize::Wide16)
25328 gen->alignWideOpcode16();
25329 else if (size == OpcodeSize::Wide32)
25330 gen->alignWideOpcode32();
25331 if (checkImpl<size>(gen, tableIndex, defaultOffset, scrutinee)) {
25332 if (recordOpcode)
25333 gen->recordOpcode(opcodeID);
25334 if (size == OpcodeSize::Wide16)
25335 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
25336 else if (size == OpcodeSize::Wide32)
25337 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
25338 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
25339 gen->write(Fits<unsigned, size>::convert(tableIndex));
25340 gen->write(Fits<BoundLabel, size>::convert(defaultOffset));
25341 gen->write(Fits<VirtualRegister, size>::convert(scrutinee));
25342 return true;
25343 }
25344 return false;
25345 }
25346
25347public:
25348 template<typename Block>
25349 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
25350 {
25351 dumper->printLocationAndOp(__location, &"**switch_string"[2 - __sizeShiftAmount]);
25352 dumper->dumpOperand(m_tableIndex, true);
25353 dumper->dumpOperand(m_defaultOffset, false);
25354 dumper->dumpOperand(m_scrutinee, false);
25355 }
25356
25357 OpSwitchString(const uint8_t* stream)
25358 : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
25359 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
25360 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
25361 {
25362 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25363 }
25364
25365 OpSwitchString(const uint16_t* stream)
25366 : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
25367 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
25368 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
25369 {
25370 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25371 }
25372
25373
25374 OpSwitchString(const uint32_t* stream)
25375 : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
25376 , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
25377 , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
25378 {
25379 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25380 }
25381
25382 static OpSwitchString decode(const uint8_t* stream)
25383 {
25384 if (*stream == op_wide32)
25385 return { bitwise_cast<const uint32_t*>(stream + 1) };
25386 if (*stream == op_wide16)
25387 return { bitwise_cast<const uint16_t*>(stream + 1) };
25388 return { stream };
25389 }
25390
25391 template<typename Functor>
25392 void setTableIndex(unsigned value, Functor func)
25393 {
25394 if (isWide32())
25395 setTableIndex<OpcodeSize::Wide32>(value, func);
25396 else if (isWide16())
25397 setTableIndex<OpcodeSize::Wide16>(value, func);
25398 else
25399 setTableIndex<OpcodeSize::Narrow>(value, func);
25400 }
25401
25402 template <OpcodeSize size, typename Functor>
25403 void setTableIndex(unsigned value, Functor func)
25404 {
25405 if (!Fits<unsigned, size>::check(value))
25406 value = func();
25407 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
25408 *stream = Fits<unsigned, size>::convert(value);
25409 }
25410
25411 template<typename Functor>
25412 void setDefaultOffset(BoundLabel value, Functor func)
25413 {
25414 if (isWide32())
25415 setDefaultOffset<OpcodeSize::Wide32>(value, func);
25416 else if (isWide16())
25417 setDefaultOffset<OpcodeSize::Wide16>(value, func);
25418 else
25419 setDefaultOffset<OpcodeSize::Narrow>(value, func);
25420 }
25421
25422 template <OpcodeSize size, typename Functor>
25423 void setDefaultOffset(BoundLabel value, Functor func)
25424 {
25425 if (!Fits<BoundLabel, size>::check(value))
25426 value = func();
25427 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
25428 *stream = Fits<BoundLabel, size>::convert(value);
25429 }
25430
25431 template<typename Functor>
25432 void setScrutinee(VirtualRegister value, Functor func)
25433 {
25434 if (isWide32())
25435 setScrutinee<OpcodeSize::Wide32>(value, func);
25436 else if (isWide16())
25437 setScrutinee<OpcodeSize::Wide16>(value, func);
25438 else
25439 setScrutinee<OpcodeSize::Narrow>(value, func);
25440 }
25441
25442 template <OpcodeSize size, typename Functor>
25443 void setScrutinee(VirtualRegister value, Functor func)
25444 {
25445 if (!Fits<VirtualRegister, size>::check(value))
25446 value = func();
25447 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
25448 *stream = Fits<VirtualRegister, size>::convert(value);
25449 }
25450
25451 unsigned m_tableIndex;
25452 BoundLabel m_defaultOffset;
25453 VirtualRegister m_scrutinee;
25454};
25455
25456struct OpNewFunc : public Instruction {
25457 static constexpr OpcodeID opcodeID = op_new_func;
25458
25459 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25460 {
25461 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
25462 }
25463
25464 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
25465 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25466 {
25467 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
25468 if (shouldAssert == Assert)
25469 ASSERT(didEmit);
25470 return didEmit;
25471 }
25472
25473 template<OpcodeSize size>
25474 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25475 {
25476
25477 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
25478 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
25479 return;
25480 }
25481 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
25482 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
25483 return;
25484 }
25485 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
25486 }
25487
25488private:
25489 template<OpcodeSize size>
25490 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
25491 {
25492 UNUSED_PARAM(gen);
25493#if OS(WINDOWS) && ENABLE(C_LOOP)
25494 // FIXME: Disable wide16 optimization for Windows CLoop
25495 // https://bugs.webkit.org/show_bug.cgi?id=198283
25496 if (size == OpcodeSize::Wide16)
25497 return false;
25498#endif
25499 return Fits<OpcodeID, size>::check(opcodeID)
25500 && Fits<VirtualRegister, size>::check(dst)
25501 && Fits<VirtualRegister, size>::check(scope)
25502 && Fits<unsigned, size>::check(functionDecl)
25503 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
25504 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
25505 }
25506
25507 template<OpcodeSize size, bool recordOpcode>
25508 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25509 {
25510 if (size == OpcodeSize::Wide16)
25511 gen->alignWideOpcode16();
25512 else if (size == OpcodeSize::Wide32)
25513 gen->alignWideOpcode32();
25514 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
25515 if (recordOpcode)
25516 gen->recordOpcode(opcodeID);
25517 if (size == OpcodeSize::Wide16)
25518 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
25519 else if (size == OpcodeSize::Wide32)
25520 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
25521 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
25522 gen->write(Fits<VirtualRegister, size>::convert(dst));
25523 gen->write(Fits<VirtualRegister, size>::convert(scope));
25524 gen->write(Fits<unsigned, size>::convert(functionDecl));
25525 return true;
25526 }
25527 return false;
25528 }
25529
25530public:
25531 template<typename Block>
25532 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
25533 {
25534 dumper->printLocationAndOp(__location, &"**new_func"[2 - __sizeShiftAmount]);
25535 dumper->dumpOperand(m_dst, true);
25536 dumper->dumpOperand(m_scope, false);
25537 dumper->dumpOperand(m_functionDecl, false);
25538 }
25539
25540 OpNewFunc(const uint8_t* stream)
25541 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
25542 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
25543 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
25544 {
25545 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25546 }
25547
25548 OpNewFunc(const uint16_t* stream)
25549 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
25550 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
25551 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
25552 {
25553 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25554 }
25555
25556
25557 OpNewFunc(const uint32_t* stream)
25558 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
25559 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
25560 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
25561 {
25562 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25563 }
25564
25565 static OpNewFunc decode(const uint8_t* stream)
25566 {
25567 if (*stream == op_wide32)
25568 return { bitwise_cast<const uint32_t*>(stream + 1) };
25569 if (*stream == op_wide16)
25570 return { bitwise_cast<const uint16_t*>(stream + 1) };
25571 return { stream };
25572 }
25573
25574 template<typename Functor>
25575 void setDst(VirtualRegister value, Functor func)
25576 {
25577 if (isWide32())
25578 setDst<OpcodeSize::Wide32>(value, func);
25579 else if (isWide16())
25580 setDst<OpcodeSize::Wide16>(value, func);
25581 else
25582 setDst<OpcodeSize::Narrow>(value, func);
25583 }
25584
25585 template <OpcodeSize size, typename Functor>
25586 void setDst(VirtualRegister value, Functor func)
25587 {
25588 if (!Fits<VirtualRegister, size>::check(value))
25589 value = func();
25590 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
25591 *stream = Fits<VirtualRegister, size>::convert(value);
25592 }
25593
25594 template<typename Functor>
25595 void setScope(VirtualRegister value, Functor func)
25596 {
25597 if (isWide32())
25598 setScope<OpcodeSize::Wide32>(value, func);
25599 else if (isWide16())
25600 setScope<OpcodeSize::Wide16>(value, func);
25601 else
25602 setScope<OpcodeSize::Narrow>(value, func);
25603 }
25604
25605 template <OpcodeSize size, typename Functor>
25606 void setScope(VirtualRegister value, Functor func)
25607 {
25608 if (!Fits<VirtualRegister, size>::check(value))
25609 value = func();
25610 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
25611 *stream = Fits<VirtualRegister, size>::convert(value);
25612 }
25613
25614 template<typename Functor>
25615 void setFunctionDecl(unsigned value, Functor func)
25616 {
25617 if (isWide32())
25618 setFunctionDecl<OpcodeSize::Wide32>(value, func);
25619 else if (isWide16())
25620 setFunctionDecl<OpcodeSize::Wide16>(value, func);
25621 else
25622 setFunctionDecl<OpcodeSize::Narrow>(value, func);
25623 }
25624
25625 template <OpcodeSize size, typename Functor>
25626 void setFunctionDecl(unsigned value, Functor func)
25627 {
25628 if (!Fits<unsigned, size>::check(value))
25629 value = func();
25630 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
25631 *stream = Fits<unsigned, size>::convert(value);
25632 }
25633
25634 VirtualRegister m_dst;
25635 VirtualRegister m_scope;
25636 unsigned m_functionDecl;
25637};
25638
25639struct OpNewFuncExp : public Instruction {
25640 static constexpr OpcodeID opcodeID = op_new_func_exp;
25641
25642 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25643 {
25644 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
25645 }
25646
25647 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
25648 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25649 {
25650 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
25651 if (shouldAssert == Assert)
25652 ASSERT(didEmit);
25653 return didEmit;
25654 }
25655
25656 template<OpcodeSize size>
25657 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25658 {
25659
25660 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
25661 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
25662 return;
25663 }
25664 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
25665 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
25666 return;
25667 }
25668 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
25669 }
25670
25671private:
25672 template<OpcodeSize size>
25673 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
25674 {
25675 UNUSED_PARAM(gen);
25676#if OS(WINDOWS) && ENABLE(C_LOOP)
25677 // FIXME: Disable wide16 optimization for Windows CLoop
25678 // https://bugs.webkit.org/show_bug.cgi?id=198283
25679 if (size == OpcodeSize::Wide16)
25680 return false;
25681#endif
25682 return Fits<OpcodeID, size>::check(opcodeID)
25683 && Fits<VirtualRegister, size>::check(dst)
25684 && Fits<VirtualRegister, size>::check(scope)
25685 && Fits<unsigned, size>::check(functionDecl)
25686 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
25687 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
25688 }
25689
25690 template<OpcodeSize size, bool recordOpcode>
25691 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25692 {
25693 if (size == OpcodeSize::Wide16)
25694 gen->alignWideOpcode16();
25695 else if (size == OpcodeSize::Wide32)
25696 gen->alignWideOpcode32();
25697 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
25698 if (recordOpcode)
25699 gen->recordOpcode(opcodeID);
25700 if (size == OpcodeSize::Wide16)
25701 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
25702 else if (size == OpcodeSize::Wide32)
25703 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
25704 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
25705 gen->write(Fits<VirtualRegister, size>::convert(dst));
25706 gen->write(Fits<VirtualRegister, size>::convert(scope));
25707 gen->write(Fits<unsigned, size>::convert(functionDecl));
25708 return true;
25709 }
25710 return false;
25711 }
25712
25713public:
25714 template<typename Block>
25715 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
25716 {
25717 dumper->printLocationAndOp(__location, &"**new_func_exp"[2 - __sizeShiftAmount]);
25718 dumper->dumpOperand(m_dst, true);
25719 dumper->dumpOperand(m_scope, false);
25720 dumper->dumpOperand(m_functionDecl, false);
25721 }
25722
25723 OpNewFuncExp(const uint8_t* stream)
25724 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
25725 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
25726 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
25727 {
25728 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25729 }
25730
25731 OpNewFuncExp(const uint16_t* stream)
25732 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
25733 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
25734 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
25735 {
25736 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25737 }
25738
25739
25740 OpNewFuncExp(const uint32_t* stream)
25741 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
25742 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
25743 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
25744 {
25745 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25746 }
25747
25748 static OpNewFuncExp decode(const uint8_t* stream)
25749 {
25750 if (*stream == op_wide32)
25751 return { bitwise_cast<const uint32_t*>(stream + 1) };
25752 if (*stream == op_wide16)
25753 return { bitwise_cast<const uint16_t*>(stream + 1) };
25754 return { stream };
25755 }
25756
25757 template<typename Functor>
25758 void setDst(VirtualRegister value, Functor func)
25759 {
25760 if (isWide32())
25761 setDst<OpcodeSize::Wide32>(value, func);
25762 else if (isWide16())
25763 setDst<OpcodeSize::Wide16>(value, func);
25764 else
25765 setDst<OpcodeSize::Narrow>(value, func);
25766 }
25767
25768 template <OpcodeSize size, typename Functor>
25769 void setDst(VirtualRegister value, Functor func)
25770 {
25771 if (!Fits<VirtualRegister, size>::check(value))
25772 value = func();
25773 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
25774 *stream = Fits<VirtualRegister, size>::convert(value);
25775 }
25776
25777 template<typename Functor>
25778 void setScope(VirtualRegister value, Functor func)
25779 {
25780 if (isWide32())
25781 setScope<OpcodeSize::Wide32>(value, func);
25782 else if (isWide16())
25783 setScope<OpcodeSize::Wide16>(value, func);
25784 else
25785 setScope<OpcodeSize::Narrow>(value, func);
25786 }
25787
25788 template <OpcodeSize size, typename Functor>
25789 void setScope(VirtualRegister value, Functor func)
25790 {
25791 if (!Fits<VirtualRegister, size>::check(value))
25792 value = func();
25793 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
25794 *stream = Fits<VirtualRegister, size>::convert(value);
25795 }
25796
25797 template<typename Functor>
25798 void setFunctionDecl(unsigned value, Functor func)
25799 {
25800 if (isWide32())
25801 setFunctionDecl<OpcodeSize::Wide32>(value, func);
25802 else if (isWide16())
25803 setFunctionDecl<OpcodeSize::Wide16>(value, func);
25804 else
25805 setFunctionDecl<OpcodeSize::Narrow>(value, func);
25806 }
25807
25808 template <OpcodeSize size, typename Functor>
25809 void setFunctionDecl(unsigned value, Functor func)
25810 {
25811 if (!Fits<unsigned, size>::check(value))
25812 value = func();
25813 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
25814 *stream = Fits<unsigned, size>::convert(value);
25815 }
25816
25817 VirtualRegister m_dst;
25818 VirtualRegister m_scope;
25819 unsigned m_functionDecl;
25820};
25821
25822struct OpNewGeneratorFunc : public Instruction {
25823 static constexpr OpcodeID opcodeID = op_new_generator_func;
25824
25825 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25826 {
25827 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
25828 }
25829
25830 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
25831 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25832 {
25833 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
25834 if (shouldAssert == Assert)
25835 ASSERT(didEmit);
25836 return didEmit;
25837 }
25838
25839 template<OpcodeSize size>
25840 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25841 {
25842
25843 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
25844 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
25845 return;
25846 }
25847 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
25848 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
25849 return;
25850 }
25851 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
25852 }
25853
25854private:
25855 template<OpcodeSize size>
25856 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
25857 {
25858 UNUSED_PARAM(gen);
25859#if OS(WINDOWS) && ENABLE(C_LOOP)
25860 // FIXME: Disable wide16 optimization for Windows CLoop
25861 // https://bugs.webkit.org/show_bug.cgi?id=198283
25862 if (size == OpcodeSize::Wide16)
25863 return false;
25864#endif
25865 return Fits<OpcodeID, size>::check(opcodeID)
25866 && Fits<VirtualRegister, size>::check(dst)
25867 && Fits<VirtualRegister, size>::check(scope)
25868 && Fits<unsigned, size>::check(functionDecl)
25869 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
25870 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
25871 }
25872
25873 template<OpcodeSize size, bool recordOpcode>
25874 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
25875 {
25876 if (size == OpcodeSize::Wide16)
25877 gen->alignWideOpcode16();
25878 else if (size == OpcodeSize::Wide32)
25879 gen->alignWideOpcode32();
25880 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
25881 if (recordOpcode)
25882 gen->recordOpcode(opcodeID);
25883 if (size == OpcodeSize::Wide16)
25884 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
25885 else if (size == OpcodeSize::Wide32)
25886 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
25887 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
25888 gen->write(Fits<VirtualRegister, size>::convert(dst));
25889 gen->write(Fits<VirtualRegister, size>::convert(scope));
25890 gen->write(Fits<unsigned, size>::convert(functionDecl));
25891 return true;
25892 }
25893 return false;
25894 }
25895
25896public:
25897 template<typename Block>
25898 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
25899 {
25900 dumper->printLocationAndOp(__location, &"**new_generator_func"[2 - __sizeShiftAmount]);
25901 dumper->dumpOperand(m_dst, true);
25902 dumper->dumpOperand(m_scope, false);
25903 dumper->dumpOperand(m_functionDecl, false);
25904 }
25905
25906 OpNewGeneratorFunc(const uint8_t* stream)
25907 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
25908 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
25909 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
25910 {
25911 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25912 }
25913
25914 OpNewGeneratorFunc(const uint16_t* stream)
25915 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
25916 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
25917 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
25918 {
25919 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25920 }
25921
25922
25923 OpNewGeneratorFunc(const uint32_t* stream)
25924 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
25925 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
25926 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
25927 {
25928 ASSERT_UNUSED(stream, stream[0] == opcodeID);
25929 }
25930
25931 static OpNewGeneratorFunc decode(const uint8_t* stream)
25932 {
25933 if (*stream == op_wide32)
25934 return { bitwise_cast<const uint32_t*>(stream + 1) };
25935 if (*stream == op_wide16)
25936 return { bitwise_cast<const uint16_t*>(stream + 1) };
25937 return { stream };
25938 }
25939
25940 template<typename Functor>
25941 void setDst(VirtualRegister value, Functor func)
25942 {
25943 if (isWide32())
25944 setDst<OpcodeSize::Wide32>(value, func);
25945 else if (isWide16())
25946 setDst<OpcodeSize::Wide16>(value, func);
25947 else
25948 setDst<OpcodeSize::Narrow>(value, func);
25949 }
25950
25951 template <OpcodeSize size, typename Functor>
25952 void setDst(VirtualRegister value, Functor func)
25953 {
25954 if (!Fits<VirtualRegister, size>::check(value))
25955 value = func();
25956 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
25957 *stream = Fits<VirtualRegister, size>::convert(value);
25958 }
25959
25960 template<typename Functor>
25961 void setScope(VirtualRegister value, Functor func)
25962 {
25963 if (isWide32())
25964 setScope<OpcodeSize::Wide32>(value, func);
25965 else if (isWide16())
25966 setScope<OpcodeSize::Wide16>(value, func);
25967 else
25968 setScope<OpcodeSize::Narrow>(value, func);
25969 }
25970
25971 template <OpcodeSize size, typename Functor>
25972 void setScope(VirtualRegister value, Functor func)
25973 {
25974 if (!Fits<VirtualRegister, size>::check(value))
25975 value = func();
25976 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
25977 *stream = Fits<VirtualRegister, size>::convert(value);
25978 }
25979
25980 template<typename Functor>
25981 void setFunctionDecl(unsigned value, Functor func)
25982 {
25983 if (isWide32())
25984 setFunctionDecl<OpcodeSize::Wide32>(value, func);
25985 else if (isWide16())
25986 setFunctionDecl<OpcodeSize::Wide16>(value, func);
25987 else
25988 setFunctionDecl<OpcodeSize::Narrow>(value, func);
25989 }
25990
25991 template <OpcodeSize size, typename Functor>
25992 void setFunctionDecl(unsigned value, Functor func)
25993 {
25994 if (!Fits<unsigned, size>::check(value))
25995 value = func();
25996 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
25997 *stream = Fits<unsigned, size>::convert(value);
25998 }
25999
26000 VirtualRegister m_dst;
26001 VirtualRegister m_scope;
26002 unsigned m_functionDecl;
26003};
26004
26005struct OpNewGeneratorFuncExp : public Instruction {
26006 static constexpr OpcodeID opcodeID = op_new_generator_func_exp;
26007
26008 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26009 {
26010 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
26011 }
26012
26013 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
26014 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26015 {
26016 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
26017 if (shouldAssert == Assert)
26018 ASSERT(didEmit);
26019 return didEmit;
26020 }
26021
26022 template<OpcodeSize size>
26023 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26024 {
26025
26026 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
26027 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
26028 return;
26029 }
26030 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
26031 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
26032 return;
26033 }
26034 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
26035 }
26036
26037private:
26038 template<OpcodeSize size>
26039 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
26040 {
26041 UNUSED_PARAM(gen);
26042#if OS(WINDOWS) && ENABLE(C_LOOP)
26043 // FIXME: Disable wide16 optimization for Windows CLoop
26044 // https://bugs.webkit.org/show_bug.cgi?id=198283
26045 if (size == OpcodeSize::Wide16)
26046 return false;
26047#endif
26048 return Fits<OpcodeID, size>::check(opcodeID)
26049 && Fits<VirtualRegister, size>::check(dst)
26050 && Fits<VirtualRegister, size>::check(scope)
26051 && Fits<unsigned, size>::check(functionDecl)
26052 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
26053 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
26054 }
26055
26056 template<OpcodeSize size, bool recordOpcode>
26057 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26058 {
26059 if (size == OpcodeSize::Wide16)
26060 gen->alignWideOpcode16();
26061 else if (size == OpcodeSize::Wide32)
26062 gen->alignWideOpcode32();
26063 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
26064 if (recordOpcode)
26065 gen->recordOpcode(opcodeID);
26066 if (size == OpcodeSize::Wide16)
26067 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
26068 else if (size == OpcodeSize::Wide32)
26069 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
26070 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
26071 gen->write(Fits<VirtualRegister, size>::convert(dst));
26072 gen->write(Fits<VirtualRegister, size>::convert(scope));
26073 gen->write(Fits<unsigned, size>::convert(functionDecl));
26074 return true;
26075 }
26076 return false;
26077 }
26078
26079public:
26080 template<typename Block>
26081 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
26082 {
26083 dumper->printLocationAndOp(__location, &"**new_generator_func_exp"[2 - __sizeShiftAmount]);
26084 dumper->dumpOperand(m_dst, true);
26085 dumper->dumpOperand(m_scope, false);
26086 dumper->dumpOperand(m_functionDecl, false);
26087 }
26088
26089 OpNewGeneratorFuncExp(const uint8_t* stream)
26090 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
26091 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
26092 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
26093 {
26094 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26095 }
26096
26097 OpNewGeneratorFuncExp(const uint16_t* stream)
26098 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
26099 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
26100 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
26101 {
26102 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26103 }
26104
26105
26106 OpNewGeneratorFuncExp(const uint32_t* stream)
26107 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
26108 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
26109 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
26110 {
26111 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26112 }
26113
26114 static OpNewGeneratorFuncExp decode(const uint8_t* stream)
26115 {
26116 if (*stream == op_wide32)
26117 return { bitwise_cast<const uint32_t*>(stream + 1) };
26118 if (*stream == op_wide16)
26119 return { bitwise_cast<const uint16_t*>(stream + 1) };
26120 return { stream };
26121 }
26122
26123 template<typename Functor>
26124 void setDst(VirtualRegister value, Functor func)
26125 {
26126 if (isWide32())
26127 setDst<OpcodeSize::Wide32>(value, func);
26128 else if (isWide16())
26129 setDst<OpcodeSize::Wide16>(value, func);
26130 else
26131 setDst<OpcodeSize::Narrow>(value, func);
26132 }
26133
26134 template <OpcodeSize size, typename Functor>
26135 void setDst(VirtualRegister value, Functor func)
26136 {
26137 if (!Fits<VirtualRegister, size>::check(value))
26138 value = func();
26139 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
26140 *stream = Fits<VirtualRegister, size>::convert(value);
26141 }
26142
26143 template<typename Functor>
26144 void setScope(VirtualRegister value, Functor func)
26145 {
26146 if (isWide32())
26147 setScope<OpcodeSize::Wide32>(value, func);
26148 else if (isWide16())
26149 setScope<OpcodeSize::Wide16>(value, func);
26150 else
26151 setScope<OpcodeSize::Narrow>(value, func);
26152 }
26153
26154 template <OpcodeSize size, typename Functor>
26155 void setScope(VirtualRegister value, Functor func)
26156 {
26157 if (!Fits<VirtualRegister, size>::check(value))
26158 value = func();
26159 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
26160 *stream = Fits<VirtualRegister, size>::convert(value);
26161 }
26162
26163 template<typename Functor>
26164 void setFunctionDecl(unsigned value, Functor func)
26165 {
26166 if (isWide32())
26167 setFunctionDecl<OpcodeSize::Wide32>(value, func);
26168 else if (isWide16())
26169 setFunctionDecl<OpcodeSize::Wide16>(value, func);
26170 else
26171 setFunctionDecl<OpcodeSize::Narrow>(value, func);
26172 }
26173
26174 template <OpcodeSize size, typename Functor>
26175 void setFunctionDecl(unsigned value, Functor func)
26176 {
26177 if (!Fits<unsigned, size>::check(value))
26178 value = func();
26179 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
26180 *stream = Fits<unsigned, size>::convert(value);
26181 }
26182
26183 VirtualRegister m_dst;
26184 VirtualRegister m_scope;
26185 unsigned m_functionDecl;
26186};
26187
26188struct OpNewAsyncFunc : public Instruction {
26189 static constexpr OpcodeID opcodeID = op_new_async_func;
26190
26191 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26192 {
26193 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
26194 }
26195
26196 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
26197 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26198 {
26199 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
26200 if (shouldAssert == Assert)
26201 ASSERT(didEmit);
26202 return didEmit;
26203 }
26204
26205 template<OpcodeSize size>
26206 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26207 {
26208
26209 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
26210 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
26211 return;
26212 }
26213 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
26214 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
26215 return;
26216 }
26217 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
26218 }
26219
26220private:
26221 template<OpcodeSize size>
26222 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
26223 {
26224 UNUSED_PARAM(gen);
26225#if OS(WINDOWS) && ENABLE(C_LOOP)
26226 // FIXME: Disable wide16 optimization for Windows CLoop
26227 // https://bugs.webkit.org/show_bug.cgi?id=198283
26228 if (size == OpcodeSize::Wide16)
26229 return false;
26230#endif
26231 return Fits<OpcodeID, size>::check(opcodeID)
26232 && Fits<VirtualRegister, size>::check(dst)
26233 && Fits<VirtualRegister, size>::check(scope)
26234 && Fits<unsigned, size>::check(functionDecl)
26235 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
26236 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
26237 }
26238
26239 template<OpcodeSize size, bool recordOpcode>
26240 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26241 {
26242 if (size == OpcodeSize::Wide16)
26243 gen->alignWideOpcode16();
26244 else if (size == OpcodeSize::Wide32)
26245 gen->alignWideOpcode32();
26246 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
26247 if (recordOpcode)
26248 gen->recordOpcode(opcodeID);
26249 if (size == OpcodeSize::Wide16)
26250 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
26251 else if (size == OpcodeSize::Wide32)
26252 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
26253 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
26254 gen->write(Fits<VirtualRegister, size>::convert(dst));
26255 gen->write(Fits<VirtualRegister, size>::convert(scope));
26256 gen->write(Fits<unsigned, size>::convert(functionDecl));
26257 return true;
26258 }
26259 return false;
26260 }
26261
26262public:
26263 template<typename Block>
26264 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
26265 {
26266 dumper->printLocationAndOp(__location, &"**new_async_func"[2 - __sizeShiftAmount]);
26267 dumper->dumpOperand(m_dst, true);
26268 dumper->dumpOperand(m_scope, false);
26269 dumper->dumpOperand(m_functionDecl, false);
26270 }
26271
26272 OpNewAsyncFunc(const uint8_t* stream)
26273 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
26274 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
26275 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
26276 {
26277 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26278 }
26279
26280 OpNewAsyncFunc(const uint16_t* stream)
26281 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
26282 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
26283 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
26284 {
26285 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26286 }
26287
26288
26289 OpNewAsyncFunc(const uint32_t* stream)
26290 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
26291 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
26292 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
26293 {
26294 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26295 }
26296
26297 static OpNewAsyncFunc decode(const uint8_t* stream)
26298 {
26299 if (*stream == op_wide32)
26300 return { bitwise_cast<const uint32_t*>(stream + 1) };
26301 if (*stream == op_wide16)
26302 return { bitwise_cast<const uint16_t*>(stream + 1) };
26303 return { stream };
26304 }
26305
26306 template<typename Functor>
26307 void setDst(VirtualRegister value, Functor func)
26308 {
26309 if (isWide32())
26310 setDst<OpcodeSize::Wide32>(value, func);
26311 else if (isWide16())
26312 setDst<OpcodeSize::Wide16>(value, func);
26313 else
26314 setDst<OpcodeSize::Narrow>(value, func);
26315 }
26316
26317 template <OpcodeSize size, typename Functor>
26318 void setDst(VirtualRegister value, Functor func)
26319 {
26320 if (!Fits<VirtualRegister, size>::check(value))
26321 value = func();
26322 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
26323 *stream = Fits<VirtualRegister, size>::convert(value);
26324 }
26325
26326 template<typename Functor>
26327 void setScope(VirtualRegister value, Functor func)
26328 {
26329 if (isWide32())
26330 setScope<OpcodeSize::Wide32>(value, func);
26331 else if (isWide16())
26332 setScope<OpcodeSize::Wide16>(value, func);
26333 else
26334 setScope<OpcodeSize::Narrow>(value, func);
26335 }
26336
26337 template <OpcodeSize size, typename Functor>
26338 void setScope(VirtualRegister value, Functor func)
26339 {
26340 if (!Fits<VirtualRegister, size>::check(value))
26341 value = func();
26342 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
26343 *stream = Fits<VirtualRegister, size>::convert(value);
26344 }
26345
26346 template<typename Functor>
26347 void setFunctionDecl(unsigned value, Functor func)
26348 {
26349 if (isWide32())
26350 setFunctionDecl<OpcodeSize::Wide32>(value, func);
26351 else if (isWide16())
26352 setFunctionDecl<OpcodeSize::Wide16>(value, func);
26353 else
26354 setFunctionDecl<OpcodeSize::Narrow>(value, func);
26355 }
26356
26357 template <OpcodeSize size, typename Functor>
26358 void setFunctionDecl(unsigned value, Functor func)
26359 {
26360 if (!Fits<unsigned, size>::check(value))
26361 value = func();
26362 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
26363 *stream = Fits<unsigned, size>::convert(value);
26364 }
26365
26366 VirtualRegister m_dst;
26367 VirtualRegister m_scope;
26368 unsigned m_functionDecl;
26369};
26370
26371struct OpNewAsyncFuncExp : public Instruction {
26372 static constexpr OpcodeID opcodeID = op_new_async_func_exp;
26373
26374 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26375 {
26376 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
26377 }
26378
26379 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
26380 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26381 {
26382 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
26383 if (shouldAssert == Assert)
26384 ASSERT(didEmit);
26385 return didEmit;
26386 }
26387
26388 template<OpcodeSize size>
26389 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26390 {
26391
26392 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
26393 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
26394 return;
26395 }
26396 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
26397 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
26398 return;
26399 }
26400 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
26401 }
26402
26403private:
26404 template<OpcodeSize size>
26405 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
26406 {
26407 UNUSED_PARAM(gen);
26408#if OS(WINDOWS) && ENABLE(C_LOOP)
26409 // FIXME: Disable wide16 optimization for Windows CLoop
26410 // https://bugs.webkit.org/show_bug.cgi?id=198283
26411 if (size == OpcodeSize::Wide16)
26412 return false;
26413#endif
26414 return Fits<OpcodeID, size>::check(opcodeID)
26415 && Fits<VirtualRegister, size>::check(dst)
26416 && Fits<VirtualRegister, size>::check(scope)
26417 && Fits<unsigned, size>::check(functionDecl)
26418 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
26419 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
26420 }
26421
26422 template<OpcodeSize size, bool recordOpcode>
26423 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26424 {
26425 if (size == OpcodeSize::Wide16)
26426 gen->alignWideOpcode16();
26427 else if (size == OpcodeSize::Wide32)
26428 gen->alignWideOpcode32();
26429 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
26430 if (recordOpcode)
26431 gen->recordOpcode(opcodeID);
26432 if (size == OpcodeSize::Wide16)
26433 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
26434 else if (size == OpcodeSize::Wide32)
26435 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
26436 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
26437 gen->write(Fits<VirtualRegister, size>::convert(dst));
26438 gen->write(Fits<VirtualRegister, size>::convert(scope));
26439 gen->write(Fits<unsigned, size>::convert(functionDecl));
26440 return true;
26441 }
26442 return false;
26443 }
26444
26445public:
26446 template<typename Block>
26447 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
26448 {
26449 dumper->printLocationAndOp(__location, &"**new_async_func_exp"[2 - __sizeShiftAmount]);
26450 dumper->dumpOperand(m_dst, true);
26451 dumper->dumpOperand(m_scope, false);
26452 dumper->dumpOperand(m_functionDecl, false);
26453 }
26454
26455 OpNewAsyncFuncExp(const uint8_t* stream)
26456 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
26457 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
26458 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
26459 {
26460 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26461 }
26462
26463 OpNewAsyncFuncExp(const uint16_t* stream)
26464 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
26465 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
26466 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
26467 {
26468 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26469 }
26470
26471
26472 OpNewAsyncFuncExp(const uint32_t* stream)
26473 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
26474 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
26475 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
26476 {
26477 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26478 }
26479
26480 static OpNewAsyncFuncExp decode(const uint8_t* stream)
26481 {
26482 if (*stream == op_wide32)
26483 return { bitwise_cast<const uint32_t*>(stream + 1) };
26484 if (*stream == op_wide16)
26485 return { bitwise_cast<const uint16_t*>(stream + 1) };
26486 return { stream };
26487 }
26488
26489 template<typename Functor>
26490 void setDst(VirtualRegister value, Functor func)
26491 {
26492 if (isWide32())
26493 setDst<OpcodeSize::Wide32>(value, func);
26494 else if (isWide16())
26495 setDst<OpcodeSize::Wide16>(value, func);
26496 else
26497 setDst<OpcodeSize::Narrow>(value, func);
26498 }
26499
26500 template <OpcodeSize size, typename Functor>
26501 void setDst(VirtualRegister value, Functor func)
26502 {
26503 if (!Fits<VirtualRegister, size>::check(value))
26504 value = func();
26505 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
26506 *stream = Fits<VirtualRegister, size>::convert(value);
26507 }
26508
26509 template<typename Functor>
26510 void setScope(VirtualRegister value, Functor func)
26511 {
26512 if (isWide32())
26513 setScope<OpcodeSize::Wide32>(value, func);
26514 else if (isWide16())
26515 setScope<OpcodeSize::Wide16>(value, func);
26516 else
26517 setScope<OpcodeSize::Narrow>(value, func);
26518 }
26519
26520 template <OpcodeSize size, typename Functor>
26521 void setScope(VirtualRegister value, Functor func)
26522 {
26523 if (!Fits<VirtualRegister, size>::check(value))
26524 value = func();
26525 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
26526 *stream = Fits<VirtualRegister, size>::convert(value);
26527 }
26528
26529 template<typename Functor>
26530 void setFunctionDecl(unsigned value, Functor func)
26531 {
26532 if (isWide32())
26533 setFunctionDecl<OpcodeSize::Wide32>(value, func);
26534 else if (isWide16())
26535 setFunctionDecl<OpcodeSize::Wide16>(value, func);
26536 else
26537 setFunctionDecl<OpcodeSize::Narrow>(value, func);
26538 }
26539
26540 template <OpcodeSize size, typename Functor>
26541 void setFunctionDecl(unsigned value, Functor func)
26542 {
26543 if (!Fits<unsigned, size>::check(value))
26544 value = func();
26545 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
26546 *stream = Fits<unsigned, size>::convert(value);
26547 }
26548
26549 VirtualRegister m_dst;
26550 VirtualRegister m_scope;
26551 unsigned m_functionDecl;
26552};
26553
26554struct OpNewAsyncGeneratorFunc : public Instruction {
26555 static constexpr OpcodeID opcodeID = op_new_async_generator_func;
26556
26557 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26558 {
26559 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
26560 }
26561
26562 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
26563 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26564 {
26565 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
26566 if (shouldAssert == Assert)
26567 ASSERT(didEmit);
26568 return didEmit;
26569 }
26570
26571 template<OpcodeSize size>
26572 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26573 {
26574
26575 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
26576 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
26577 return;
26578 }
26579 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
26580 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
26581 return;
26582 }
26583 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
26584 }
26585
26586private:
26587 template<OpcodeSize size>
26588 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
26589 {
26590 UNUSED_PARAM(gen);
26591#if OS(WINDOWS) && ENABLE(C_LOOP)
26592 // FIXME: Disable wide16 optimization for Windows CLoop
26593 // https://bugs.webkit.org/show_bug.cgi?id=198283
26594 if (size == OpcodeSize::Wide16)
26595 return false;
26596#endif
26597 return Fits<OpcodeID, size>::check(opcodeID)
26598 && Fits<VirtualRegister, size>::check(dst)
26599 && Fits<VirtualRegister, size>::check(scope)
26600 && Fits<unsigned, size>::check(functionDecl)
26601 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
26602 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
26603 }
26604
26605 template<OpcodeSize size, bool recordOpcode>
26606 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26607 {
26608 if (size == OpcodeSize::Wide16)
26609 gen->alignWideOpcode16();
26610 else if (size == OpcodeSize::Wide32)
26611 gen->alignWideOpcode32();
26612 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
26613 if (recordOpcode)
26614 gen->recordOpcode(opcodeID);
26615 if (size == OpcodeSize::Wide16)
26616 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
26617 else if (size == OpcodeSize::Wide32)
26618 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
26619 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
26620 gen->write(Fits<VirtualRegister, size>::convert(dst));
26621 gen->write(Fits<VirtualRegister, size>::convert(scope));
26622 gen->write(Fits<unsigned, size>::convert(functionDecl));
26623 return true;
26624 }
26625 return false;
26626 }
26627
26628public:
26629 template<typename Block>
26630 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
26631 {
26632 dumper->printLocationAndOp(__location, &"**new_async_generator_func"[2 - __sizeShiftAmount]);
26633 dumper->dumpOperand(m_dst, true);
26634 dumper->dumpOperand(m_scope, false);
26635 dumper->dumpOperand(m_functionDecl, false);
26636 }
26637
26638 OpNewAsyncGeneratorFunc(const uint8_t* stream)
26639 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
26640 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
26641 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
26642 {
26643 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26644 }
26645
26646 OpNewAsyncGeneratorFunc(const uint16_t* stream)
26647 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
26648 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
26649 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
26650 {
26651 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26652 }
26653
26654
26655 OpNewAsyncGeneratorFunc(const uint32_t* stream)
26656 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
26657 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
26658 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
26659 {
26660 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26661 }
26662
26663 static OpNewAsyncGeneratorFunc decode(const uint8_t* stream)
26664 {
26665 if (*stream == op_wide32)
26666 return { bitwise_cast<const uint32_t*>(stream + 1) };
26667 if (*stream == op_wide16)
26668 return { bitwise_cast<const uint16_t*>(stream + 1) };
26669 return { stream };
26670 }
26671
26672 template<typename Functor>
26673 void setDst(VirtualRegister value, Functor func)
26674 {
26675 if (isWide32())
26676 setDst<OpcodeSize::Wide32>(value, func);
26677 else if (isWide16())
26678 setDst<OpcodeSize::Wide16>(value, func);
26679 else
26680 setDst<OpcodeSize::Narrow>(value, func);
26681 }
26682
26683 template <OpcodeSize size, typename Functor>
26684 void setDst(VirtualRegister value, Functor func)
26685 {
26686 if (!Fits<VirtualRegister, size>::check(value))
26687 value = func();
26688 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
26689 *stream = Fits<VirtualRegister, size>::convert(value);
26690 }
26691
26692 template<typename Functor>
26693 void setScope(VirtualRegister value, Functor func)
26694 {
26695 if (isWide32())
26696 setScope<OpcodeSize::Wide32>(value, func);
26697 else if (isWide16())
26698 setScope<OpcodeSize::Wide16>(value, func);
26699 else
26700 setScope<OpcodeSize::Narrow>(value, func);
26701 }
26702
26703 template <OpcodeSize size, typename Functor>
26704 void setScope(VirtualRegister value, Functor func)
26705 {
26706 if (!Fits<VirtualRegister, size>::check(value))
26707 value = func();
26708 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
26709 *stream = Fits<VirtualRegister, size>::convert(value);
26710 }
26711
26712 template<typename Functor>
26713 void setFunctionDecl(unsigned value, Functor func)
26714 {
26715 if (isWide32())
26716 setFunctionDecl<OpcodeSize::Wide32>(value, func);
26717 else if (isWide16())
26718 setFunctionDecl<OpcodeSize::Wide16>(value, func);
26719 else
26720 setFunctionDecl<OpcodeSize::Narrow>(value, func);
26721 }
26722
26723 template <OpcodeSize size, typename Functor>
26724 void setFunctionDecl(unsigned value, Functor func)
26725 {
26726 if (!Fits<unsigned, size>::check(value))
26727 value = func();
26728 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
26729 *stream = Fits<unsigned, size>::convert(value);
26730 }
26731
26732 VirtualRegister m_dst;
26733 VirtualRegister m_scope;
26734 unsigned m_functionDecl;
26735};
26736
26737struct OpNewAsyncGeneratorFuncExp : public Instruction {
26738 static constexpr OpcodeID opcodeID = op_new_async_generator_func_exp;
26739
26740 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26741 {
26742 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
26743 }
26744
26745 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
26746 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26747 {
26748 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, functionDecl);
26749 if (shouldAssert == Assert)
26750 ASSERT(didEmit);
26751 return didEmit;
26752 }
26753
26754 template<OpcodeSize size>
26755 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26756 {
26757
26758 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
26759 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, functionDecl))
26760 return;
26761 }
26762 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
26763 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
26764 return;
26765 }
26766 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
26767 }
26768
26769private:
26770 template<OpcodeSize size>
26771 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
26772 {
26773 UNUSED_PARAM(gen);
26774#if OS(WINDOWS) && ENABLE(C_LOOP)
26775 // FIXME: Disable wide16 optimization for Windows CLoop
26776 // https://bugs.webkit.org/show_bug.cgi?id=198283
26777 if (size == OpcodeSize::Wide16)
26778 return false;
26779#endif
26780 return Fits<OpcodeID, size>::check(opcodeID)
26781 && Fits<VirtualRegister, size>::check(dst)
26782 && Fits<VirtualRegister, size>::check(scope)
26783 && Fits<unsigned, size>::check(functionDecl)
26784 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
26785 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
26786 }
26787
26788 template<OpcodeSize size, bool recordOpcode>
26789 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
26790 {
26791 if (size == OpcodeSize::Wide16)
26792 gen->alignWideOpcode16();
26793 else if (size == OpcodeSize::Wide32)
26794 gen->alignWideOpcode32();
26795 if (checkImpl<size>(gen, dst, scope, functionDecl)) {
26796 if (recordOpcode)
26797 gen->recordOpcode(opcodeID);
26798 if (size == OpcodeSize::Wide16)
26799 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
26800 else if (size == OpcodeSize::Wide32)
26801 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
26802 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
26803 gen->write(Fits<VirtualRegister, size>::convert(dst));
26804 gen->write(Fits<VirtualRegister, size>::convert(scope));
26805 gen->write(Fits<unsigned, size>::convert(functionDecl));
26806 return true;
26807 }
26808 return false;
26809 }
26810
26811public:
26812 template<typename Block>
26813 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
26814 {
26815 dumper->printLocationAndOp(__location, &"**new_async_generator_func_exp"[2 - __sizeShiftAmount]);
26816 dumper->dumpOperand(m_dst, true);
26817 dumper->dumpOperand(m_scope, false);
26818 dumper->dumpOperand(m_functionDecl, false);
26819 }
26820
26821 OpNewAsyncGeneratorFuncExp(const uint8_t* stream)
26822 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
26823 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
26824 , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
26825 {
26826 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26827 }
26828
26829 OpNewAsyncGeneratorFuncExp(const uint16_t* stream)
26830 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
26831 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
26832 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
26833 {
26834 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26835 }
26836
26837
26838 OpNewAsyncGeneratorFuncExp(const uint32_t* stream)
26839 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
26840 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
26841 , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
26842 {
26843 ASSERT_UNUSED(stream, stream[0] == opcodeID);
26844 }
26845
26846 static OpNewAsyncGeneratorFuncExp decode(const uint8_t* stream)
26847 {
26848 if (*stream == op_wide32)
26849 return { bitwise_cast<const uint32_t*>(stream + 1) };
26850 if (*stream == op_wide16)
26851 return { bitwise_cast<const uint16_t*>(stream + 1) };
26852 return { stream };
26853 }
26854
26855 template<typename Functor>
26856 void setDst(VirtualRegister value, Functor func)
26857 {
26858 if (isWide32())
26859 setDst<OpcodeSize::Wide32>(value, func);
26860 else if (isWide16())
26861 setDst<OpcodeSize::Wide16>(value, func);
26862 else
26863 setDst<OpcodeSize::Narrow>(value, func);
26864 }
26865
26866 template <OpcodeSize size, typename Functor>
26867 void setDst(VirtualRegister value, Functor func)
26868 {
26869 if (!Fits<VirtualRegister, size>::check(value))
26870 value = func();
26871 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
26872 *stream = Fits<VirtualRegister, size>::convert(value);
26873 }
26874
26875 template<typename Functor>
26876 void setScope(VirtualRegister value, Functor func)
26877 {
26878 if (isWide32())
26879 setScope<OpcodeSize::Wide32>(value, func);
26880 else if (isWide16())
26881 setScope<OpcodeSize::Wide16>(value, func);
26882 else
26883 setScope<OpcodeSize::Narrow>(value, func);
26884 }
26885
26886 template <OpcodeSize size, typename Functor>
26887 void setScope(VirtualRegister value, Functor func)
26888 {
26889 if (!Fits<VirtualRegister, size>::check(value))
26890 value = func();
26891 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
26892 *stream = Fits<VirtualRegister, size>::convert(value);
26893 }
26894
26895 template<typename Functor>
26896 void setFunctionDecl(unsigned value, Functor func)
26897 {
26898 if (isWide32())
26899 setFunctionDecl<OpcodeSize::Wide32>(value, func);
26900 else if (isWide16())
26901 setFunctionDecl<OpcodeSize::Wide16>(value, func);
26902 else
26903 setFunctionDecl<OpcodeSize::Narrow>(value, func);
26904 }
26905
26906 template <OpcodeSize size, typename Functor>
26907 void setFunctionDecl(unsigned value, Functor func)
26908 {
26909 if (!Fits<unsigned, size>::check(value))
26910 value = func();
26911 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
26912 *stream = Fits<unsigned, size>::convert(value);
26913 }
26914
26915 VirtualRegister m_dst;
26916 VirtualRegister m_scope;
26917 unsigned m_functionDecl;
26918};
26919
26920struct OpSetFunctionName : public Instruction {
26921 static constexpr OpcodeID opcodeID = op_set_function_name;
26922
26923 static void emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
26924 {
26925 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, function, name);
26926 }
26927
26928 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
26929 static bool emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
26930 {
26931 bool didEmit = emitImpl<size, recordOpcode>(gen, function, name);
26932 if (shouldAssert == Assert)
26933 ASSERT(didEmit);
26934 return didEmit;
26935 }
26936
26937 template<OpcodeSize size>
26938 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
26939 {
26940
26941 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
26942 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, function, name))
26943 return;
26944 }
26945 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
26946 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, function, name))
26947 return;
26948 }
26949 emit<OpcodeSize::Wide32, Assert, true>(gen, function, name);
26950 }
26951
26952private:
26953 template<OpcodeSize size>
26954 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& function, VirtualRegister& name)
26955 {
26956 UNUSED_PARAM(gen);
26957#if OS(WINDOWS) && ENABLE(C_LOOP)
26958 // FIXME: Disable wide16 optimization for Windows CLoop
26959 // https://bugs.webkit.org/show_bug.cgi?id=198283
26960 if (size == OpcodeSize::Wide16)
26961 return false;
26962#endif
26963 return Fits<OpcodeID, size>::check(opcodeID)
26964 && Fits<VirtualRegister, size>::check(function)
26965 && Fits<VirtualRegister, size>::check(name)
26966 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
26967 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
26968 }
26969
26970 template<OpcodeSize size, bool recordOpcode>
26971 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
26972 {
26973 if (size == OpcodeSize::Wide16)
26974 gen->alignWideOpcode16();
26975 else if (size == OpcodeSize::Wide32)
26976 gen->alignWideOpcode32();
26977 if (checkImpl<size>(gen, function, name)) {
26978 if (recordOpcode)
26979 gen->recordOpcode(opcodeID);
26980 if (size == OpcodeSize::Wide16)
26981 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
26982 else if (size == OpcodeSize::Wide32)
26983 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
26984 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
26985 gen->write(Fits<VirtualRegister, size>::convert(function));
26986 gen->write(Fits<VirtualRegister, size>::convert(name));
26987 return true;
26988 }
26989 return false;
26990 }
26991
26992public:
26993 template<typename Block>
26994 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
26995 {
26996 dumper->printLocationAndOp(__location, &"**set_function_name"[2 - __sizeShiftAmount]);
26997 dumper->dumpOperand(m_function, true);
26998 dumper->dumpOperand(m_name, false);
26999 }
27000
27001 OpSetFunctionName(const uint8_t* stream)
27002 : m_function(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
27003 , m_name(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
27004 {
27005 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27006 }
27007
27008 OpSetFunctionName(const uint16_t* stream)
27009 : m_function(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
27010 , m_name(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
27011 {
27012 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27013 }
27014
27015
27016 OpSetFunctionName(const uint32_t* stream)
27017 : m_function(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
27018 , m_name(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
27019 {
27020 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27021 }
27022
27023 static OpSetFunctionName decode(const uint8_t* stream)
27024 {
27025 if (*stream == op_wide32)
27026 return { bitwise_cast<const uint32_t*>(stream + 1) };
27027 if (*stream == op_wide16)
27028 return { bitwise_cast<const uint16_t*>(stream + 1) };
27029 return { stream };
27030 }
27031
27032 template<typename Functor>
27033 void setFunction(VirtualRegister value, Functor func)
27034 {
27035 if (isWide32())
27036 setFunction<OpcodeSize::Wide32>(value, func);
27037 else if (isWide16())
27038 setFunction<OpcodeSize::Wide16>(value, func);
27039 else
27040 setFunction<OpcodeSize::Narrow>(value, func);
27041 }
27042
27043 template <OpcodeSize size, typename Functor>
27044 void setFunction(VirtualRegister value, Functor func)
27045 {
27046 if (!Fits<VirtualRegister, size>::check(value))
27047 value = func();
27048 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
27049 *stream = Fits<VirtualRegister, size>::convert(value);
27050 }
27051
27052 template<typename Functor>
27053 void setName(VirtualRegister value, Functor func)
27054 {
27055 if (isWide32())
27056 setName<OpcodeSize::Wide32>(value, func);
27057 else if (isWide16())
27058 setName<OpcodeSize::Wide16>(value, func);
27059 else
27060 setName<OpcodeSize::Narrow>(value, func);
27061 }
27062
27063 template <OpcodeSize size, typename Functor>
27064 void setName(VirtualRegister value, Functor func)
27065 {
27066 if (!Fits<VirtualRegister, size>::check(value))
27067 value = func();
27068 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
27069 *stream = Fits<VirtualRegister, size>::convert(value);
27070 }
27071
27072 VirtualRegister m_function;
27073 VirtualRegister m_name;
27074};
27075
27076struct OpRet : public Instruction {
27077 static constexpr OpcodeID opcodeID = op_ret;
27078
27079 static void emit(BytecodeGenerator* gen, VirtualRegister value)
27080 {
27081 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, value);
27082 }
27083
27084 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
27085 static bool emit(BytecodeGenerator* gen, VirtualRegister value)
27086 {
27087 bool didEmit = emitImpl<size, recordOpcode>(gen, value);
27088 if (shouldAssert == Assert)
27089 ASSERT(didEmit);
27090 return didEmit;
27091 }
27092
27093 template<OpcodeSize size>
27094 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
27095 {
27096
27097 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
27098 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value))
27099 return;
27100 }
27101 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
27102 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value))
27103 return;
27104 }
27105 emit<OpcodeSize::Wide32, Assert, true>(gen, value);
27106 }
27107
27108private:
27109 template<OpcodeSize size>
27110 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value)
27111 {
27112 UNUSED_PARAM(gen);
27113#if OS(WINDOWS) && ENABLE(C_LOOP)
27114 // FIXME: Disable wide16 optimization for Windows CLoop
27115 // https://bugs.webkit.org/show_bug.cgi?id=198283
27116 if (size == OpcodeSize::Wide16)
27117 return false;
27118#endif
27119 return Fits<OpcodeID, size>::check(opcodeID)
27120 && Fits<VirtualRegister, size>::check(value)
27121 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
27122 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
27123 }
27124
27125 template<OpcodeSize size, bool recordOpcode>
27126 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value)
27127 {
27128 if (size == OpcodeSize::Wide16)
27129 gen->alignWideOpcode16();
27130 else if (size == OpcodeSize::Wide32)
27131 gen->alignWideOpcode32();
27132 if (checkImpl<size>(gen, value)) {
27133 if (recordOpcode)
27134 gen->recordOpcode(opcodeID);
27135 if (size == OpcodeSize::Wide16)
27136 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
27137 else if (size == OpcodeSize::Wide32)
27138 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
27139 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
27140 gen->write(Fits<VirtualRegister, size>::convert(value));
27141 return true;
27142 }
27143 return false;
27144 }
27145
27146public:
27147 template<typename Block>
27148 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
27149 {
27150 dumper->printLocationAndOp(__location, &"**ret"[2 - __sizeShiftAmount]);
27151 dumper->dumpOperand(m_value, true);
27152 }
27153
27154 OpRet(const uint8_t* stream)
27155 : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
27156 {
27157 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27158 }
27159
27160 OpRet(const uint16_t* stream)
27161 : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
27162 {
27163 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27164 }
27165
27166
27167 OpRet(const uint32_t* stream)
27168 : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
27169 {
27170 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27171 }
27172
27173 static OpRet decode(const uint8_t* stream)
27174 {
27175 if (*stream == op_wide32)
27176 return { bitwise_cast<const uint32_t*>(stream + 1) };
27177 if (*stream == op_wide16)
27178 return { bitwise_cast<const uint16_t*>(stream + 1) };
27179 return { stream };
27180 }
27181
27182 template<typename Functor>
27183 void setValue(VirtualRegister value, Functor func)
27184 {
27185 if (isWide32())
27186 setValue<OpcodeSize::Wide32>(value, func);
27187 else if (isWide16())
27188 setValue<OpcodeSize::Wide16>(value, func);
27189 else
27190 setValue<OpcodeSize::Narrow>(value, func);
27191 }
27192
27193 template <OpcodeSize size, typename Functor>
27194 void setValue(VirtualRegister value, Functor func)
27195 {
27196 if (!Fits<VirtualRegister, size>::check(value))
27197 value = func();
27198 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
27199 *stream = Fits<VirtualRegister, size>::convert(value);
27200 }
27201
27202 VirtualRegister m_value;
27203};
27204
27205struct OpStrcat : public Instruction {
27206 static constexpr OpcodeID opcodeID = op_strcat;
27207
27208 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
27209 {
27210 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, src, count);
27211 }
27212
27213 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
27214 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
27215 {
27216 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, src, count);
27217 if (shouldAssert == Assert)
27218 ASSERT(didEmit);
27219 return didEmit;
27220 }
27221
27222 template<OpcodeSize size>
27223 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
27224 {
27225
27226 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
27227 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src, count))
27228 return;
27229 }
27230 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
27231 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, src, count))
27232 return;
27233 }
27234 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, src, count);
27235 }
27236
27237private:
27238 template<OpcodeSize size>
27239 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src, int& count)
27240 {
27241 UNUSED_PARAM(gen);
27242#if OS(WINDOWS) && ENABLE(C_LOOP)
27243 // FIXME: Disable wide16 optimization for Windows CLoop
27244 // https://bugs.webkit.org/show_bug.cgi?id=198283
27245 if (size == OpcodeSize::Wide16)
27246 return false;
27247#endif
27248 return Fits<OpcodeID, size>::check(opcodeID)
27249 && Fits<VirtualRegister, size>::check(dst)
27250 && Fits<VirtualRegister, size>::check(src)
27251 && Fits<int, size>::check(count)
27252 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
27253 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
27254 }
27255
27256 template<OpcodeSize size, bool recordOpcode>
27257 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
27258 {
27259 if (size == OpcodeSize::Wide16)
27260 gen->alignWideOpcode16();
27261 else if (size == OpcodeSize::Wide32)
27262 gen->alignWideOpcode32();
27263 if (checkImpl<size>(gen, dst, src, count)) {
27264 if (recordOpcode)
27265 gen->recordOpcode(opcodeID);
27266 if (size == OpcodeSize::Wide16)
27267 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
27268 else if (size == OpcodeSize::Wide32)
27269 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
27270 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
27271 gen->write(Fits<VirtualRegister, size>::convert(dst));
27272 gen->write(Fits<VirtualRegister, size>::convert(src));
27273 gen->write(Fits<int, size>::convert(count));
27274 return true;
27275 }
27276 return false;
27277 }
27278
27279public:
27280 template<typename Block>
27281 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
27282 {
27283 dumper->printLocationAndOp(__location, &"**strcat"[2 - __sizeShiftAmount]);
27284 dumper->dumpOperand(m_dst, true);
27285 dumper->dumpOperand(m_src, false);
27286 dumper->dumpOperand(m_count, false);
27287 }
27288
27289 OpStrcat(const uint8_t* stream)
27290 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
27291 , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
27292 , m_count(Fits<int, OpcodeSize::Narrow>::convert(stream[3]))
27293 {
27294 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27295 }
27296
27297 OpStrcat(const uint16_t* stream)
27298 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
27299 , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
27300 , m_count(Fits<int, OpcodeSize::Wide16>::convert(stream[3]))
27301 {
27302 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27303 }
27304
27305
27306 OpStrcat(const uint32_t* stream)
27307 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
27308 , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
27309 , m_count(Fits<int, OpcodeSize::Wide32>::convert(stream[3]))
27310 {
27311 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27312 }
27313
27314 static OpStrcat decode(const uint8_t* stream)
27315 {
27316 if (*stream == op_wide32)
27317 return { bitwise_cast<const uint32_t*>(stream + 1) };
27318 if (*stream == op_wide16)
27319 return { bitwise_cast<const uint16_t*>(stream + 1) };
27320 return { stream };
27321 }
27322
27323 template<typename Functor>
27324 void setDst(VirtualRegister value, Functor func)
27325 {
27326 if (isWide32())
27327 setDst<OpcodeSize::Wide32>(value, func);
27328 else if (isWide16())
27329 setDst<OpcodeSize::Wide16>(value, func);
27330 else
27331 setDst<OpcodeSize::Narrow>(value, func);
27332 }
27333
27334 template <OpcodeSize size, typename Functor>
27335 void setDst(VirtualRegister value, Functor func)
27336 {
27337 if (!Fits<VirtualRegister, size>::check(value))
27338 value = func();
27339 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
27340 *stream = Fits<VirtualRegister, size>::convert(value);
27341 }
27342
27343 template<typename Functor>
27344 void setSrc(VirtualRegister value, Functor func)
27345 {
27346 if (isWide32())
27347 setSrc<OpcodeSize::Wide32>(value, func);
27348 else if (isWide16())
27349 setSrc<OpcodeSize::Wide16>(value, func);
27350 else
27351 setSrc<OpcodeSize::Narrow>(value, func);
27352 }
27353
27354 template <OpcodeSize size, typename Functor>
27355 void setSrc(VirtualRegister value, Functor func)
27356 {
27357 if (!Fits<VirtualRegister, size>::check(value))
27358 value = func();
27359 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
27360 *stream = Fits<VirtualRegister, size>::convert(value);
27361 }
27362
27363 template<typename Functor>
27364 void setCount(int value, Functor func)
27365 {
27366 if (isWide32())
27367 setCount<OpcodeSize::Wide32>(value, func);
27368 else if (isWide16())
27369 setCount<OpcodeSize::Wide16>(value, func);
27370 else
27371 setCount<OpcodeSize::Narrow>(value, func);
27372 }
27373
27374 template <OpcodeSize size, typename Functor>
27375 void setCount(int value, Functor func)
27376 {
27377 if (!Fits<int, size>::check(value))
27378 value = func();
27379 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
27380 *stream = Fits<int, size>::convert(value);
27381 }
27382
27383 VirtualRegister m_dst;
27384 VirtualRegister m_src;
27385 int m_count;
27386};
27387
27388struct OpToPrimitive : public Instruction {
27389 static constexpr OpcodeID opcodeID = op_to_primitive;
27390
27391 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
27392 {
27393 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, src);
27394 }
27395
27396 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
27397 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
27398 {
27399 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, src);
27400 if (shouldAssert == Assert)
27401 ASSERT(didEmit);
27402 return didEmit;
27403 }
27404
27405 template<OpcodeSize size>
27406 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
27407 {
27408
27409 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
27410 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src))
27411 return;
27412 }
27413 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
27414 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, src))
27415 return;
27416 }
27417 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, src);
27418 }
27419
27420private:
27421 template<OpcodeSize size>
27422 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src)
27423 {
27424 UNUSED_PARAM(gen);
27425#if OS(WINDOWS) && ENABLE(C_LOOP)
27426 // FIXME: Disable wide16 optimization for Windows CLoop
27427 // https://bugs.webkit.org/show_bug.cgi?id=198283
27428 if (size == OpcodeSize::Wide16)
27429 return false;
27430#endif
27431 return Fits<OpcodeID, size>::check(opcodeID)
27432 && Fits<VirtualRegister, size>::check(dst)
27433 && Fits<VirtualRegister, size>::check(src)
27434 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
27435 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
27436 }
27437
27438 template<OpcodeSize size, bool recordOpcode>
27439 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
27440 {
27441 if (size == OpcodeSize::Wide16)
27442 gen->alignWideOpcode16();
27443 else if (size == OpcodeSize::Wide32)
27444 gen->alignWideOpcode32();
27445 if (checkImpl<size>(gen, dst, src)) {
27446 if (recordOpcode)
27447 gen->recordOpcode(opcodeID);
27448 if (size == OpcodeSize::Wide16)
27449 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
27450 else if (size == OpcodeSize::Wide32)
27451 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
27452 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
27453 gen->write(Fits<VirtualRegister, size>::convert(dst));
27454 gen->write(Fits<VirtualRegister, size>::convert(src));
27455 return true;
27456 }
27457 return false;
27458 }
27459
27460public:
27461 template<typename Block>
27462 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
27463 {
27464 dumper->printLocationAndOp(__location, &"**to_primitive"[2 - __sizeShiftAmount]);
27465 dumper->dumpOperand(m_dst, true);
27466 dumper->dumpOperand(m_src, false);
27467 }
27468
27469 OpToPrimitive(const uint8_t* stream)
27470 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
27471 , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
27472 {
27473 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27474 }
27475
27476 OpToPrimitive(const uint16_t* stream)
27477 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
27478 , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
27479 {
27480 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27481 }
27482
27483
27484 OpToPrimitive(const uint32_t* stream)
27485 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
27486 , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
27487 {
27488 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27489 }
27490
27491 static OpToPrimitive decode(const uint8_t* stream)
27492 {
27493 if (*stream == op_wide32)
27494 return { bitwise_cast<const uint32_t*>(stream + 1) };
27495 if (*stream == op_wide16)
27496 return { bitwise_cast<const uint16_t*>(stream + 1) };
27497 return { stream };
27498 }
27499
27500 template<typename Functor>
27501 void setDst(VirtualRegister value, Functor func)
27502 {
27503 if (isWide32())
27504 setDst<OpcodeSize::Wide32>(value, func);
27505 else if (isWide16())
27506 setDst<OpcodeSize::Wide16>(value, func);
27507 else
27508 setDst<OpcodeSize::Narrow>(value, func);
27509 }
27510
27511 template <OpcodeSize size, typename Functor>
27512 void setDst(VirtualRegister value, Functor func)
27513 {
27514 if (!Fits<VirtualRegister, size>::check(value))
27515 value = func();
27516 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
27517 *stream = Fits<VirtualRegister, size>::convert(value);
27518 }
27519
27520 template<typename Functor>
27521 void setSrc(VirtualRegister value, Functor func)
27522 {
27523 if (isWide32())
27524 setSrc<OpcodeSize::Wide32>(value, func);
27525 else if (isWide16())
27526 setSrc<OpcodeSize::Wide16>(value, func);
27527 else
27528 setSrc<OpcodeSize::Narrow>(value, func);
27529 }
27530
27531 template <OpcodeSize size, typename Functor>
27532 void setSrc(VirtualRegister value, Functor func)
27533 {
27534 if (!Fits<VirtualRegister, size>::check(value))
27535 value = func();
27536 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
27537 *stream = Fits<VirtualRegister, size>::convert(value);
27538 }
27539
27540 VirtualRegister m_dst;
27541 VirtualRegister m_src;
27542};
27543
27544struct OpPutToArguments : public Instruction {
27545 static constexpr OpcodeID opcodeID = op_put_to_arguments;
27546
27547 static void emit(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
27548 {
27549 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, arguments, index, value);
27550 }
27551
27552 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
27553 static bool emit(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
27554 {
27555 bool didEmit = emitImpl<size, recordOpcode>(gen, arguments, index, value);
27556 if (shouldAssert == Assert)
27557 ASSERT(didEmit);
27558 return didEmit;
27559 }
27560
27561 template<OpcodeSize size>
27562 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
27563 {
27564
27565 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
27566 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, arguments, index, value))
27567 return;
27568 }
27569 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
27570 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, arguments, index, value))
27571 return;
27572 }
27573 emit<OpcodeSize::Wide32, Assert, true>(gen, arguments, index, value);
27574 }
27575
27576private:
27577 template<OpcodeSize size>
27578 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& arguments, unsigned& index, VirtualRegister& value)
27579 {
27580 UNUSED_PARAM(gen);
27581#if OS(WINDOWS) && ENABLE(C_LOOP)
27582 // FIXME: Disable wide16 optimization for Windows CLoop
27583 // https://bugs.webkit.org/show_bug.cgi?id=198283
27584 if (size == OpcodeSize::Wide16)
27585 return false;
27586#endif
27587 return Fits<OpcodeID, size>::check(opcodeID)
27588 && Fits<VirtualRegister, size>::check(arguments)
27589 && Fits<unsigned, size>::check(index)
27590 && Fits<VirtualRegister, size>::check(value)
27591 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
27592 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
27593 }
27594
27595 template<OpcodeSize size, bool recordOpcode>
27596 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
27597 {
27598 if (size == OpcodeSize::Wide16)
27599 gen->alignWideOpcode16();
27600 else if (size == OpcodeSize::Wide32)
27601 gen->alignWideOpcode32();
27602 if (checkImpl<size>(gen, arguments, index, value)) {
27603 if (recordOpcode)
27604 gen->recordOpcode(opcodeID);
27605 if (size == OpcodeSize::Wide16)
27606 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
27607 else if (size == OpcodeSize::Wide32)
27608 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
27609 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
27610 gen->write(Fits<VirtualRegister, size>::convert(arguments));
27611 gen->write(Fits<unsigned, size>::convert(index));
27612 gen->write(Fits<VirtualRegister, size>::convert(value));
27613 return true;
27614 }
27615 return false;
27616 }
27617
27618public:
27619 template<typename Block>
27620 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
27621 {
27622 dumper->printLocationAndOp(__location, &"**put_to_arguments"[2 - __sizeShiftAmount]);
27623 dumper->dumpOperand(m_arguments, true);
27624 dumper->dumpOperand(m_index, false);
27625 dumper->dumpOperand(m_value, false);
27626 }
27627
27628 OpPutToArguments(const uint8_t* stream)
27629 : m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
27630 , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
27631 , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
27632 {
27633 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27634 }
27635
27636 OpPutToArguments(const uint16_t* stream)
27637 : m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
27638 , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
27639 , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
27640 {
27641 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27642 }
27643
27644
27645 OpPutToArguments(const uint32_t* stream)
27646 : m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
27647 , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
27648 , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
27649 {
27650 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27651 }
27652
27653 static OpPutToArguments decode(const uint8_t* stream)
27654 {
27655 if (*stream == op_wide32)
27656 return { bitwise_cast<const uint32_t*>(stream + 1) };
27657 if (*stream == op_wide16)
27658 return { bitwise_cast<const uint16_t*>(stream + 1) };
27659 return { stream };
27660 }
27661
27662 template<typename Functor>
27663 void setArguments(VirtualRegister value, Functor func)
27664 {
27665 if (isWide32())
27666 setArguments<OpcodeSize::Wide32>(value, func);
27667 else if (isWide16())
27668 setArguments<OpcodeSize::Wide16>(value, func);
27669 else
27670 setArguments<OpcodeSize::Narrow>(value, func);
27671 }
27672
27673 template <OpcodeSize size, typename Functor>
27674 void setArguments(VirtualRegister value, Functor func)
27675 {
27676 if (!Fits<VirtualRegister, size>::check(value))
27677 value = func();
27678 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
27679 *stream = Fits<VirtualRegister, size>::convert(value);
27680 }
27681
27682 template<typename Functor>
27683 void setIndex(unsigned value, Functor func)
27684 {
27685 if (isWide32())
27686 setIndex<OpcodeSize::Wide32>(value, func);
27687 else if (isWide16())
27688 setIndex<OpcodeSize::Wide16>(value, func);
27689 else
27690 setIndex<OpcodeSize::Narrow>(value, func);
27691 }
27692
27693 template <OpcodeSize size, typename Functor>
27694 void setIndex(unsigned value, Functor func)
27695 {
27696 if (!Fits<unsigned, size>::check(value))
27697 value = func();
27698 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
27699 *stream = Fits<unsigned, size>::convert(value);
27700 }
27701
27702 template<typename Functor>
27703 void setValue(VirtualRegister value, Functor func)
27704 {
27705 if (isWide32())
27706 setValue<OpcodeSize::Wide32>(value, func);
27707 else if (isWide16())
27708 setValue<OpcodeSize::Wide16>(value, func);
27709 else
27710 setValue<OpcodeSize::Narrow>(value, func);
27711 }
27712
27713 template <OpcodeSize size, typename Functor>
27714 void setValue(VirtualRegister value, Functor func)
27715 {
27716 if (!Fits<VirtualRegister, size>::check(value))
27717 value = func();
27718 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
27719 *stream = Fits<VirtualRegister, size>::convert(value);
27720 }
27721
27722 VirtualRegister m_arguments;
27723 unsigned m_index;
27724 VirtualRegister m_value;
27725};
27726
27727struct OpPushWithScope : public Instruction {
27728 static constexpr OpcodeID opcodeID = op_push_with_scope;
27729
27730 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
27731 {
27732 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, currentScope, newScope);
27733 }
27734
27735 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
27736 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
27737 {
27738 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, currentScope, newScope);
27739 if (shouldAssert == Assert)
27740 ASSERT(didEmit);
27741 return didEmit;
27742 }
27743
27744 template<OpcodeSize size>
27745 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
27746 {
27747
27748 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
27749 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, currentScope, newScope))
27750 return;
27751 }
27752 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
27753 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, currentScope, newScope))
27754 return;
27755 }
27756 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, currentScope, newScope);
27757 }
27758
27759private:
27760 template<OpcodeSize size>
27761 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& currentScope, VirtualRegister& newScope)
27762 {
27763 UNUSED_PARAM(gen);
27764#if OS(WINDOWS) && ENABLE(C_LOOP)
27765 // FIXME: Disable wide16 optimization for Windows CLoop
27766 // https://bugs.webkit.org/show_bug.cgi?id=198283
27767 if (size == OpcodeSize::Wide16)
27768 return false;
27769#endif
27770 return Fits<OpcodeID, size>::check(opcodeID)
27771 && Fits<VirtualRegister, size>::check(dst)
27772 && Fits<VirtualRegister, size>::check(currentScope)
27773 && Fits<VirtualRegister, size>::check(newScope)
27774 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
27775 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
27776 }
27777
27778 template<OpcodeSize size, bool recordOpcode>
27779 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
27780 {
27781 if (size == OpcodeSize::Wide16)
27782 gen->alignWideOpcode16();
27783 else if (size == OpcodeSize::Wide32)
27784 gen->alignWideOpcode32();
27785 if (checkImpl<size>(gen, dst, currentScope, newScope)) {
27786 if (recordOpcode)
27787 gen->recordOpcode(opcodeID);
27788 if (size == OpcodeSize::Wide16)
27789 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
27790 else if (size == OpcodeSize::Wide32)
27791 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
27792 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
27793 gen->write(Fits<VirtualRegister, size>::convert(dst));
27794 gen->write(Fits<VirtualRegister, size>::convert(currentScope));
27795 gen->write(Fits<VirtualRegister, size>::convert(newScope));
27796 return true;
27797 }
27798 return false;
27799 }
27800
27801public:
27802 template<typename Block>
27803 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
27804 {
27805 dumper->printLocationAndOp(__location, &"**push_with_scope"[2 - __sizeShiftAmount]);
27806 dumper->dumpOperand(m_dst, true);
27807 dumper->dumpOperand(m_currentScope, false);
27808 dumper->dumpOperand(m_newScope, false);
27809 }
27810
27811 OpPushWithScope(const uint8_t* stream)
27812 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
27813 , m_currentScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
27814 , m_newScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
27815 {
27816 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27817 }
27818
27819 OpPushWithScope(const uint16_t* stream)
27820 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
27821 , m_currentScope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
27822 , m_newScope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
27823 {
27824 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27825 }
27826
27827
27828 OpPushWithScope(const uint32_t* stream)
27829 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
27830 , m_currentScope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
27831 , m_newScope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
27832 {
27833 ASSERT_UNUSED(stream, stream[0] == opcodeID);
27834 }
27835
27836 static OpPushWithScope decode(const uint8_t* stream)
27837 {
27838 if (*stream == op_wide32)
27839 return { bitwise_cast<const uint32_t*>(stream + 1) };
27840 if (*stream == op_wide16)
27841 return { bitwise_cast<const uint16_t*>(stream + 1) };
27842 return { stream };
27843 }
27844
27845 template<typename Functor>
27846 void setDst(VirtualRegister value, Functor func)
27847 {
27848 if (isWide32())
27849 setDst<OpcodeSize::Wide32>(value, func);
27850 else if (isWide16())
27851 setDst<OpcodeSize::Wide16>(value, func);
27852 else
27853 setDst<OpcodeSize::Narrow>(value, func);
27854 }
27855
27856 template <OpcodeSize size, typename Functor>
27857 void setDst(VirtualRegister value, Functor func)
27858 {
27859 if (!Fits<VirtualRegister, size>::check(value))
27860 value = func();
27861 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
27862 *stream = Fits<VirtualRegister, size>::convert(value);
27863 }
27864
27865 template<typename Functor>
27866 void setCurrentScope(VirtualRegister value, Functor func)
27867 {
27868 if (isWide32())
27869 setCurrentScope<OpcodeSize::Wide32>(value, func);
27870 else if (isWide16())
27871 setCurrentScope<OpcodeSize::Wide16>(value, func);
27872 else
27873 setCurrentScope<OpcodeSize::Narrow>(value, func);
27874 }
27875
27876 template <OpcodeSize size, typename Functor>
27877 void setCurrentScope(VirtualRegister value, Functor func)
27878 {
27879 if (!Fits<VirtualRegister, size>::check(value))
27880 value = func();
27881 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
27882 *stream = Fits<VirtualRegister, size>::convert(value);
27883 }
27884
27885 template<typename Functor>
27886 void setNewScope(VirtualRegister value, Functor func)
27887 {
27888 if (isWide32())
27889 setNewScope<OpcodeSize::Wide32>(value, func);
27890 else if (isWide16())
27891 setNewScope<OpcodeSize::Wide16>(value, func);
27892 else
27893 setNewScope<OpcodeSize::Narrow>(value, func);
27894 }
27895
27896 template <OpcodeSize size, typename Functor>
27897 void setNewScope(VirtualRegister value, Functor func)
27898 {
27899 if (!Fits<VirtualRegister, size>::check(value))
27900 value = func();
27901 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
27902 *stream = Fits<VirtualRegister, size>::convert(value);
27903 }
27904
27905 VirtualRegister m_dst;
27906 VirtualRegister m_currentScope;
27907 VirtualRegister m_newScope;
27908};
27909
27910struct OpCreateLexicalEnvironment : public Instruction {
27911 static constexpr OpcodeID opcodeID = op_create_lexical_environment;
27912
27913 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
27914 {
27915 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, symbolTable, initialValue);
27916 }
27917
27918 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
27919 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
27920 {
27921 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, symbolTable, initialValue);
27922 if (shouldAssert == Assert)
27923 ASSERT(didEmit);
27924 return didEmit;
27925 }
27926
27927 template<OpcodeSize size>
27928 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
27929 {
27930
27931 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
27932 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
27933 return;
27934 }
27935 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
27936 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
27937 return;
27938 }
27939 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, symbolTable, initialValue);
27940 }
27941
27942private:
27943 template<OpcodeSize size>
27944 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, VirtualRegister& symbolTable, VirtualRegister& initialValue)
27945 {
27946 UNUSED_PARAM(gen);
27947#if OS(WINDOWS) && ENABLE(C_LOOP)
27948 // FIXME: Disable wide16 optimization for Windows CLoop
27949 // https://bugs.webkit.org/show_bug.cgi?id=198283
27950 if (size == OpcodeSize::Wide16)
27951 return false;
27952#endif
27953 return Fits<OpcodeID, size>::check(opcodeID)
27954 && Fits<VirtualRegister, size>::check(dst)
27955 && Fits<VirtualRegister, size>::check(scope)
27956 && Fits<VirtualRegister, size>::check(symbolTable)
27957 && Fits<VirtualRegister, size>::check(initialValue)
27958 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
27959 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
27960 }
27961
27962 template<OpcodeSize size, bool recordOpcode>
27963 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
27964 {
27965 if (size == OpcodeSize::Wide16)
27966 gen->alignWideOpcode16();
27967 else if (size == OpcodeSize::Wide32)
27968 gen->alignWideOpcode32();
27969 if (checkImpl<size>(gen, dst, scope, symbolTable, initialValue)) {
27970 if (recordOpcode)
27971 gen->recordOpcode(opcodeID);
27972 if (size == OpcodeSize::Wide16)
27973 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
27974 else if (size == OpcodeSize::Wide32)
27975 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
27976 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
27977 gen->write(Fits<VirtualRegister, size>::convert(dst));
27978 gen->write(Fits<VirtualRegister, size>::convert(scope));
27979 gen->write(Fits<VirtualRegister, size>::convert(symbolTable));
27980 gen->write(Fits<VirtualRegister, size>::convert(initialValue));
27981 return true;
27982 }
27983 return false;
27984 }
27985
27986public:
27987 template<typename Block>
27988 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
27989 {
27990 dumper->printLocationAndOp(__location, &"**create_lexical_environment"[2 - __sizeShiftAmount]);
27991 dumper->dumpOperand(m_dst, true);
27992 dumper->dumpOperand(m_scope, false);
27993 dumper->dumpOperand(m_symbolTable, false);
27994 dumper->dumpOperand(m_initialValue, false);
27995 }
27996
27997 OpCreateLexicalEnvironment(const uint8_t* stream)
27998 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
27999 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
28000 , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
28001 , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
28002 {
28003 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28004 }
28005
28006 OpCreateLexicalEnvironment(const uint16_t* stream)
28007 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
28008 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
28009 , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
28010 , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
28011 {
28012 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28013 }
28014
28015
28016 OpCreateLexicalEnvironment(const uint32_t* stream)
28017 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
28018 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
28019 , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
28020 , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
28021 {
28022 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28023 }
28024
28025 static OpCreateLexicalEnvironment decode(const uint8_t* stream)
28026 {
28027 if (*stream == op_wide32)
28028 return { bitwise_cast<const uint32_t*>(stream + 1) };
28029 if (*stream == op_wide16)
28030 return { bitwise_cast<const uint16_t*>(stream + 1) };
28031 return { stream };
28032 }
28033
28034 template<typename Functor>
28035 void setDst(VirtualRegister value, Functor func)
28036 {
28037 if (isWide32())
28038 setDst<OpcodeSize::Wide32>(value, func);
28039 else if (isWide16())
28040 setDst<OpcodeSize::Wide16>(value, func);
28041 else
28042 setDst<OpcodeSize::Narrow>(value, func);
28043 }
28044
28045 template <OpcodeSize size, typename Functor>
28046 void setDst(VirtualRegister value, Functor func)
28047 {
28048 if (!Fits<VirtualRegister, size>::check(value))
28049 value = func();
28050 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
28051 *stream = Fits<VirtualRegister, size>::convert(value);
28052 }
28053
28054 template<typename Functor>
28055 void setScope(VirtualRegister value, Functor func)
28056 {
28057 if (isWide32())
28058 setScope<OpcodeSize::Wide32>(value, func);
28059 else if (isWide16())
28060 setScope<OpcodeSize::Wide16>(value, func);
28061 else
28062 setScope<OpcodeSize::Narrow>(value, func);
28063 }
28064
28065 template <OpcodeSize size, typename Functor>
28066 void setScope(VirtualRegister value, Functor func)
28067 {
28068 if (!Fits<VirtualRegister, size>::check(value))
28069 value = func();
28070 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
28071 *stream = Fits<VirtualRegister, size>::convert(value);
28072 }
28073
28074 template<typename Functor>
28075 void setSymbolTable(VirtualRegister value, Functor func)
28076 {
28077 if (isWide32())
28078 setSymbolTable<OpcodeSize::Wide32>(value, func);
28079 else if (isWide16())
28080 setSymbolTable<OpcodeSize::Wide16>(value, func);
28081 else
28082 setSymbolTable<OpcodeSize::Narrow>(value, func);
28083 }
28084
28085 template <OpcodeSize size, typename Functor>
28086 void setSymbolTable(VirtualRegister value, Functor func)
28087 {
28088 if (!Fits<VirtualRegister, size>::check(value))
28089 value = func();
28090 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
28091 *stream = Fits<VirtualRegister, size>::convert(value);
28092 }
28093
28094 template<typename Functor>
28095 void setInitialValue(VirtualRegister value, Functor func)
28096 {
28097 if (isWide32())
28098 setInitialValue<OpcodeSize::Wide32>(value, func);
28099 else if (isWide16())
28100 setInitialValue<OpcodeSize::Wide16>(value, func);
28101 else
28102 setInitialValue<OpcodeSize::Narrow>(value, func);
28103 }
28104
28105 template <OpcodeSize size, typename Functor>
28106 void setInitialValue(VirtualRegister value, Functor func)
28107 {
28108 if (!Fits<VirtualRegister, size>::check(value))
28109 value = func();
28110 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
28111 *stream = Fits<VirtualRegister, size>::convert(value);
28112 }
28113
28114 VirtualRegister m_dst;
28115 VirtualRegister m_scope;
28116 VirtualRegister m_symbolTable;
28117 VirtualRegister m_initialValue;
28118};
28119
28120struct OpCreateGeneratorFrameEnvironment : public Instruction {
28121 static constexpr OpcodeID opcodeID = op_create_generator_frame_environment;
28122
28123 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
28124 {
28125 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, symbolTable, initialValue);
28126 }
28127
28128 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
28129 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
28130 {
28131 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, symbolTable, initialValue);
28132 if (shouldAssert == Assert)
28133 ASSERT(didEmit);
28134 return didEmit;
28135 }
28136
28137 template<OpcodeSize size>
28138 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
28139 {
28140
28141 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
28142 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
28143 return;
28144 }
28145 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
28146 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
28147 return;
28148 }
28149 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, symbolTable, initialValue);
28150 }
28151
28152private:
28153 template<OpcodeSize size>
28154 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, VirtualRegister& symbolTable, VirtualRegister& initialValue)
28155 {
28156 UNUSED_PARAM(gen);
28157#if OS(WINDOWS) && ENABLE(C_LOOP)
28158 // FIXME: Disable wide16 optimization for Windows CLoop
28159 // https://bugs.webkit.org/show_bug.cgi?id=198283
28160 if (size == OpcodeSize::Wide16)
28161 return false;
28162#endif
28163 return Fits<OpcodeID, size>::check(opcodeID)
28164 && Fits<VirtualRegister, size>::check(dst)
28165 && Fits<VirtualRegister, size>::check(scope)
28166 && Fits<VirtualRegister, size>::check(symbolTable)
28167 && Fits<VirtualRegister, size>::check(initialValue)
28168 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
28169 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
28170 }
28171
28172 template<OpcodeSize size, bool recordOpcode>
28173 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
28174 {
28175 if (size == OpcodeSize::Wide16)
28176 gen->alignWideOpcode16();
28177 else if (size == OpcodeSize::Wide32)
28178 gen->alignWideOpcode32();
28179 if (checkImpl<size>(gen, dst, scope, symbolTable, initialValue)) {
28180 if (recordOpcode)
28181 gen->recordOpcode(opcodeID);
28182 if (size == OpcodeSize::Wide16)
28183 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
28184 else if (size == OpcodeSize::Wide32)
28185 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
28186 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
28187 gen->write(Fits<VirtualRegister, size>::convert(dst));
28188 gen->write(Fits<VirtualRegister, size>::convert(scope));
28189 gen->write(Fits<VirtualRegister, size>::convert(symbolTable));
28190 gen->write(Fits<VirtualRegister, size>::convert(initialValue));
28191 return true;
28192 }
28193 return false;
28194 }
28195
28196public:
28197 template<typename Block>
28198 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
28199 {
28200 dumper->printLocationAndOp(__location, &"**create_generator_frame_environment"[2 - __sizeShiftAmount]);
28201 dumper->dumpOperand(m_dst, true);
28202 dumper->dumpOperand(m_scope, false);
28203 dumper->dumpOperand(m_symbolTable, false);
28204 dumper->dumpOperand(m_initialValue, false);
28205 }
28206
28207 OpCreateGeneratorFrameEnvironment(const uint8_t* stream)
28208 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
28209 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
28210 , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
28211 , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
28212 {
28213 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28214 }
28215
28216 OpCreateGeneratorFrameEnvironment(const uint16_t* stream)
28217 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
28218 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
28219 , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
28220 , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
28221 {
28222 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28223 }
28224
28225
28226 OpCreateGeneratorFrameEnvironment(const uint32_t* stream)
28227 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
28228 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
28229 , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
28230 , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
28231 {
28232 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28233 }
28234
28235 static OpCreateGeneratorFrameEnvironment decode(const uint8_t* stream)
28236 {
28237 if (*stream == op_wide32)
28238 return { bitwise_cast<const uint32_t*>(stream + 1) };
28239 if (*stream == op_wide16)
28240 return { bitwise_cast<const uint16_t*>(stream + 1) };
28241 return { stream };
28242 }
28243
28244 template<typename Functor>
28245 void setDst(VirtualRegister value, Functor func)
28246 {
28247 if (isWide32())
28248 setDst<OpcodeSize::Wide32>(value, func);
28249 else if (isWide16())
28250 setDst<OpcodeSize::Wide16>(value, func);
28251 else
28252 setDst<OpcodeSize::Narrow>(value, func);
28253 }
28254
28255 template <OpcodeSize size, typename Functor>
28256 void setDst(VirtualRegister value, Functor func)
28257 {
28258 if (!Fits<VirtualRegister, size>::check(value))
28259 value = func();
28260 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
28261 *stream = Fits<VirtualRegister, size>::convert(value);
28262 }
28263
28264 template<typename Functor>
28265 void setScope(VirtualRegister value, Functor func)
28266 {
28267 if (isWide32())
28268 setScope<OpcodeSize::Wide32>(value, func);
28269 else if (isWide16())
28270 setScope<OpcodeSize::Wide16>(value, func);
28271 else
28272 setScope<OpcodeSize::Narrow>(value, func);
28273 }
28274
28275 template <OpcodeSize size, typename Functor>
28276 void setScope(VirtualRegister value, Functor func)
28277 {
28278 if (!Fits<VirtualRegister, size>::check(value))
28279 value = func();
28280 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
28281 *stream = Fits<VirtualRegister, size>::convert(value);
28282 }
28283
28284 template<typename Functor>
28285 void setSymbolTable(VirtualRegister value, Functor func)
28286 {
28287 if (isWide32())
28288 setSymbolTable<OpcodeSize::Wide32>(value, func);
28289 else if (isWide16())
28290 setSymbolTable<OpcodeSize::Wide16>(value, func);
28291 else
28292 setSymbolTable<OpcodeSize::Narrow>(value, func);
28293 }
28294
28295 template <OpcodeSize size, typename Functor>
28296 void setSymbolTable(VirtualRegister value, Functor func)
28297 {
28298 if (!Fits<VirtualRegister, size>::check(value))
28299 value = func();
28300 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
28301 *stream = Fits<VirtualRegister, size>::convert(value);
28302 }
28303
28304 template<typename Functor>
28305 void setInitialValue(VirtualRegister value, Functor func)
28306 {
28307 if (isWide32())
28308 setInitialValue<OpcodeSize::Wide32>(value, func);
28309 else if (isWide16())
28310 setInitialValue<OpcodeSize::Wide16>(value, func);
28311 else
28312 setInitialValue<OpcodeSize::Narrow>(value, func);
28313 }
28314
28315 template <OpcodeSize size, typename Functor>
28316 void setInitialValue(VirtualRegister value, Functor func)
28317 {
28318 if (!Fits<VirtualRegister, size>::check(value))
28319 value = func();
28320 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
28321 *stream = Fits<VirtualRegister, size>::convert(value);
28322 }
28323
28324 VirtualRegister m_dst;
28325 VirtualRegister m_scope;
28326 VirtualRegister m_symbolTable;
28327 VirtualRegister m_initialValue;
28328};
28329
28330struct OpGetParentScope : public Instruction {
28331 static constexpr OpcodeID opcodeID = op_get_parent_scope;
28332
28333 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
28334 {
28335 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope);
28336 }
28337
28338 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
28339 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
28340 {
28341 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope);
28342 if (shouldAssert == Assert)
28343 ASSERT(didEmit);
28344 return didEmit;
28345 }
28346
28347 template<OpcodeSize size>
28348 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
28349 {
28350
28351 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
28352 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope))
28353 return;
28354 }
28355 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
28356 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope))
28357 return;
28358 }
28359 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope);
28360 }
28361
28362private:
28363 template<OpcodeSize size>
28364 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope)
28365 {
28366 UNUSED_PARAM(gen);
28367#if OS(WINDOWS) && ENABLE(C_LOOP)
28368 // FIXME: Disable wide16 optimization for Windows CLoop
28369 // https://bugs.webkit.org/show_bug.cgi?id=198283
28370 if (size == OpcodeSize::Wide16)
28371 return false;
28372#endif
28373 return Fits<OpcodeID, size>::check(opcodeID)
28374 && Fits<VirtualRegister, size>::check(dst)
28375 && Fits<VirtualRegister, size>::check(scope)
28376 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
28377 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
28378 }
28379
28380 template<OpcodeSize size, bool recordOpcode>
28381 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
28382 {
28383 if (size == OpcodeSize::Wide16)
28384 gen->alignWideOpcode16();
28385 else if (size == OpcodeSize::Wide32)
28386 gen->alignWideOpcode32();
28387 if (checkImpl<size>(gen, dst, scope)) {
28388 if (recordOpcode)
28389 gen->recordOpcode(opcodeID);
28390 if (size == OpcodeSize::Wide16)
28391 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
28392 else if (size == OpcodeSize::Wide32)
28393 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
28394 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
28395 gen->write(Fits<VirtualRegister, size>::convert(dst));
28396 gen->write(Fits<VirtualRegister, size>::convert(scope));
28397 return true;
28398 }
28399 return false;
28400 }
28401
28402public:
28403 template<typename Block>
28404 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
28405 {
28406 dumper->printLocationAndOp(__location, &"**get_parent_scope"[2 - __sizeShiftAmount]);
28407 dumper->dumpOperand(m_dst, true);
28408 dumper->dumpOperand(m_scope, false);
28409 }
28410
28411 OpGetParentScope(const uint8_t* stream)
28412 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
28413 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
28414 {
28415 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28416 }
28417
28418 OpGetParentScope(const uint16_t* stream)
28419 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
28420 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
28421 {
28422 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28423 }
28424
28425
28426 OpGetParentScope(const uint32_t* stream)
28427 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
28428 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
28429 {
28430 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28431 }
28432
28433 static OpGetParentScope decode(const uint8_t* stream)
28434 {
28435 if (*stream == op_wide32)
28436 return { bitwise_cast<const uint32_t*>(stream + 1) };
28437 if (*stream == op_wide16)
28438 return { bitwise_cast<const uint16_t*>(stream + 1) };
28439 return { stream };
28440 }
28441
28442 template<typename Functor>
28443 void setDst(VirtualRegister value, Functor func)
28444 {
28445 if (isWide32())
28446 setDst<OpcodeSize::Wide32>(value, func);
28447 else if (isWide16())
28448 setDst<OpcodeSize::Wide16>(value, func);
28449 else
28450 setDst<OpcodeSize::Narrow>(value, func);
28451 }
28452
28453 template <OpcodeSize size, typename Functor>
28454 void setDst(VirtualRegister value, Functor func)
28455 {
28456 if (!Fits<VirtualRegister, size>::check(value))
28457 value = func();
28458 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
28459 *stream = Fits<VirtualRegister, size>::convert(value);
28460 }
28461
28462 template<typename Functor>
28463 void setScope(VirtualRegister value, Functor func)
28464 {
28465 if (isWide32())
28466 setScope<OpcodeSize::Wide32>(value, func);
28467 else if (isWide16())
28468 setScope<OpcodeSize::Wide16>(value, func);
28469 else
28470 setScope<OpcodeSize::Narrow>(value, func);
28471 }
28472
28473 template <OpcodeSize size, typename Functor>
28474 void setScope(VirtualRegister value, Functor func)
28475 {
28476 if (!Fits<VirtualRegister, size>::check(value))
28477 value = func();
28478 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
28479 *stream = Fits<VirtualRegister, size>::convert(value);
28480 }
28481
28482 VirtualRegister m_dst;
28483 VirtualRegister m_scope;
28484};
28485
28486struct OpThrow : public Instruction {
28487 static constexpr OpcodeID opcodeID = op_throw;
28488
28489 static void emit(BytecodeGenerator* gen, VirtualRegister value)
28490 {
28491 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, value);
28492 }
28493
28494 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
28495 static bool emit(BytecodeGenerator* gen, VirtualRegister value)
28496 {
28497 bool didEmit = emitImpl<size, recordOpcode>(gen, value);
28498 if (shouldAssert == Assert)
28499 ASSERT(didEmit);
28500 return didEmit;
28501 }
28502
28503 template<OpcodeSize size>
28504 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
28505 {
28506
28507 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
28508 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value))
28509 return;
28510 }
28511 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
28512 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value))
28513 return;
28514 }
28515 emit<OpcodeSize::Wide32, Assert, true>(gen, value);
28516 }
28517
28518private:
28519 template<OpcodeSize size>
28520 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value)
28521 {
28522 UNUSED_PARAM(gen);
28523#if OS(WINDOWS) && ENABLE(C_LOOP)
28524 // FIXME: Disable wide16 optimization for Windows CLoop
28525 // https://bugs.webkit.org/show_bug.cgi?id=198283
28526 if (size == OpcodeSize::Wide16)
28527 return false;
28528#endif
28529 return Fits<OpcodeID, size>::check(opcodeID)
28530 && Fits<VirtualRegister, size>::check(value)
28531 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
28532 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
28533 }
28534
28535 template<OpcodeSize size, bool recordOpcode>
28536 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value)
28537 {
28538 if (size == OpcodeSize::Wide16)
28539 gen->alignWideOpcode16();
28540 else if (size == OpcodeSize::Wide32)
28541 gen->alignWideOpcode32();
28542 if (checkImpl<size>(gen, value)) {
28543 if (recordOpcode)
28544 gen->recordOpcode(opcodeID);
28545 if (size == OpcodeSize::Wide16)
28546 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
28547 else if (size == OpcodeSize::Wide32)
28548 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
28549 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
28550 gen->write(Fits<VirtualRegister, size>::convert(value));
28551 return true;
28552 }
28553 return false;
28554 }
28555
28556public:
28557 template<typename Block>
28558 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
28559 {
28560 dumper->printLocationAndOp(__location, &"**throw"[2 - __sizeShiftAmount]);
28561 dumper->dumpOperand(m_value, true);
28562 }
28563
28564 OpThrow(const uint8_t* stream)
28565 : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
28566 {
28567 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28568 }
28569
28570 OpThrow(const uint16_t* stream)
28571 : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
28572 {
28573 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28574 }
28575
28576
28577 OpThrow(const uint32_t* stream)
28578 : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
28579 {
28580 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28581 }
28582
28583 static OpThrow decode(const uint8_t* stream)
28584 {
28585 if (*stream == op_wide32)
28586 return { bitwise_cast<const uint32_t*>(stream + 1) };
28587 if (*stream == op_wide16)
28588 return { bitwise_cast<const uint16_t*>(stream + 1) };
28589 return { stream };
28590 }
28591
28592 template<typename Functor>
28593 void setValue(VirtualRegister value, Functor func)
28594 {
28595 if (isWide32())
28596 setValue<OpcodeSize::Wide32>(value, func);
28597 else if (isWide16())
28598 setValue<OpcodeSize::Wide16>(value, func);
28599 else
28600 setValue<OpcodeSize::Narrow>(value, func);
28601 }
28602
28603 template <OpcodeSize size, typename Functor>
28604 void setValue(VirtualRegister value, Functor func)
28605 {
28606 if (!Fits<VirtualRegister, size>::check(value))
28607 value = func();
28608 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
28609 *stream = Fits<VirtualRegister, size>::convert(value);
28610 }
28611
28612 VirtualRegister m_value;
28613};
28614
28615struct OpThrowStaticError : public Instruction {
28616 static constexpr OpcodeID opcodeID = op_throw_static_error;
28617
28618 static void emit(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType)
28619 {
28620 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, message, errorType);
28621 }
28622
28623 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
28624 static bool emit(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType)
28625 {
28626 bool didEmit = emitImpl<size, recordOpcode>(gen, message, errorType);
28627 if (shouldAssert == Assert)
28628 ASSERT(didEmit);
28629 return didEmit;
28630 }
28631
28632 template<OpcodeSize size>
28633 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType)
28634 {
28635
28636 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
28637 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, message, errorType))
28638 return;
28639 }
28640 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
28641 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, message, errorType))
28642 return;
28643 }
28644 emit<OpcodeSize::Wide32, Assert, true>(gen, message, errorType);
28645 }
28646
28647private:
28648 template<OpcodeSize size>
28649 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& message, ErrorType& errorType)
28650 {
28651 UNUSED_PARAM(gen);
28652#if OS(WINDOWS) && ENABLE(C_LOOP)
28653 // FIXME: Disable wide16 optimization for Windows CLoop
28654 // https://bugs.webkit.org/show_bug.cgi?id=198283
28655 if (size == OpcodeSize::Wide16)
28656 return false;
28657#endif
28658 return Fits<OpcodeID, size>::check(opcodeID)
28659 && Fits<VirtualRegister, size>::check(message)
28660 && Fits<ErrorType, size>::check(errorType)
28661 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
28662 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
28663 }
28664
28665 template<OpcodeSize size, bool recordOpcode>
28666 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType)
28667 {
28668 if (size == OpcodeSize::Wide16)
28669 gen->alignWideOpcode16();
28670 else if (size == OpcodeSize::Wide32)
28671 gen->alignWideOpcode32();
28672 if (checkImpl<size>(gen, message, errorType)) {
28673 if (recordOpcode)
28674 gen->recordOpcode(opcodeID);
28675 if (size == OpcodeSize::Wide16)
28676 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
28677 else if (size == OpcodeSize::Wide32)
28678 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
28679 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
28680 gen->write(Fits<VirtualRegister, size>::convert(message));
28681 gen->write(Fits<ErrorType, size>::convert(errorType));
28682 return true;
28683 }
28684 return false;
28685 }
28686
28687public:
28688 template<typename Block>
28689 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
28690 {
28691 dumper->printLocationAndOp(__location, &"**throw_static_error"[2 - __sizeShiftAmount]);
28692 dumper->dumpOperand(m_message, true);
28693 dumper->dumpOperand(m_errorType, false);
28694 }
28695
28696 OpThrowStaticError(const uint8_t* stream)
28697 : m_message(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
28698 , m_errorType(Fits<ErrorType, OpcodeSize::Narrow>::convert(stream[2]))
28699 {
28700 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28701 }
28702
28703 OpThrowStaticError(const uint16_t* stream)
28704 : m_message(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
28705 , m_errorType(Fits<ErrorType, OpcodeSize::Wide16>::convert(stream[2]))
28706 {
28707 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28708 }
28709
28710
28711 OpThrowStaticError(const uint32_t* stream)
28712 : m_message(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
28713 , m_errorType(Fits<ErrorType, OpcodeSize::Wide32>::convert(stream[2]))
28714 {
28715 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28716 }
28717
28718 static OpThrowStaticError decode(const uint8_t* stream)
28719 {
28720 if (*stream == op_wide32)
28721 return { bitwise_cast<const uint32_t*>(stream + 1) };
28722 if (*stream == op_wide16)
28723 return { bitwise_cast<const uint16_t*>(stream + 1) };
28724 return { stream };
28725 }
28726
28727 template<typename Functor>
28728 void setMessage(VirtualRegister value, Functor func)
28729 {
28730 if (isWide32())
28731 setMessage<OpcodeSize::Wide32>(value, func);
28732 else if (isWide16())
28733 setMessage<OpcodeSize::Wide16>(value, func);
28734 else
28735 setMessage<OpcodeSize::Narrow>(value, func);
28736 }
28737
28738 template <OpcodeSize size, typename Functor>
28739 void setMessage(VirtualRegister value, Functor func)
28740 {
28741 if (!Fits<VirtualRegister, size>::check(value))
28742 value = func();
28743 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
28744 *stream = Fits<VirtualRegister, size>::convert(value);
28745 }
28746
28747 template<typename Functor>
28748 void setErrorType(ErrorType value, Functor func)
28749 {
28750 if (isWide32())
28751 setErrorType<OpcodeSize::Wide32>(value, func);
28752 else if (isWide16())
28753 setErrorType<OpcodeSize::Wide16>(value, func);
28754 else
28755 setErrorType<OpcodeSize::Narrow>(value, func);
28756 }
28757
28758 template <OpcodeSize size, typename Functor>
28759 void setErrorType(ErrorType value, Functor func)
28760 {
28761 if (!Fits<ErrorType, size>::check(value))
28762 value = func();
28763 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
28764 *stream = Fits<ErrorType, size>::convert(value);
28765 }
28766
28767 VirtualRegister m_message;
28768 ErrorType m_errorType;
28769};
28770
28771struct OpDebug : public Instruction {
28772 static constexpr OpcodeID opcodeID = op_debug;
28773
28774 static void emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
28775 {
28776 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, debugHookType, hasBreakpoint);
28777 }
28778
28779 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
28780 static bool emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
28781 {
28782 bool didEmit = emitImpl<size, recordOpcode>(gen, debugHookType, hasBreakpoint);
28783 if (shouldAssert == Assert)
28784 ASSERT(didEmit);
28785 return didEmit;
28786 }
28787
28788 template<OpcodeSize size>
28789 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
28790 {
28791
28792 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
28793 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, debugHookType, hasBreakpoint))
28794 return;
28795 }
28796 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
28797 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, debugHookType, hasBreakpoint))
28798 return;
28799 }
28800 emit<OpcodeSize::Wide32, Assert, true>(gen, debugHookType, hasBreakpoint);
28801 }
28802
28803private:
28804 template<OpcodeSize size>
28805 static bool checkImpl(BytecodeGenerator* gen, DebugHookType& debugHookType, bool& hasBreakpoint)
28806 {
28807 UNUSED_PARAM(gen);
28808#if OS(WINDOWS) && ENABLE(C_LOOP)
28809 // FIXME: Disable wide16 optimization for Windows CLoop
28810 // https://bugs.webkit.org/show_bug.cgi?id=198283
28811 if (size == OpcodeSize::Wide16)
28812 return false;
28813#endif
28814 return Fits<OpcodeID, size>::check(opcodeID)
28815 && Fits<DebugHookType, size>::check(debugHookType)
28816 && Fits<bool, size>::check(hasBreakpoint)
28817 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
28818 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
28819 }
28820
28821 template<OpcodeSize size, bool recordOpcode>
28822 static bool emitImpl(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
28823 {
28824 if (size == OpcodeSize::Wide16)
28825 gen->alignWideOpcode16();
28826 else if (size == OpcodeSize::Wide32)
28827 gen->alignWideOpcode32();
28828 if (checkImpl<size>(gen, debugHookType, hasBreakpoint)) {
28829 if (recordOpcode)
28830 gen->recordOpcode(opcodeID);
28831 if (size == OpcodeSize::Wide16)
28832 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
28833 else if (size == OpcodeSize::Wide32)
28834 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
28835 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
28836 gen->write(Fits<DebugHookType, size>::convert(debugHookType));
28837 gen->write(Fits<bool, size>::convert(hasBreakpoint));
28838 return true;
28839 }
28840 return false;
28841 }
28842
28843public:
28844 template<typename Block>
28845 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
28846 {
28847 dumper->printLocationAndOp(__location, &"**debug"[2 - __sizeShiftAmount]);
28848 dumper->dumpOperand(m_debugHookType, true);
28849 dumper->dumpOperand(m_hasBreakpoint, false);
28850 }
28851
28852 OpDebug(const uint8_t* stream)
28853 : m_debugHookType(Fits<DebugHookType, OpcodeSize::Narrow>::convert(stream[1]))
28854 , m_hasBreakpoint(Fits<bool, OpcodeSize::Narrow>::convert(stream[2]))
28855 {
28856 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28857 }
28858
28859 OpDebug(const uint16_t* stream)
28860 : m_debugHookType(Fits<DebugHookType, OpcodeSize::Wide16>::convert(stream[1]))
28861 , m_hasBreakpoint(Fits<bool, OpcodeSize::Wide16>::convert(stream[2]))
28862 {
28863 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28864 }
28865
28866
28867 OpDebug(const uint32_t* stream)
28868 : m_debugHookType(Fits<DebugHookType, OpcodeSize::Wide32>::convert(stream[1]))
28869 , m_hasBreakpoint(Fits<bool, OpcodeSize::Wide32>::convert(stream[2]))
28870 {
28871 ASSERT_UNUSED(stream, stream[0] == opcodeID);
28872 }
28873
28874 static OpDebug decode(const uint8_t* stream)
28875 {
28876 if (*stream == op_wide32)
28877 return { bitwise_cast<const uint32_t*>(stream + 1) };
28878 if (*stream == op_wide16)
28879 return { bitwise_cast<const uint16_t*>(stream + 1) };
28880 return { stream };
28881 }
28882
28883 template<typename Functor>
28884 void setDebugHookType(DebugHookType value, Functor func)
28885 {
28886 if (isWide32())
28887 setDebugHookType<OpcodeSize::Wide32>(value, func);
28888 else if (isWide16())
28889 setDebugHookType<OpcodeSize::Wide16>(value, func);
28890 else
28891 setDebugHookType<OpcodeSize::Narrow>(value, func);
28892 }
28893
28894 template <OpcodeSize size, typename Functor>
28895 void setDebugHookType(DebugHookType value, Functor func)
28896 {
28897 if (!Fits<DebugHookType, size>::check(value))
28898 value = func();
28899 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
28900 *stream = Fits<DebugHookType, size>::convert(value);
28901 }
28902
28903 template<typename Functor>
28904 void setHasBreakpoint(bool value, Functor func)
28905 {
28906 if (isWide32())
28907 setHasBreakpoint<OpcodeSize::Wide32>(value, func);
28908 else if (isWide16())
28909 setHasBreakpoint<OpcodeSize::Wide16>(value, func);
28910 else
28911 setHasBreakpoint<OpcodeSize::Narrow>(value, func);
28912 }
28913
28914 template <OpcodeSize size, typename Functor>
28915 void setHasBreakpoint(bool value, Functor func)
28916 {
28917 if (!Fits<bool, size>::check(value))
28918 value = func();
28919 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
28920 *stream = Fits<bool, size>::convert(value);
28921 }
28922
28923 DebugHookType m_debugHookType;
28924 bool m_hasBreakpoint;
28925};
28926
28927struct OpEnd : public Instruction {
28928 static constexpr OpcodeID opcodeID = op_end;
28929
28930 static void emit(BytecodeGenerator* gen, VirtualRegister value)
28931 {
28932 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, value);
28933 }
28934
28935 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
28936 static bool emit(BytecodeGenerator* gen, VirtualRegister value)
28937 {
28938 bool didEmit = emitImpl<size, recordOpcode>(gen, value);
28939 if (shouldAssert == Assert)
28940 ASSERT(didEmit);
28941 return didEmit;
28942 }
28943
28944 template<OpcodeSize size>
28945 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
28946 {
28947
28948 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
28949 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value))
28950 return;
28951 }
28952 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
28953 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value))
28954 return;
28955 }
28956 emit<OpcodeSize::Wide32, Assert, true>(gen, value);
28957 }
28958
28959private:
28960 template<OpcodeSize size>
28961 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value)
28962 {
28963 UNUSED_PARAM(gen);
28964#if OS(WINDOWS) && ENABLE(C_LOOP)
28965 // FIXME: Disable wide16 optimization for Windows CLoop
28966 // https://bugs.webkit.org/show_bug.cgi?id=198283
28967 if (size == OpcodeSize::Wide16)
28968 return false;
28969#endif
28970 return Fits<OpcodeID, size>::check(opcodeID)
28971 && Fits<VirtualRegister, size>::check(value)
28972 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
28973 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
28974 }
28975
28976 template<OpcodeSize size, bool recordOpcode>
28977 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value)
28978 {
28979 if (size == OpcodeSize::Wide16)
28980 gen->alignWideOpcode16();
28981 else if (size == OpcodeSize::Wide32)
28982 gen->alignWideOpcode32();
28983 if (checkImpl<size>(gen, value)) {
28984 if (recordOpcode)
28985 gen->recordOpcode(opcodeID);
28986 if (size == OpcodeSize::Wide16)
28987 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
28988 else if (size == OpcodeSize::Wide32)
28989 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
28990 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
28991 gen->write(Fits<VirtualRegister, size>::convert(value));
28992 return true;
28993 }
28994 return false;
28995 }
28996
28997public:
28998 template<typename Block>
28999 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
29000 {
29001 dumper->printLocationAndOp(__location, &"**end"[2 - __sizeShiftAmount]);
29002 dumper->dumpOperand(m_value, true);
29003 }
29004
29005 OpEnd(const uint8_t* stream)
29006 : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
29007 {
29008 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29009 }
29010
29011 OpEnd(const uint16_t* stream)
29012 : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
29013 {
29014 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29015 }
29016
29017
29018 OpEnd(const uint32_t* stream)
29019 : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
29020 {
29021 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29022 }
29023
29024 static OpEnd decode(const uint8_t* stream)
29025 {
29026 if (*stream == op_wide32)
29027 return { bitwise_cast<const uint32_t*>(stream + 1) };
29028 if (*stream == op_wide16)
29029 return { bitwise_cast<const uint16_t*>(stream + 1) };
29030 return { stream };
29031 }
29032
29033 template<typename Functor>
29034 void setValue(VirtualRegister value, Functor func)
29035 {
29036 if (isWide32())
29037 setValue<OpcodeSize::Wide32>(value, func);
29038 else if (isWide16())
29039 setValue<OpcodeSize::Wide16>(value, func);
29040 else
29041 setValue<OpcodeSize::Narrow>(value, func);
29042 }
29043
29044 template <OpcodeSize size, typename Functor>
29045 void setValue(VirtualRegister value, Functor func)
29046 {
29047 if (!Fits<VirtualRegister, size>::check(value))
29048 value = func();
29049 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
29050 *stream = Fits<VirtualRegister, size>::convert(value);
29051 }
29052
29053 VirtualRegister m_value;
29054};
29055
29056struct OpGetEnumerableLength : public Instruction {
29057 static constexpr OpcodeID opcodeID = op_get_enumerable_length;
29058
29059 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29060 {
29061 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base);
29062 }
29063
29064 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
29065 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29066 {
29067 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base);
29068 if (shouldAssert == Assert)
29069 ASSERT(didEmit);
29070 return didEmit;
29071 }
29072
29073 template<OpcodeSize size>
29074 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29075 {
29076
29077 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
29078 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base))
29079 return;
29080 }
29081 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
29082 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base))
29083 return;
29084 }
29085 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base);
29086 }
29087
29088private:
29089 template<OpcodeSize size>
29090 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base)
29091 {
29092 UNUSED_PARAM(gen);
29093#if OS(WINDOWS) && ENABLE(C_LOOP)
29094 // FIXME: Disable wide16 optimization for Windows CLoop
29095 // https://bugs.webkit.org/show_bug.cgi?id=198283
29096 if (size == OpcodeSize::Wide16)
29097 return false;
29098#endif
29099 return Fits<OpcodeID, size>::check(opcodeID)
29100 && Fits<VirtualRegister, size>::check(dst)
29101 && Fits<VirtualRegister, size>::check(base)
29102 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
29103 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
29104 }
29105
29106 template<OpcodeSize size, bool recordOpcode>
29107 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29108 {
29109 if (size == OpcodeSize::Wide16)
29110 gen->alignWideOpcode16();
29111 else if (size == OpcodeSize::Wide32)
29112 gen->alignWideOpcode32();
29113 if (checkImpl<size>(gen, dst, base)) {
29114 if (recordOpcode)
29115 gen->recordOpcode(opcodeID);
29116 if (size == OpcodeSize::Wide16)
29117 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
29118 else if (size == OpcodeSize::Wide32)
29119 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
29120 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
29121 gen->write(Fits<VirtualRegister, size>::convert(dst));
29122 gen->write(Fits<VirtualRegister, size>::convert(base));
29123 return true;
29124 }
29125 return false;
29126 }
29127
29128public:
29129 template<typename Block>
29130 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
29131 {
29132 dumper->printLocationAndOp(__location, &"**get_enumerable_length"[2 - __sizeShiftAmount]);
29133 dumper->dumpOperand(m_dst, true);
29134 dumper->dumpOperand(m_base, false);
29135 }
29136
29137 OpGetEnumerableLength(const uint8_t* stream)
29138 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
29139 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
29140 {
29141 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29142 }
29143
29144 OpGetEnumerableLength(const uint16_t* stream)
29145 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
29146 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
29147 {
29148 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29149 }
29150
29151
29152 OpGetEnumerableLength(const uint32_t* stream)
29153 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
29154 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
29155 {
29156 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29157 }
29158
29159 static OpGetEnumerableLength decode(const uint8_t* stream)
29160 {
29161 if (*stream == op_wide32)
29162 return { bitwise_cast<const uint32_t*>(stream + 1) };
29163 if (*stream == op_wide16)
29164 return { bitwise_cast<const uint16_t*>(stream + 1) };
29165 return { stream };
29166 }
29167
29168 template<typename Functor>
29169 void setDst(VirtualRegister value, Functor func)
29170 {
29171 if (isWide32())
29172 setDst<OpcodeSize::Wide32>(value, func);
29173 else if (isWide16())
29174 setDst<OpcodeSize::Wide16>(value, func);
29175 else
29176 setDst<OpcodeSize::Narrow>(value, func);
29177 }
29178
29179 template <OpcodeSize size, typename Functor>
29180 void setDst(VirtualRegister value, Functor func)
29181 {
29182 if (!Fits<VirtualRegister, size>::check(value))
29183 value = func();
29184 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
29185 *stream = Fits<VirtualRegister, size>::convert(value);
29186 }
29187
29188 template<typename Functor>
29189 void setBase(VirtualRegister value, Functor func)
29190 {
29191 if (isWide32())
29192 setBase<OpcodeSize::Wide32>(value, func);
29193 else if (isWide16())
29194 setBase<OpcodeSize::Wide16>(value, func);
29195 else
29196 setBase<OpcodeSize::Narrow>(value, func);
29197 }
29198
29199 template <OpcodeSize size, typename Functor>
29200 void setBase(VirtualRegister value, Functor func)
29201 {
29202 if (!Fits<VirtualRegister, size>::check(value))
29203 value = func();
29204 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
29205 *stream = Fits<VirtualRegister, size>::convert(value);
29206 }
29207
29208 VirtualRegister m_dst;
29209 VirtualRegister m_base;
29210};
29211
29212struct OpHasStructureProperty : public Instruction {
29213 static constexpr OpcodeID opcodeID = op_has_structure_property;
29214
29215 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
29216 {
29217 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property, enumerator);
29218 }
29219
29220 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
29221 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
29222 {
29223 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property, enumerator);
29224 if (shouldAssert == Assert)
29225 ASSERT(didEmit);
29226 return didEmit;
29227 }
29228
29229 template<OpcodeSize size>
29230 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
29231 {
29232
29233 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
29234 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property, enumerator))
29235 return;
29236 }
29237 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
29238 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, enumerator))
29239 return;
29240 }
29241 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, enumerator);
29242 }
29243
29244private:
29245 template<OpcodeSize size>
29246 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, VirtualRegister& enumerator)
29247 {
29248 UNUSED_PARAM(gen);
29249#if OS(WINDOWS) && ENABLE(C_LOOP)
29250 // FIXME: Disable wide16 optimization for Windows CLoop
29251 // https://bugs.webkit.org/show_bug.cgi?id=198283
29252 if (size == OpcodeSize::Wide16)
29253 return false;
29254#endif
29255 return Fits<OpcodeID, size>::check(opcodeID)
29256 && Fits<VirtualRegister, size>::check(dst)
29257 && Fits<VirtualRegister, size>::check(base)
29258 && Fits<VirtualRegister, size>::check(property)
29259 && Fits<VirtualRegister, size>::check(enumerator)
29260 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
29261 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
29262 }
29263
29264 template<OpcodeSize size, bool recordOpcode>
29265 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
29266 {
29267 if (size == OpcodeSize::Wide16)
29268 gen->alignWideOpcode16();
29269 else if (size == OpcodeSize::Wide32)
29270 gen->alignWideOpcode32();
29271 if (checkImpl<size>(gen, dst, base, property, enumerator)) {
29272 if (recordOpcode)
29273 gen->recordOpcode(opcodeID);
29274 if (size == OpcodeSize::Wide16)
29275 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
29276 else if (size == OpcodeSize::Wide32)
29277 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
29278 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
29279 gen->write(Fits<VirtualRegister, size>::convert(dst));
29280 gen->write(Fits<VirtualRegister, size>::convert(base));
29281 gen->write(Fits<VirtualRegister, size>::convert(property));
29282 gen->write(Fits<VirtualRegister, size>::convert(enumerator));
29283 return true;
29284 }
29285 return false;
29286 }
29287
29288public:
29289 template<typename Block>
29290 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
29291 {
29292 dumper->printLocationAndOp(__location, &"**has_structure_property"[2 - __sizeShiftAmount]);
29293 dumper->dumpOperand(m_dst, true);
29294 dumper->dumpOperand(m_base, false);
29295 dumper->dumpOperand(m_property, false);
29296 dumper->dumpOperand(m_enumerator, false);
29297 }
29298
29299 OpHasStructureProperty(const uint8_t* stream)
29300 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
29301 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
29302 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
29303 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
29304 {
29305 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29306 }
29307
29308 OpHasStructureProperty(const uint16_t* stream)
29309 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
29310 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
29311 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
29312 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
29313 {
29314 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29315 }
29316
29317
29318 OpHasStructureProperty(const uint32_t* stream)
29319 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
29320 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
29321 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
29322 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
29323 {
29324 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29325 }
29326
29327 static OpHasStructureProperty decode(const uint8_t* stream)
29328 {
29329 if (*stream == op_wide32)
29330 return { bitwise_cast<const uint32_t*>(stream + 1) };
29331 if (*stream == op_wide16)
29332 return { bitwise_cast<const uint16_t*>(stream + 1) };
29333 return { stream };
29334 }
29335
29336 template<typename Functor>
29337 void setDst(VirtualRegister value, Functor func)
29338 {
29339 if (isWide32())
29340 setDst<OpcodeSize::Wide32>(value, func);
29341 else if (isWide16())
29342 setDst<OpcodeSize::Wide16>(value, func);
29343 else
29344 setDst<OpcodeSize::Narrow>(value, func);
29345 }
29346
29347 template <OpcodeSize size, typename Functor>
29348 void setDst(VirtualRegister value, Functor func)
29349 {
29350 if (!Fits<VirtualRegister, size>::check(value))
29351 value = func();
29352 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
29353 *stream = Fits<VirtualRegister, size>::convert(value);
29354 }
29355
29356 template<typename Functor>
29357 void setBase(VirtualRegister value, Functor func)
29358 {
29359 if (isWide32())
29360 setBase<OpcodeSize::Wide32>(value, func);
29361 else if (isWide16())
29362 setBase<OpcodeSize::Wide16>(value, func);
29363 else
29364 setBase<OpcodeSize::Narrow>(value, func);
29365 }
29366
29367 template <OpcodeSize size, typename Functor>
29368 void setBase(VirtualRegister value, Functor func)
29369 {
29370 if (!Fits<VirtualRegister, size>::check(value))
29371 value = func();
29372 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
29373 *stream = Fits<VirtualRegister, size>::convert(value);
29374 }
29375
29376 template<typename Functor>
29377 void setProperty(VirtualRegister value, Functor func)
29378 {
29379 if (isWide32())
29380 setProperty<OpcodeSize::Wide32>(value, func);
29381 else if (isWide16())
29382 setProperty<OpcodeSize::Wide16>(value, func);
29383 else
29384 setProperty<OpcodeSize::Narrow>(value, func);
29385 }
29386
29387 template <OpcodeSize size, typename Functor>
29388 void setProperty(VirtualRegister value, Functor func)
29389 {
29390 if (!Fits<VirtualRegister, size>::check(value))
29391 value = func();
29392 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
29393 *stream = Fits<VirtualRegister, size>::convert(value);
29394 }
29395
29396 template<typename Functor>
29397 void setEnumerator(VirtualRegister value, Functor func)
29398 {
29399 if (isWide32())
29400 setEnumerator<OpcodeSize::Wide32>(value, func);
29401 else if (isWide16())
29402 setEnumerator<OpcodeSize::Wide16>(value, func);
29403 else
29404 setEnumerator<OpcodeSize::Narrow>(value, func);
29405 }
29406
29407 template <OpcodeSize size, typename Functor>
29408 void setEnumerator(VirtualRegister value, Functor func)
29409 {
29410 if (!Fits<VirtualRegister, size>::check(value))
29411 value = func();
29412 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value);
29413 *stream = Fits<VirtualRegister, size>::convert(value);
29414 }
29415
29416 VirtualRegister m_dst;
29417 VirtualRegister m_base;
29418 VirtualRegister m_property;
29419 VirtualRegister m_enumerator;
29420};
29421
29422struct OpHasGenericProperty : public Instruction {
29423 static constexpr OpcodeID opcodeID = op_has_generic_property;
29424
29425 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
29426 {
29427 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base, property);
29428 }
29429
29430 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
29431 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
29432 {
29433 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base, property);
29434 if (shouldAssert == Assert)
29435 ASSERT(didEmit);
29436 return didEmit;
29437 }
29438
29439 template<OpcodeSize size>
29440 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
29441 {
29442
29443 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
29444 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base, property))
29445 return;
29446 }
29447 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
29448 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
29449 return;
29450 }
29451 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
29452 }
29453
29454private:
29455 template<OpcodeSize size>
29456 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property)
29457 {
29458 UNUSED_PARAM(gen);
29459#if OS(WINDOWS) && ENABLE(C_LOOP)
29460 // FIXME: Disable wide16 optimization for Windows CLoop
29461 // https://bugs.webkit.org/show_bug.cgi?id=198283
29462 if (size == OpcodeSize::Wide16)
29463 return false;
29464#endif
29465 return Fits<OpcodeID, size>::check(opcodeID)
29466 && Fits<VirtualRegister, size>::check(dst)
29467 && Fits<VirtualRegister, size>::check(base)
29468 && Fits<VirtualRegister, size>::check(property)
29469 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
29470 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
29471 }
29472
29473 template<OpcodeSize size, bool recordOpcode>
29474 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
29475 {
29476 if (size == OpcodeSize::Wide16)
29477 gen->alignWideOpcode16();
29478 else if (size == OpcodeSize::Wide32)
29479 gen->alignWideOpcode32();
29480 if (checkImpl<size>(gen, dst, base, property)) {
29481 if (recordOpcode)
29482 gen->recordOpcode(opcodeID);
29483 if (size == OpcodeSize::Wide16)
29484 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
29485 else if (size == OpcodeSize::Wide32)
29486 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
29487 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
29488 gen->write(Fits<VirtualRegister, size>::convert(dst));
29489 gen->write(Fits<VirtualRegister, size>::convert(base));
29490 gen->write(Fits<VirtualRegister, size>::convert(property));
29491 return true;
29492 }
29493 return false;
29494 }
29495
29496public:
29497 template<typename Block>
29498 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
29499 {
29500 dumper->printLocationAndOp(__location, &"**has_generic_property"[2 - __sizeShiftAmount]);
29501 dumper->dumpOperand(m_dst, true);
29502 dumper->dumpOperand(m_base, false);
29503 dumper->dumpOperand(m_property, false);
29504 }
29505
29506 OpHasGenericProperty(const uint8_t* stream)
29507 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
29508 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
29509 , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
29510 {
29511 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29512 }
29513
29514 OpHasGenericProperty(const uint16_t* stream)
29515 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
29516 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
29517 , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
29518 {
29519 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29520 }
29521
29522
29523 OpHasGenericProperty(const uint32_t* stream)
29524 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
29525 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
29526 , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
29527 {
29528 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29529 }
29530
29531 static OpHasGenericProperty decode(const uint8_t* stream)
29532 {
29533 if (*stream == op_wide32)
29534 return { bitwise_cast<const uint32_t*>(stream + 1) };
29535 if (*stream == op_wide16)
29536 return { bitwise_cast<const uint16_t*>(stream + 1) };
29537 return { stream };
29538 }
29539
29540 template<typename Functor>
29541 void setDst(VirtualRegister value, Functor func)
29542 {
29543 if (isWide32())
29544 setDst<OpcodeSize::Wide32>(value, func);
29545 else if (isWide16())
29546 setDst<OpcodeSize::Wide16>(value, func);
29547 else
29548 setDst<OpcodeSize::Narrow>(value, func);
29549 }
29550
29551 template <OpcodeSize size, typename Functor>
29552 void setDst(VirtualRegister value, Functor func)
29553 {
29554 if (!Fits<VirtualRegister, size>::check(value))
29555 value = func();
29556 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
29557 *stream = Fits<VirtualRegister, size>::convert(value);
29558 }
29559
29560 template<typename Functor>
29561 void setBase(VirtualRegister value, Functor func)
29562 {
29563 if (isWide32())
29564 setBase<OpcodeSize::Wide32>(value, func);
29565 else if (isWide16())
29566 setBase<OpcodeSize::Wide16>(value, func);
29567 else
29568 setBase<OpcodeSize::Narrow>(value, func);
29569 }
29570
29571 template <OpcodeSize size, typename Functor>
29572 void setBase(VirtualRegister value, Functor func)
29573 {
29574 if (!Fits<VirtualRegister, size>::check(value))
29575 value = func();
29576 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
29577 *stream = Fits<VirtualRegister, size>::convert(value);
29578 }
29579
29580 template<typename Functor>
29581 void setProperty(VirtualRegister value, Functor func)
29582 {
29583 if (isWide32())
29584 setProperty<OpcodeSize::Wide32>(value, func);
29585 else if (isWide16())
29586 setProperty<OpcodeSize::Wide16>(value, func);
29587 else
29588 setProperty<OpcodeSize::Narrow>(value, func);
29589 }
29590
29591 template <OpcodeSize size, typename Functor>
29592 void setProperty(VirtualRegister value, Functor func)
29593 {
29594 if (!Fits<VirtualRegister, size>::check(value))
29595 value = func();
29596 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
29597 *stream = Fits<VirtualRegister, size>::convert(value);
29598 }
29599
29600 VirtualRegister m_dst;
29601 VirtualRegister m_base;
29602 VirtualRegister m_property;
29603};
29604
29605struct OpGetPropertyEnumerator : public Instruction {
29606 static constexpr OpcodeID opcodeID = op_get_property_enumerator;
29607
29608 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29609 {
29610 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, base);
29611 }
29612
29613 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
29614 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29615 {
29616 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, base);
29617 if (shouldAssert == Assert)
29618 ASSERT(didEmit);
29619 return didEmit;
29620 }
29621
29622 template<OpcodeSize size>
29623 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29624 {
29625
29626 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
29627 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base))
29628 return;
29629 }
29630 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
29631 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base))
29632 return;
29633 }
29634 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base);
29635 }
29636
29637private:
29638 template<OpcodeSize size>
29639 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base)
29640 {
29641 UNUSED_PARAM(gen);
29642#if OS(WINDOWS) && ENABLE(C_LOOP)
29643 // FIXME: Disable wide16 optimization for Windows CLoop
29644 // https://bugs.webkit.org/show_bug.cgi?id=198283
29645 if (size == OpcodeSize::Wide16)
29646 return false;
29647#endif
29648 return Fits<OpcodeID, size>::check(opcodeID)
29649 && Fits<VirtualRegister, size>::check(dst)
29650 && Fits<VirtualRegister, size>::check(base)
29651 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
29652 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
29653 }
29654
29655 template<OpcodeSize size, bool recordOpcode>
29656 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
29657 {
29658 if (size == OpcodeSize::Wide16)
29659 gen->alignWideOpcode16();
29660 else if (size == OpcodeSize::Wide32)
29661 gen->alignWideOpcode32();
29662 if (checkImpl<size>(gen, dst, base)) {
29663 if (recordOpcode)
29664 gen->recordOpcode(opcodeID);
29665 if (size == OpcodeSize::Wide16)
29666 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
29667 else if (size == OpcodeSize::Wide32)
29668 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
29669 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
29670 gen->write(Fits<VirtualRegister, size>::convert(dst));
29671 gen->write(Fits<VirtualRegister, size>::convert(base));
29672 return true;
29673 }
29674 return false;
29675 }
29676
29677public:
29678 template<typename Block>
29679 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
29680 {
29681 dumper->printLocationAndOp(__location, &"**get_property_enumerator"[2 - __sizeShiftAmount]);
29682 dumper->dumpOperand(m_dst, true);
29683 dumper->dumpOperand(m_base, false);
29684 }
29685
29686 OpGetPropertyEnumerator(const uint8_t* stream)
29687 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
29688 , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
29689 {
29690 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29691 }
29692
29693 OpGetPropertyEnumerator(const uint16_t* stream)
29694 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
29695 , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
29696 {
29697 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29698 }
29699
29700
29701 OpGetPropertyEnumerator(const uint32_t* stream)
29702 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
29703 , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
29704 {
29705 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29706 }
29707
29708 static OpGetPropertyEnumerator decode(const uint8_t* stream)
29709 {
29710 if (*stream == op_wide32)
29711 return { bitwise_cast<const uint32_t*>(stream + 1) };
29712 if (*stream == op_wide16)
29713 return { bitwise_cast<const uint16_t*>(stream + 1) };
29714 return { stream };
29715 }
29716
29717 template<typename Functor>
29718 void setDst(VirtualRegister value, Functor func)
29719 {
29720 if (isWide32())
29721 setDst<OpcodeSize::Wide32>(value, func);
29722 else if (isWide16())
29723 setDst<OpcodeSize::Wide16>(value, func);
29724 else
29725 setDst<OpcodeSize::Narrow>(value, func);
29726 }
29727
29728 template <OpcodeSize size, typename Functor>
29729 void setDst(VirtualRegister value, Functor func)
29730 {
29731 if (!Fits<VirtualRegister, size>::check(value))
29732 value = func();
29733 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
29734 *stream = Fits<VirtualRegister, size>::convert(value);
29735 }
29736
29737 template<typename Functor>
29738 void setBase(VirtualRegister value, Functor func)
29739 {
29740 if (isWide32())
29741 setBase<OpcodeSize::Wide32>(value, func);
29742 else if (isWide16())
29743 setBase<OpcodeSize::Wide16>(value, func);
29744 else
29745 setBase<OpcodeSize::Narrow>(value, func);
29746 }
29747
29748 template <OpcodeSize size, typename Functor>
29749 void setBase(VirtualRegister value, Functor func)
29750 {
29751 if (!Fits<VirtualRegister, size>::check(value))
29752 value = func();
29753 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
29754 *stream = Fits<VirtualRegister, size>::convert(value);
29755 }
29756
29757 VirtualRegister m_dst;
29758 VirtualRegister m_base;
29759};
29760
29761struct OpEnumeratorStructurePname : public Instruction {
29762 static constexpr OpcodeID opcodeID = op_enumerator_structure_pname;
29763
29764 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29765 {
29766 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, enumerator, index);
29767 }
29768
29769 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
29770 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29771 {
29772 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, enumerator, index);
29773 if (shouldAssert == Assert)
29774 ASSERT(didEmit);
29775 return didEmit;
29776 }
29777
29778 template<OpcodeSize size>
29779 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29780 {
29781
29782 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
29783 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, enumerator, index))
29784 return;
29785 }
29786 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
29787 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, enumerator, index))
29788 return;
29789 }
29790 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, enumerator, index);
29791 }
29792
29793private:
29794 template<OpcodeSize size>
29795 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& enumerator, VirtualRegister& index)
29796 {
29797 UNUSED_PARAM(gen);
29798#if OS(WINDOWS) && ENABLE(C_LOOP)
29799 // FIXME: Disable wide16 optimization for Windows CLoop
29800 // https://bugs.webkit.org/show_bug.cgi?id=198283
29801 if (size == OpcodeSize::Wide16)
29802 return false;
29803#endif
29804 return Fits<OpcodeID, size>::check(opcodeID)
29805 && Fits<VirtualRegister, size>::check(dst)
29806 && Fits<VirtualRegister, size>::check(enumerator)
29807 && Fits<VirtualRegister, size>::check(index)
29808 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
29809 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
29810 }
29811
29812 template<OpcodeSize size, bool recordOpcode>
29813 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29814 {
29815 if (size == OpcodeSize::Wide16)
29816 gen->alignWideOpcode16();
29817 else if (size == OpcodeSize::Wide32)
29818 gen->alignWideOpcode32();
29819 if (checkImpl<size>(gen, dst, enumerator, index)) {
29820 if (recordOpcode)
29821 gen->recordOpcode(opcodeID);
29822 if (size == OpcodeSize::Wide16)
29823 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
29824 else if (size == OpcodeSize::Wide32)
29825 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
29826 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
29827 gen->write(Fits<VirtualRegister, size>::convert(dst));
29828 gen->write(Fits<VirtualRegister, size>::convert(enumerator));
29829 gen->write(Fits<VirtualRegister, size>::convert(index));
29830 return true;
29831 }
29832 return false;
29833 }
29834
29835public:
29836 template<typename Block>
29837 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
29838 {
29839 dumper->printLocationAndOp(__location, &"**enumerator_structure_pname"[2 - __sizeShiftAmount]);
29840 dumper->dumpOperand(m_dst, true);
29841 dumper->dumpOperand(m_enumerator, false);
29842 dumper->dumpOperand(m_index, false);
29843 }
29844
29845 OpEnumeratorStructurePname(const uint8_t* stream)
29846 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
29847 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
29848 , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
29849 {
29850 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29851 }
29852
29853 OpEnumeratorStructurePname(const uint16_t* stream)
29854 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
29855 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
29856 , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
29857 {
29858 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29859 }
29860
29861
29862 OpEnumeratorStructurePname(const uint32_t* stream)
29863 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
29864 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
29865 , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
29866 {
29867 ASSERT_UNUSED(stream, stream[0] == opcodeID);
29868 }
29869
29870 static OpEnumeratorStructurePname decode(const uint8_t* stream)
29871 {
29872 if (*stream == op_wide32)
29873 return { bitwise_cast<const uint32_t*>(stream + 1) };
29874 if (*stream == op_wide16)
29875 return { bitwise_cast<const uint16_t*>(stream + 1) };
29876 return { stream };
29877 }
29878
29879 template<typename Functor>
29880 void setDst(VirtualRegister value, Functor func)
29881 {
29882 if (isWide32())
29883 setDst<OpcodeSize::Wide32>(value, func);
29884 else if (isWide16())
29885 setDst<OpcodeSize::Wide16>(value, func);
29886 else
29887 setDst<OpcodeSize::Narrow>(value, func);
29888 }
29889
29890 template <OpcodeSize size, typename Functor>
29891 void setDst(VirtualRegister value, Functor func)
29892 {
29893 if (!Fits<VirtualRegister, size>::check(value))
29894 value = func();
29895 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
29896 *stream = Fits<VirtualRegister, size>::convert(value);
29897 }
29898
29899 template<typename Functor>
29900 void setEnumerator(VirtualRegister value, Functor func)
29901 {
29902 if (isWide32())
29903 setEnumerator<OpcodeSize::Wide32>(value, func);
29904 else if (isWide16())
29905 setEnumerator<OpcodeSize::Wide16>(value, func);
29906 else
29907 setEnumerator<OpcodeSize::Narrow>(value, func);
29908 }
29909
29910 template <OpcodeSize size, typename Functor>
29911 void setEnumerator(VirtualRegister value, Functor func)
29912 {
29913 if (!Fits<VirtualRegister, size>::check(value))
29914 value = func();
29915 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
29916 *stream = Fits<VirtualRegister, size>::convert(value);
29917 }
29918
29919 template<typename Functor>
29920 void setIndex(VirtualRegister value, Functor func)
29921 {
29922 if (isWide32())
29923 setIndex<OpcodeSize::Wide32>(value, func);
29924 else if (isWide16())
29925 setIndex<OpcodeSize::Wide16>(value, func);
29926 else
29927 setIndex<OpcodeSize::Narrow>(value, func);
29928 }
29929
29930 template <OpcodeSize size, typename Functor>
29931 void setIndex(VirtualRegister value, Functor func)
29932 {
29933 if (!Fits<VirtualRegister, size>::check(value))
29934 value = func();
29935 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
29936 *stream = Fits<VirtualRegister, size>::convert(value);
29937 }
29938
29939 VirtualRegister m_dst;
29940 VirtualRegister m_enumerator;
29941 VirtualRegister m_index;
29942};
29943
29944struct OpEnumeratorGenericPname : public Instruction {
29945 static constexpr OpcodeID opcodeID = op_enumerator_generic_pname;
29946
29947 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29948 {
29949 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, enumerator, index);
29950 }
29951
29952 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
29953 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29954 {
29955 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, enumerator, index);
29956 if (shouldAssert == Assert)
29957 ASSERT(didEmit);
29958 return didEmit;
29959 }
29960
29961 template<OpcodeSize size>
29962 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29963 {
29964
29965 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
29966 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, enumerator, index))
29967 return;
29968 }
29969 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
29970 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, enumerator, index))
29971 return;
29972 }
29973 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, enumerator, index);
29974 }
29975
29976private:
29977 template<OpcodeSize size>
29978 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& enumerator, VirtualRegister& index)
29979 {
29980 UNUSED_PARAM(gen);
29981#if OS(WINDOWS) && ENABLE(C_LOOP)
29982 // FIXME: Disable wide16 optimization for Windows CLoop
29983 // https://bugs.webkit.org/show_bug.cgi?id=198283
29984 if (size == OpcodeSize::Wide16)
29985 return false;
29986#endif
29987 return Fits<OpcodeID, size>::check(opcodeID)
29988 && Fits<VirtualRegister, size>::check(dst)
29989 && Fits<VirtualRegister, size>::check(enumerator)
29990 && Fits<VirtualRegister, size>::check(index)
29991 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
29992 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
29993 }
29994
29995 template<OpcodeSize size, bool recordOpcode>
29996 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
29997 {
29998 if (size == OpcodeSize::Wide16)
29999 gen->alignWideOpcode16();
30000 else if (size == OpcodeSize::Wide32)
30001 gen->alignWideOpcode32();
30002 if (checkImpl<size>(gen, dst, enumerator, index)) {
30003 if (recordOpcode)
30004 gen->recordOpcode(opcodeID);
30005 if (size == OpcodeSize::Wide16)
30006 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
30007 else if (size == OpcodeSize::Wide32)
30008 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
30009 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
30010 gen->write(Fits<VirtualRegister, size>::convert(dst));
30011 gen->write(Fits<VirtualRegister, size>::convert(enumerator));
30012 gen->write(Fits<VirtualRegister, size>::convert(index));
30013 return true;
30014 }
30015 return false;
30016 }
30017
30018public:
30019 template<typename Block>
30020 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
30021 {
30022 dumper->printLocationAndOp(__location, &"**enumerator_generic_pname"[2 - __sizeShiftAmount]);
30023 dumper->dumpOperand(m_dst, true);
30024 dumper->dumpOperand(m_enumerator, false);
30025 dumper->dumpOperand(m_index, false);
30026 }
30027
30028 OpEnumeratorGenericPname(const uint8_t* stream)
30029 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
30030 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
30031 , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
30032 {
30033 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30034 }
30035
30036 OpEnumeratorGenericPname(const uint16_t* stream)
30037 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
30038 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
30039 , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
30040 {
30041 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30042 }
30043
30044
30045 OpEnumeratorGenericPname(const uint32_t* stream)
30046 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
30047 , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
30048 , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
30049 {
30050 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30051 }
30052
30053 static OpEnumeratorGenericPname decode(const uint8_t* stream)
30054 {
30055 if (*stream == op_wide32)
30056 return { bitwise_cast<const uint32_t*>(stream + 1) };
30057 if (*stream == op_wide16)
30058 return { bitwise_cast<const uint16_t*>(stream + 1) };
30059 return { stream };
30060 }
30061
30062 template<typename Functor>
30063 void setDst(VirtualRegister value, Functor func)
30064 {
30065 if (isWide32())
30066 setDst<OpcodeSize::Wide32>(value, func);
30067 else if (isWide16())
30068 setDst<OpcodeSize::Wide16>(value, func);
30069 else
30070 setDst<OpcodeSize::Narrow>(value, func);
30071 }
30072
30073 template <OpcodeSize size, typename Functor>
30074 void setDst(VirtualRegister value, Functor func)
30075 {
30076 if (!Fits<VirtualRegister, size>::check(value))
30077 value = func();
30078 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
30079 *stream = Fits<VirtualRegister, size>::convert(value);
30080 }
30081
30082 template<typename Functor>
30083 void setEnumerator(VirtualRegister value, Functor func)
30084 {
30085 if (isWide32())
30086 setEnumerator<OpcodeSize::Wide32>(value, func);
30087 else if (isWide16())
30088 setEnumerator<OpcodeSize::Wide16>(value, func);
30089 else
30090 setEnumerator<OpcodeSize::Narrow>(value, func);
30091 }
30092
30093 template <OpcodeSize size, typename Functor>
30094 void setEnumerator(VirtualRegister value, Functor func)
30095 {
30096 if (!Fits<VirtualRegister, size>::check(value))
30097 value = func();
30098 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
30099 *stream = Fits<VirtualRegister, size>::convert(value);
30100 }
30101
30102 template<typename Functor>
30103 void setIndex(VirtualRegister value, Functor func)
30104 {
30105 if (isWide32())
30106 setIndex<OpcodeSize::Wide32>(value, func);
30107 else if (isWide16())
30108 setIndex<OpcodeSize::Wide16>(value, func);
30109 else
30110 setIndex<OpcodeSize::Narrow>(value, func);
30111 }
30112
30113 template <OpcodeSize size, typename Functor>
30114 void setIndex(VirtualRegister value, Functor func)
30115 {
30116 if (!Fits<VirtualRegister, size>::check(value))
30117 value = func();
30118 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
30119 *stream = Fits<VirtualRegister, size>::convert(value);
30120 }
30121
30122 VirtualRegister m_dst;
30123 VirtualRegister m_enumerator;
30124 VirtualRegister m_index;
30125};
30126
30127struct OpToIndexString : public Instruction {
30128 static constexpr OpcodeID opcodeID = op_to_index_string;
30129
30130 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
30131 {
30132 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, index);
30133 }
30134
30135 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
30136 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
30137 {
30138 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, index);
30139 if (shouldAssert == Assert)
30140 ASSERT(didEmit);
30141 return didEmit;
30142 }
30143
30144 template<OpcodeSize size>
30145 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
30146 {
30147
30148 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
30149 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, index))
30150 return;
30151 }
30152 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
30153 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, index))
30154 return;
30155 }
30156 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, index);
30157 }
30158
30159private:
30160 template<OpcodeSize size>
30161 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& index)
30162 {
30163 UNUSED_PARAM(gen);
30164#if OS(WINDOWS) && ENABLE(C_LOOP)
30165 // FIXME: Disable wide16 optimization for Windows CLoop
30166 // https://bugs.webkit.org/show_bug.cgi?id=198283
30167 if (size == OpcodeSize::Wide16)
30168 return false;
30169#endif
30170 return Fits<OpcodeID, size>::check(opcodeID)
30171 && Fits<VirtualRegister, size>::check(dst)
30172 && Fits<VirtualRegister, size>::check(index)
30173 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
30174 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
30175 }
30176
30177 template<OpcodeSize size, bool recordOpcode>
30178 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
30179 {
30180 if (size == OpcodeSize::Wide16)
30181 gen->alignWideOpcode16();
30182 else if (size == OpcodeSize::Wide32)
30183 gen->alignWideOpcode32();
30184 if (checkImpl<size>(gen, dst, index)) {
30185 if (recordOpcode)
30186 gen->recordOpcode(opcodeID);
30187 if (size == OpcodeSize::Wide16)
30188 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
30189 else if (size == OpcodeSize::Wide32)
30190 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
30191 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
30192 gen->write(Fits<VirtualRegister, size>::convert(dst));
30193 gen->write(Fits<VirtualRegister, size>::convert(index));
30194 return true;
30195 }
30196 return false;
30197 }
30198
30199public:
30200 template<typename Block>
30201 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
30202 {
30203 dumper->printLocationAndOp(__location, &"**to_index_string"[2 - __sizeShiftAmount]);
30204 dumper->dumpOperand(m_dst, true);
30205 dumper->dumpOperand(m_index, false);
30206 }
30207
30208 OpToIndexString(const uint8_t* stream)
30209 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
30210 , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
30211 {
30212 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30213 }
30214
30215 OpToIndexString(const uint16_t* stream)
30216 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
30217 , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
30218 {
30219 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30220 }
30221
30222
30223 OpToIndexString(const uint32_t* stream)
30224 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
30225 , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
30226 {
30227 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30228 }
30229
30230 static OpToIndexString decode(const uint8_t* stream)
30231 {
30232 if (*stream == op_wide32)
30233 return { bitwise_cast<const uint32_t*>(stream + 1) };
30234 if (*stream == op_wide16)
30235 return { bitwise_cast<const uint16_t*>(stream + 1) };
30236 return { stream };
30237 }
30238
30239 template<typename Functor>
30240 void setDst(VirtualRegister value, Functor func)
30241 {
30242 if (isWide32())
30243 setDst<OpcodeSize::Wide32>(value, func);
30244 else if (isWide16())
30245 setDst<OpcodeSize::Wide16>(value, func);
30246 else
30247 setDst<OpcodeSize::Narrow>(value, func);
30248 }
30249
30250 template <OpcodeSize size, typename Functor>
30251 void setDst(VirtualRegister value, Functor func)
30252 {
30253 if (!Fits<VirtualRegister, size>::check(value))
30254 value = func();
30255 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
30256 *stream = Fits<VirtualRegister, size>::convert(value);
30257 }
30258
30259 template<typename Functor>
30260 void setIndex(VirtualRegister value, Functor func)
30261 {
30262 if (isWide32())
30263 setIndex<OpcodeSize::Wide32>(value, func);
30264 else if (isWide16())
30265 setIndex<OpcodeSize::Wide16>(value, func);
30266 else
30267 setIndex<OpcodeSize::Narrow>(value, func);
30268 }
30269
30270 template <OpcodeSize size, typename Functor>
30271 void setIndex(VirtualRegister value, Functor func)
30272 {
30273 if (!Fits<VirtualRegister, size>::check(value))
30274 value = func();
30275 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
30276 *stream = Fits<VirtualRegister, size>::convert(value);
30277 }
30278
30279 VirtualRegister m_dst;
30280 VirtualRegister m_index;
30281};
30282
30283struct OpUnreachable : public Instruction {
30284 static constexpr OpcodeID opcodeID = op_unreachable;
30285
30286 static void emit(BytecodeGenerator* gen)
30287 {
30288 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
30289 }
30290
30291 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
30292 static bool emit(BytecodeGenerator* gen)
30293 {
30294 bool didEmit = emitImpl<size, recordOpcode>(gen);
30295 if (shouldAssert == Assert)
30296 ASSERT(didEmit);
30297 return didEmit;
30298 }
30299
30300 template<OpcodeSize size>
30301 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
30302 {
30303
30304 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
30305 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
30306 return;
30307 }
30308 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
30309 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
30310 return;
30311 }
30312 emit<OpcodeSize::Wide32, Assert, true>(gen);
30313 }
30314
30315private:
30316 template<OpcodeSize size>
30317 static bool checkImpl(BytecodeGenerator* gen)
30318 {
30319 UNUSED_PARAM(gen);
30320#if OS(WINDOWS) && ENABLE(C_LOOP)
30321 // FIXME: Disable wide16 optimization for Windows CLoop
30322 // https://bugs.webkit.org/show_bug.cgi?id=198283
30323 if (size == OpcodeSize::Wide16)
30324 return false;
30325#endif
30326 return Fits<OpcodeID, size>::check(opcodeID)
30327 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
30328 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
30329 }
30330
30331 template<OpcodeSize size, bool recordOpcode>
30332 static bool emitImpl(BytecodeGenerator* gen)
30333 {
30334 if (size == OpcodeSize::Wide16)
30335 gen->alignWideOpcode16();
30336 else if (size == OpcodeSize::Wide32)
30337 gen->alignWideOpcode32();
30338 if (checkImpl<size>(gen)) {
30339 if (recordOpcode)
30340 gen->recordOpcode(opcodeID);
30341 if (size == OpcodeSize::Wide16)
30342 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
30343 else if (size == OpcodeSize::Wide32)
30344 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
30345 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
30346 return true;
30347 }
30348 return false;
30349 }
30350
30351public:
30352 template<typename Block>
30353 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
30354 {
30355 dumper->printLocationAndOp(__location, &"**unreachable"[2 - __sizeShiftAmount]);
30356
30357 }
30358
30359 OpUnreachable(const uint8_t* stream)
30360
30361 {
30362 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30363 }
30364
30365 OpUnreachable(const uint16_t* stream)
30366
30367 {
30368 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30369 }
30370
30371
30372 OpUnreachable(const uint32_t* stream)
30373
30374 {
30375 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30376 }
30377
30378 static OpUnreachable decode(const uint8_t* stream)
30379 {
30380 if (*stream == op_wide32)
30381 return { bitwise_cast<const uint32_t*>(stream + 1) };
30382 if (*stream == op_wide16)
30383 return { bitwise_cast<const uint16_t*>(stream + 1) };
30384 return { stream };
30385 }
30386
30387
30388
30389};
30390
30391struct OpCreateRest : public Instruction {
30392 static constexpr OpcodeID opcodeID = op_create_rest;
30393
30394 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
30395 {
30396 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, arraySize, numParametersToSkip);
30397 }
30398
30399 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
30400 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
30401 {
30402 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, arraySize, numParametersToSkip);
30403 if (shouldAssert == Assert)
30404 ASSERT(didEmit);
30405 return didEmit;
30406 }
30407
30408 template<OpcodeSize size>
30409 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
30410 {
30411
30412 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
30413 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, arraySize, numParametersToSkip))
30414 return;
30415 }
30416 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
30417 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, arraySize, numParametersToSkip))
30418 return;
30419 }
30420 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, arraySize, numParametersToSkip);
30421 }
30422
30423private:
30424 template<OpcodeSize size>
30425 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& arraySize, unsigned& numParametersToSkip)
30426 {
30427 UNUSED_PARAM(gen);
30428#if OS(WINDOWS) && ENABLE(C_LOOP)
30429 // FIXME: Disable wide16 optimization for Windows CLoop
30430 // https://bugs.webkit.org/show_bug.cgi?id=198283
30431 if (size == OpcodeSize::Wide16)
30432 return false;
30433#endif
30434 return Fits<OpcodeID, size>::check(opcodeID)
30435 && Fits<VirtualRegister, size>::check(dst)
30436 && Fits<VirtualRegister, size>::check(arraySize)
30437 && Fits<unsigned, size>::check(numParametersToSkip)
30438 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
30439 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
30440 }
30441
30442 template<OpcodeSize size, bool recordOpcode>
30443 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
30444 {
30445 if (size == OpcodeSize::Wide16)
30446 gen->alignWideOpcode16();
30447 else if (size == OpcodeSize::Wide32)
30448 gen->alignWideOpcode32();
30449 if (checkImpl<size>(gen, dst, arraySize, numParametersToSkip)) {
30450 if (recordOpcode)
30451 gen->recordOpcode(opcodeID);
30452 if (size == OpcodeSize::Wide16)
30453 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
30454 else if (size == OpcodeSize::Wide32)
30455 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
30456 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
30457 gen->write(Fits<VirtualRegister, size>::convert(dst));
30458 gen->write(Fits<VirtualRegister, size>::convert(arraySize));
30459 gen->write(Fits<unsigned, size>::convert(numParametersToSkip));
30460 return true;
30461 }
30462 return false;
30463 }
30464
30465public:
30466 template<typename Block>
30467 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
30468 {
30469 dumper->printLocationAndOp(__location, &"**create_rest"[2 - __sizeShiftAmount]);
30470 dumper->dumpOperand(m_dst, true);
30471 dumper->dumpOperand(m_arraySize, false);
30472 dumper->dumpOperand(m_numParametersToSkip, false);
30473 }
30474
30475 OpCreateRest(const uint8_t* stream)
30476 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
30477 , m_arraySize(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
30478 , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
30479 {
30480 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30481 }
30482
30483 OpCreateRest(const uint16_t* stream)
30484 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
30485 , m_arraySize(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
30486 , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
30487 {
30488 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30489 }
30490
30491
30492 OpCreateRest(const uint32_t* stream)
30493 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
30494 , m_arraySize(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
30495 , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
30496 {
30497 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30498 }
30499
30500 static OpCreateRest decode(const uint8_t* stream)
30501 {
30502 if (*stream == op_wide32)
30503 return { bitwise_cast<const uint32_t*>(stream + 1) };
30504 if (*stream == op_wide16)
30505 return { bitwise_cast<const uint16_t*>(stream + 1) };
30506 return { stream };
30507 }
30508
30509 template<typename Functor>
30510 void setDst(VirtualRegister value, Functor func)
30511 {
30512 if (isWide32())
30513 setDst<OpcodeSize::Wide32>(value, func);
30514 else if (isWide16())
30515 setDst<OpcodeSize::Wide16>(value, func);
30516 else
30517 setDst<OpcodeSize::Narrow>(value, func);
30518 }
30519
30520 template <OpcodeSize size, typename Functor>
30521 void setDst(VirtualRegister value, Functor func)
30522 {
30523 if (!Fits<VirtualRegister, size>::check(value))
30524 value = func();
30525 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
30526 *stream = Fits<VirtualRegister, size>::convert(value);
30527 }
30528
30529 template<typename Functor>
30530 void setArraySize(VirtualRegister value, Functor func)
30531 {
30532 if (isWide32())
30533 setArraySize<OpcodeSize::Wide32>(value, func);
30534 else if (isWide16())
30535 setArraySize<OpcodeSize::Wide16>(value, func);
30536 else
30537 setArraySize<OpcodeSize::Narrow>(value, func);
30538 }
30539
30540 template <OpcodeSize size, typename Functor>
30541 void setArraySize(VirtualRegister value, Functor func)
30542 {
30543 if (!Fits<VirtualRegister, size>::check(value))
30544 value = func();
30545 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
30546 *stream = Fits<VirtualRegister, size>::convert(value);
30547 }
30548
30549 template<typename Functor>
30550 void setNumParametersToSkip(unsigned value, Functor func)
30551 {
30552 if (isWide32())
30553 setNumParametersToSkip<OpcodeSize::Wide32>(value, func);
30554 else if (isWide16())
30555 setNumParametersToSkip<OpcodeSize::Wide16>(value, func);
30556 else
30557 setNumParametersToSkip<OpcodeSize::Narrow>(value, func);
30558 }
30559
30560 template <OpcodeSize size, typename Functor>
30561 void setNumParametersToSkip(unsigned value, Functor func)
30562 {
30563 if (!Fits<unsigned, size>::check(value))
30564 value = func();
30565 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
30566 *stream = Fits<unsigned, size>::convert(value);
30567 }
30568
30569 VirtualRegister m_dst;
30570 VirtualRegister m_arraySize;
30571 unsigned m_numParametersToSkip;
30572};
30573
30574struct OpGetRestLength : public Instruction {
30575 static constexpr OpcodeID opcodeID = op_get_rest_length;
30576
30577 static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
30578 {
30579 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, numParametersToSkip);
30580 }
30581
30582 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
30583 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
30584 {
30585 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, numParametersToSkip);
30586 if (shouldAssert == Assert)
30587 ASSERT(didEmit);
30588 return didEmit;
30589 }
30590
30591 template<OpcodeSize size>
30592 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
30593 {
30594
30595 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
30596 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, numParametersToSkip))
30597 return;
30598 }
30599 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
30600 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, numParametersToSkip))
30601 return;
30602 }
30603 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, numParametersToSkip);
30604 }
30605
30606private:
30607 template<OpcodeSize size>
30608 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& numParametersToSkip)
30609 {
30610 UNUSED_PARAM(gen);
30611#if OS(WINDOWS) && ENABLE(C_LOOP)
30612 // FIXME: Disable wide16 optimization for Windows CLoop
30613 // https://bugs.webkit.org/show_bug.cgi?id=198283
30614 if (size == OpcodeSize::Wide16)
30615 return false;
30616#endif
30617 return Fits<OpcodeID, size>::check(opcodeID)
30618 && Fits<VirtualRegister, size>::check(dst)
30619 && Fits<unsigned, size>::check(numParametersToSkip)
30620 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
30621 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
30622 }
30623
30624 template<OpcodeSize size, bool recordOpcode>
30625 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
30626 {
30627 if (size == OpcodeSize::Wide16)
30628 gen->alignWideOpcode16();
30629 else if (size == OpcodeSize::Wide32)
30630 gen->alignWideOpcode32();
30631 if (checkImpl<size>(gen, dst, numParametersToSkip)) {
30632 if (recordOpcode)
30633 gen->recordOpcode(opcodeID);
30634 if (size == OpcodeSize::Wide16)
30635 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
30636 else if (size == OpcodeSize::Wide32)
30637 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
30638 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
30639 gen->write(Fits<VirtualRegister, size>::convert(dst));
30640 gen->write(Fits<unsigned, size>::convert(numParametersToSkip));
30641 return true;
30642 }
30643 return false;
30644 }
30645
30646public:
30647 template<typename Block>
30648 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
30649 {
30650 dumper->printLocationAndOp(__location, &"**get_rest_length"[2 - __sizeShiftAmount]);
30651 dumper->dumpOperand(m_dst, true);
30652 dumper->dumpOperand(m_numParametersToSkip, false);
30653 }
30654
30655 OpGetRestLength(const uint8_t* stream)
30656 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
30657 , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
30658 {
30659 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30660 }
30661
30662 OpGetRestLength(const uint16_t* stream)
30663 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
30664 , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
30665 {
30666 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30667 }
30668
30669
30670 OpGetRestLength(const uint32_t* stream)
30671 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
30672 , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
30673 {
30674 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30675 }
30676
30677 static OpGetRestLength decode(const uint8_t* stream)
30678 {
30679 if (*stream == op_wide32)
30680 return { bitwise_cast<const uint32_t*>(stream + 1) };
30681 if (*stream == op_wide16)
30682 return { bitwise_cast<const uint16_t*>(stream + 1) };
30683 return { stream };
30684 }
30685
30686 template<typename Functor>
30687 void setDst(VirtualRegister value, Functor func)
30688 {
30689 if (isWide32())
30690 setDst<OpcodeSize::Wide32>(value, func);
30691 else if (isWide16())
30692 setDst<OpcodeSize::Wide16>(value, func);
30693 else
30694 setDst<OpcodeSize::Narrow>(value, func);
30695 }
30696
30697 template <OpcodeSize size, typename Functor>
30698 void setDst(VirtualRegister value, Functor func)
30699 {
30700 if (!Fits<VirtualRegister, size>::check(value))
30701 value = func();
30702 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
30703 *stream = Fits<VirtualRegister, size>::convert(value);
30704 }
30705
30706 template<typename Functor>
30707 void setNumParametersToSkip(unsigned value, Functor func)
30708 {
30709 if (isWide32())
30710 setNumParametersToSkip<OpcodeSize::Wide32>(value, func);
30711 else if (isWide16())
30712 setNumParametersToSkip<OpcodeSize::Wide16>(value, func);
30713 else
30714 setNumParametersToSkip<OpcodeSize::Narrow>(value, func);
30715 }
30716
30717 template <OpcodeSize size, typename Functor>
30718 void setNumParametersToSkip(unsigned value, Functor func)
30719 {
30720 if (!Fits<unsigned, size>::check(value))
30721 value = func();
30722 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
30723 *stream = Fits<unsigned, size>::convert(value);
30724 }
30725
30726 VirtualRegister m_dst;
30727 unsigned m_numParametersToSkip;
30728};
30729
30730struct OpYield : public Instruction {
30731 static constexpr OpcodeID opcodeID = op_yield;
30732
30733 static void emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
30734 {
30735 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, generator, yieldPoint, argument);
30736 }
30737
30738 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
30739 static bool emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
30740 {
30741 bool didEmit = emitImpl<size, recordOpcode>(gen, generator, yieldPoint, argument);
30742 if (shouldAssert == Assert)
30743 ASSERT(didEmit);
30744 return didEmit;
30745 }
30746
30747 template<OpcodeSize size>
30748 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
30749 {
30750
30751 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
30752 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, generator, yieldPoint, argument))
30753 return;
30754 }
30755 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
30756 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, generator, yieldPoint, argument))
30757 return;
30758 }
30759 emit<OpcodeSize::Wide32, Assert, true>(gen, generator, yieldPoint, argument);
30760 }
30761
30762private:
30763 template<OpcodeSize size>
30764 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& generator, unsigned& yieldPoint, VirtualRegister& argument)
30765 {
30766 UNUSED_PARAM(gen);
30767#if OS(WINDOWS) && ENABLE(C_LOOP)
30768 // FIXME: Disable wide16 optimization for Windows CLoop
30769 // https://bugs.webkit.org/show_bug.cgi?id=198283
30770 if (size == OpcodeSize::Wide16)
30771 return false;
30772#endif
30773 return Fits<OpcodeID, size>::check(opcodeID)
30774 && Fits<VirtualRegister, size>::check(generator)
30775 && Fits<unsigned, size>::check(yieldPoint)
30776 && Fits<VirtualRegister, size>::check(argument)
30777 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
30778 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
30779 }
30780
30781 template<OpcodeSize size, bool recordOpcode>
30782 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
30783 {
30784 if (size == OpcodeSize::Wide16)
30785 gen->alignWideOpcode16();
30786 else if (size == OpcodeSize::Wide32)
30787 gen->alignWideOpcode32();
30788 if (checkImpl<size>(gen, generator, yieldPoint, argument)) {
30789 if (recordOpcode)
30790 gen->recordOpcode(opcodeID);
30791 if (size == OpcodeSize::Wide16)
30792 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
30793 else if (size == OpcodeSize::Wide32)
30794 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
30795 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
30796 gen->write(Fits<VirtualRegister, size>::convert(generator));
30797 gen->write(Fits<unsigned, size>::convert(yieldPoint));
30798 gen->write(Fits<VirtualRegister, size>::convert(argument));
30799 return true;
30800 }
30801 return false;
30802 }
30803
30804public:
30805 template<typename Block>
30806 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
30807 {
30808 dumper->printLocationAndOp(__location, &"**yield"[2 - __sizeShiftAmount]);
30809 dumper->dumpOperand(m_generator, true);
30810 dumper->dumpOperand(m_yieldPoint, false);
30811 dumper->dumpOperand(m_argument, false);
30812 }
30813
30814 OpYield(const uint8_t* stream)
30815 : m_generator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
30816 , m_yieldPoint(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
30817 , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
30818 {
30819 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30820 }
30821
30822 OpYield(const uint16_t* stream)
30823 : m_generator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
30824 , m_yieldPoint(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
30825 , m_argument(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
30826 {
30827 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30828 }
30829
30830
30831 OpYield(const uint32_t* stream)
30832 : m_generator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
30833 , m_yieldPoint(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
30834 , m_argument(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
30835 {
30836 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30837 }
30838
30839 static OpYield decode(const uint8_t* stream)
30840 {
30841 if (*stream == op_wide32)
30842 return { bitwise_cast<const uint32_t*>(stream + 1) };
30843 if (*stream == op_wide16)
30844 return { bitwise_cast<const uint16_t*>(stream + 1) };
30845 return { stream };
30846 }
30847
30848 template<typename Functor>
30849 void setGenerator(VirtualRegister value, Functor func)
30850 {
30851 if (isWide32())
30852 setGenerator<OpcodeSize::Wide32>(value, func);
30853 else if (isWide16())
30854 setGenerator<OpcodeSize::Wide16>(value, func);
30855 else
30856 setGenerator<OpcodeSize::Narrow>(value, func);
30857 }
30858
30859 template <OpcodeSize size, typename Functor>
30860 void setGenerator(VirtualRegister value, Functor func)
30861 {
30862 if (!Fits<VirtualRegister, size>::check(value))
30863 value = func();
30864 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
30865 *stream = Fits<VirtualRegister, size>::convert(value);
30866 }
30867
30868 template<typename Functor>
30869 void setYieldPoint(unsigned value, Functor func)
30870 {
30871 if (isWide32())
30872 setYieldPoint<OpcodeSize::Wide32>(value, func);
30873 else if (isWide16())
30874 setYieldPoint<OpcodeSize::Wide16>(value, func);
30875 else
30876 setYieldPoint<OpcodeSize::Narrow>(value, func);
30877 }
30878
30879 template <OpcodeSize size, typename Functor>
30880 void setYieldPoint(unsigned value, Functor func)
30881 {
30882 if (!Fits<unsigned, size>::check(value))
30883 value = func();
30884 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
30885 *stream = Fits<unsigned, size>::convert(value);
30886 }
30887
30888 template<typename Functor>
30889 void setArgument(VirtualRegister value, Functor func)
30890 {
30891 if (isWide32())
30892 setArgument<OpcodeSize::Wide32>(value, func);
30893 else if (isWide16())
30894 setArgument<OpcodeSize::Wide16>(value, func);
30895 else
30896 setArgument<OpcodeSize::Narrow>(value, func);
30897 }
30898
30899 template <OpcodeSize size, typename Functor>
30900 void setArgument(VirtualRegister value, Functor func)
30901 {
30902 if (!Fits<VirtualRegister, size>::check(value))
30903 value = func();
30904 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
30905 *stream = Fits<VirtualRegister, size>::convert(value);
30906 }
30907
30908 VirtualRegister m_generator;
30909 unsigned m_yieldPoint;
30910 VirtualRegister m_argument;
30911};
30912
30913struct OpCheckTraps : public Instruction {
30914 static constexpr OpcodeID opcodeID = op_check_traps;
30915
30916 static void emit(BytecodeGenerator* gen)
30917 {
30918 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
30919 }
30920
30921 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
30922 static bool emit(BytecodeGenerator* gen)
30923 {
30924 bool didEmit = emitImpl<size, recordOpcode>(gen);
30925 if (shouldAssert == Assert)
30926 ASSERT(didEmit);
30927 return didEmit;
30928 }
30929
30930 template<OpcodeSize size>
30931 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
30932 {
30933
30934 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
30935 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
30936 return;
30937 }
30938 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
30939 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
30940 return;
30941 }
30942 emit<OpcodeSize::Wide32, Assert, true>(gen);
30943 }
30944
30945private:
30946 template<OpcodeSize size>
30947 static bool checkImpl(BytecodeGenerator* gen)
30948 {
30949 UNUSED_PARAM(gen);
30950#if OS(WINDOWS) && ENABLE(C_LOOP)
30951 // FIXME: Disable wide16 optimization for Windows CLoop
30952 // https://bugs.webkit.org/show_bug.cgi?id=198283
30953 if (size == OpcodeSize::Wide16)
30954 return false;
30955#endif
30956 return Fits<OpcodeID, size>::check(opcodeID)
30957 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
30958 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
30959 }
30960
30961 template<OpcodeSize size, bool recordOpcode>
30962 static bool emitImpl(BytecodeGenerator* gen)
30963 {
30964 if (size == OpcodeSize::Wide16)
30965 gen->alignWideOpcode16();
30966 else if (size == OpcodeSize::Wide32)
30967 gen->alignWideOpcode32();
30968 if (checkImpl<size>(gen)) {
30969 if (recordOpcode)
30970 gen->recordOpcode(opcodeID);
30971 if (size == OpcodeSize::Wide16)
30972 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
30973 else if (size == OpcodeSize::Wide32)
30974 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
30975 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
30976 return true;
30977 }
30978 return false;
30979 }
30980
30981public:
30982 template<typename Block>
30983 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
30984 {
30985 dumper->printLocationAndOp(__location, &"**check_traps"[2 - __sizeShiftAmount]);
30986
30987 }
30988
30989 OpCheckTraps(const uint8_t* stream)
30990
30991 {
30992 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30993 }
30994
30995 OpCheckTraps(const uint16_t* stream)
30996
30997 {
30998 ASSERT_UNUSED(stream, stream[0] == opcodeID);
30999 }
31000
31001
31002 OpCheckTraps(const uint32_t* stream)
31003
31004 {
31005 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31006 }
31007
31008 static OpCheckTraps decode(const uint8_t* stream)
31009 {
31010 if (*stream == op_wide32)
31011 return { bitwise_cast<const uint32_t*>(stream + 1) };
31012 if (*stream == op_wide16)
31013 return { bitwise_cast<const uint16_t*>(stream + 1) };
31014 return { stream };
31015 }
31016
31017
31018
31019};
31020
31021struct OpLogShadowChickenPrologue : public Instruction {
31022 static constexpr OpcodeID opcodeID = op_log_shadow_chicken_prologue;
31023
31024 static void emit(BytecodeGenerator* gen, VirtualRegister scope)
31025 {
31026 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, scope);
31027 }
31028
31029 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
31030 static bool emit(BytecodeGenerator* gen, VirtualRegister scope)
31031 {
31032 bool didEmit = emitImpl<size, recordOpcode>(gen, scope);
31033 if (shouldAssert == Assert)
31034 ASSERT(didEmit);
31035 return didEmit;
31036 }
31037
31038 template<OpcodeSize size>
31039 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister scope)
31040 {
31041
31042 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
31043 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, scope))
31044 return;
31045 }
31046 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
31047 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, scope))
31048 return;
31049 }
31050 emit<OpcodeSize::Wide32, Assert, true>(gen, scope);
31051 }
31052
31053private:
31054 template<OpcodeSize size>
31055 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& scope)
31056 {
31057 UNUSED_PARAM(gen);
31058#if OS(WINDOWS) && ENABLE(C_LOOP)
31059 // FIXME: Disable wide16 optimization for Windows CLoop
31060 // https://bugs.webkit.org/show_bug.cgi?id=198283
31061 if (size == OpcodeSize::Wide16)
31062 return false;
31063#endif
31064 return Fits<OpcodeID, size>::check(opcodeID)
31065 && Fits<VirtualRegister, size>::check(scope)
31066 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
31067 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
31068 }
31069
31070 template<OpcodeSize size, bool recordOpcode>
31071 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister scope)
31072 {
31073 if (size == OpcodeSize::Wide16)
31074 gen->alignWideOpcode16();
31075 else if (size == OpcodeSize::Wide32)
31076 gen->alignWideOpcode32();
31077 if (checkImpl<size>(gen, scope)) {
31078 if (recordOpcode)
31079 gen->recordOpcode(opcodeID);
31080 if (size == OpcodeSize::Wide16)
31081 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
31082 else if (size == OpcodeSize::Wide32)
31083 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
31084 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
31085 gen->write(Fits<VirtualRegister, size>::convert(scope));
31086 return true;
31087 }
31088 return false;
31089 }
31090
31091public:
31092 template<typename Block>
31093 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
31094 {
31095 dumper->printLocationAndOp(__location, &"**log_shadow_chicken_prologue"[2 - __sizeShiftAmount]);
31096 dumper->dumpOperand(m_scope, true);
31097 }
31098
31099 OpLogShadowChickenPrologue(const uint8_t* stream)
31100 : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
31101 {
31102 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31103 }
31104
31105 OpLogShadowChickenPrologue(const uint16_t* stream)
31106 : m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
31107 {
31108 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31109 }
31110
31111
31112 OpLogShadowChickenPrologue(const uint32_t* stream)
31113 : m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
31114 {
31115 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31116 }
31117
31118 static OpLogShadowChickenPrologue decode(const uint8_t* stream)
31119 {
31120 if (*stream == op_wide32)
31121 return { bitwise_cast<const uint32_t*>(stream + 1) };
31122 if (*stream == op_wide16)
31123 return { bitwise_cast<const uint16_t*>(stream + 1) };
31124 return { stream };
31125 }
31126
31127 template<typename Functor>
31128 void setScope(VirtualRegister value, Functor func)
31129 {
31130 if (isWide32())
31131 setScope<OpcodeSize::Wide32>(value, func);
31132 else if (isWide16())
31133 setScope<OpcodeSize::Wide16>(value, func);
31134 else
31135 setScope<OpcodeSize::Narrow>(value, func);
31136 }
31137
31138 template <OpcodeSize size, typename Functor>
31139 void setScope(VirtualRegister value, Functor func)
31140 {
31141 if (!Fits<VirtualRegister, size>::check(value))
31142 value = func();
31143 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
31144 *stream = Fits<VirtualRegister, size>::convert(value);
31145 }
31146
31147 VirtualRegister m_scope;
31148};
31149
31150struct OpLogShadowChickenTail : public Instruction {
31151 static constexpr OpcodeID opcodeID = op_log_shadow_chicken_tail;
31152
31153 static void emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
31154 {
31155 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, thisValue, scope);
31156 }
31157
31158 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
31159 static bool emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
31160 {
31161 bool didEmit = emitImpl<size, recordOpcode>(gen, thisValue, scope);
31162 if (shouldAssert == Assert)
31163 ASSERT(didEmit);
31164 return didEmit;
31165 }
31166
31167 template<OpcodeSize size>
31168 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
31169 {
31170
31171 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
31172 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, thisValue, scope))
31173 return;
31174 }
31175 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
31176 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, thisValue, scope))
31177 return;
31178 }
31179 emit<OpcodeSize::Wide32, Assert, true>(gen, thisValue, scope);
31180 }
31181
31182private:
31183 template<OpcodeSize size>
31184 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& thisValue, VirtualRegister& scope)
31185 {
31186 UNUSED_PARAM(gen);
31187#if OS(WINDOWS) && ENABLE(C_LOOP)
31188 // FIXME: Disable wide16 optimization for Windows CLoop
31189 // https://bugs.webkit.org/show_bug.cgi?id=198283
31190 if (size == OpcodeSize::Wide16)
31191 return false;
31192#endif
31193 return Fits<OpcodeID, size>::check(opcodeID)
31194 && Fits<VirtualRegister, size>::check(thisValue)
31195 && Fits<VirtualRegister, size>::check(scope)
31196 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
31197 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
31198 }
31199
31200 template<OpcodeSize size, bool recordOpcode>
31201 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
31202 {
31203 if (size == OpcodeSize::Wide16)
31204 gen->alignWideOpcode16();
31205 else if (size == OpcodeSize::Wide32)
31206 gen->alignWideOpcode32();
31207 if (checkImpl<size>(gen, thisValue, scope)) {
31208 if (recordOpcode)
31209 gen->recordOpcode(opcodeID);
31210 if (size == OpcodeSize::Wide16)
31211 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
31212 else if (size == OpcodeSize::Wide32)
31213 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
31214 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
31215 gen->write(Fits<VirtualRegister, size>::convert(thisValue));
31216 gen->write(Fits<VirtualRegister, size>::convert(scope));
31217 return true;
31218 }
31219 return false;
31220 }
31221
31222public:
31223 template<typename Block>
31224 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
31225 {
31226 dumper->printLocationAndOp(__location, &"**log_shadow_chicken_tail"[2 - __sizeShiftAmount]);
31227 dumper->dumpOperand(m_thisValue, true);
31228 dumper->dumpOperand(m_scope, false);
31229 }
31230
31231 OpLogShadowChickenTail(const uint8_t* stream)
31232 : m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
31233 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
31234 {
31235 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31236 }
31237
31238 OpLogShadowChickenTail(const uint16_t* stream)
31239 : m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
31240 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
31241 {
31242 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31243 }
31244
31245
31246 OpLogShadowChickenTail(const uint32_t* stream)
31247 : m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
31248 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
31249 {
31250 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31251 }
31252
31253 static OpLogShadowChickenTail decode(const uint8_t* stream)
31254 {
31255 if (*stream == op_wide32)
31256 return { bitwise_cast<const uint32_t*>(stream + 1) };
31257 if (*stream == op_wide16)
31258 return { bitwise_cast<const uint16_t*>(stream + 1) };
31259 return { stream };
31260 }
31261
31262 template<typename Functor>
31263 void setThisValue(VirtualRegister value, Functor func)
31264 {
31265 if (isWide32())
31266 setThisValue<OpcodeSize::Wide32>(value, func);
31267 else if (isWide16())
31268 setThisValue<OpcodeSize::Wide16>(value, func);
31269 else
31270 setThisValue<OpcodeSize::Narrow>(value, func);
31271 }
31272
31273 template <OpcodeSize size, typename Functor>
31274 void setThisValue(VirtualRegister value, Functor func)
31275 {
31276 if (!Fits<VirtualRegister, size>::check(value))
31277 value = func();
31278 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
31279 *stream = Fits<VirtualRegister, size>::convert(value);
31280 }
31281
31282 template<typename Functor>
31283 void setScope(VirtualRegister value, Functor func)
31284 {
31285 if (isWide32())
31286 setScope<OpcodeSize::Wide32>(value, func);
31287 else if (isWide16())
31288 setScope<OpcodeSize::Wide16>(value, func);
31289 else
31290 setScope<OpcodeSize::Narrow>(value, func);
31291 }
31292
31293 template <OpcodeSize size, typename Functor>
31294 void setScope(VirtualRegister value, Functor func)
31295 {
31296 if (!Fits<VirtualRegister, size>::check(value))
31297 value = func();
31298 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
31299 *stream = Fits<VirtualRegister, size>::convert(value);
31300 }
31301
31302 VirtualRegister m_thisValue;
31303 VirtualRegister m_scope;
31304};
31305
31306struct OpResolveScopeForHoistingFuncDeclInEval : public Instruction {
31307 static constexpr OpcodeID opcodeID = op_resolve_scope_for_hoisting_func_decl_in_eval;
31308
31309 static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
31310 {
31311 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, property);
31312 }
31313
31314 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
31315 static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
31316 {
31317 bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, property);
31318 if (shouldAssert == Assert)
31319 ASSERT(didEmit);
31320 return didEmit;
31321 }
31322
31323 template<OpcodeSize size>
31324 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
31325 {
31326
31327 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
31328 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope, property))
31329 return;
31330 }
31331 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
31332 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, property))
31333 return;
31334 }
31335 emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, property);
31336 }
31337
31338private:
31339 template<OpcodeSize size>
31340 static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& property)
31341 {
31342 UNUSED_PARAM(gen);
31343#if OS(WINDOWS) && ENABLE(C_LOOP)
31344 // FIXME: Disable wide16 optimization for Windows CLoop
31345 // https://bugs.webkit.org/show_bug.cgi?id=198283
31346 if (size == OpcodeSize::Wide16)
31347 return false;
31348#endif
31349 return Fits<OpcodeID, size>::check(opcodeID)
31350 && Fits<VirtualRegister, size>::check(dst)
31351 && Fits<VirtualRegister, size>::check(scope)
31352 && Fits<unsigned, size>::check(property)
31353 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
31354 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
31355 }
31356
31357 template<OpcodeSize size, bool recordOpcode>
31358 static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
31359 {
31360 if (size == OpcodeSize::Wide16)
31361 gen->alignWideOpcode16();
31362 else if (size == OpcodeSize::Wide32)
31363 gen->alignWideOpcode32();
31364 if (checkImpl<size>(gen, dst, scope, property)) {
31365 if (recordOpcode)
31366 gen->recordOpcode(opcodeID);
31367 if (size == OpcodeSize::Wide16)
31368 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
31369 else if (size == OpcodeSize::Wide32)
31370 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
31371 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
31372 gen->write(Fits<VirtualRegister, size>::convert(dst));
31373 gen->write(Fits<VirtualRegister, size>::convert(scope));
31374 gen->write(Fits<unsigned, size>::convert(property));
31375 return true;
31376 }
31377 return false;
31378 }
31379
31380public:
31381 template<typename Block>
31382 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
31383 {
31384 dumper->printLocationAndOp(__location, &"**resolve_scope_for_hoisting_func_decl_in_eval"[2 - __sizeShiftAmount]);
31385 dumper->dumpOperand(m_dst, true);
31386 dumper->dumpOperand(m_scope, false);
31387 dumper->dumpOperand(m_property, false);
31388 }
31389
31390 OpResolveScopeForHoistingFuncDeclInEval(const uint8_t* stream)
31391 : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
31392 , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
31393 , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
31394 {
31395 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31396 }
31397
31398 OpResolveScopeForHoistingFuncDeclInEval(const uint16_t* stream)
31399 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
31400 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
31401 , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
31402 {
31403 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31404 }
31405
31406
31407 OpResolveScopeForHoistingFuncDeclInEval(const uint32_t* stream)
31408 : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
31409 , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
31410 , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
31411 {
31412 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31413 }
31414
31415 static OpResolveScopeForHoistingFuncDeclInEval decode(const uint8_t* stream)
31416 {
31417 if (*stream == op_wide32)
31418 return { bitwise_cast<const uint32_t*>(stream + 1) };
31419 if (*stream == op_wide16)
31420 return { bitwise_cast<const uint16_t*>(stream + 1) };
31421 return { stream };
31422 }
31423
31424 template<typename Functor>
31425 void setDst(VirtualRegister value, Functor func)
31426 {
31427 if (isWide32())
31428 setDst<OpcodeSize::Wide32>(value, func);
31429 else if (isWide16())
31430 setDst<OpcodeSize::Wide16>(value, func);
31431 else
31432 setDst<OpcodeSize::Narrow>(value, func);
31433 }
31434
31435 template <OpcodeSize size, typename Functor>
31436 void setDst(VirtualRegister value, Functor func)
31437 {
31438 if (!Fits<VirtualRegister, size>::check(value))
31439 value = func();
31440 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value);
31441 *stream = Fits<VirtualRegister, size>::convert(value);
31442 }
31443
31444 template<typename Functor>
31445 void setScope(VirtualRegister value, Functor func)
31446 {
31447 if (isWide32())
31448 setScope<OpcodeSize::Wide32>(value, func);
31449 else if (isWide16())
31450 setScope<OpcodeSize::Wide16>(value, func);
31451 else
31452 setScope<OpcodeSize::Narrow>(value, func);
31453 }
31454
31455 template <OpcodeSize size, typename Functor>
31456 void setScope(VirtualRegister value, Functor func)
31457 {
31458 if (!Fits<VirtualRegister, size>::check(value))
31459 value = func();
31460 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value);
31461 *stream = Fits<VirtualRegister, size>::convert(value);
31462 }
31463
31464 template<typename Functor>
31465 void setProperty(unsigned value, Functor func)
31466 {
31467 if (isWide32())
31468 setProperty<OpcodeSize::Wide32>(value, func);
31469 else if (isWide16())
31470 setProperty<OpcodeSize::Wide16>(value, func);
31471 else
31472 setProperty<OpcodeSize::Narrow>(value, func);
31473 }
31474
31475 template <OpcodeSize size, typename Functor>
31476 void setProperty(unsigned value, Functor func)
31477 {
31478 if (!Fits<unsigned, size>::check(value))
31479 value = func();
31480 auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value);
31481 *stream = Fits<unsigned, size>::convert(value);
31482 }
31483
31484 VirtualRegister m_dst;
31485 VirtualRegister m_scope;
31486 unsigned m_property;
31487};
31488
31489struct OpNop : public Instruction {
31490 static constexpr OpcodeID opcodeID = op_nop;
31491
31492 static void emit(BytecodeGenerator* gen)
31493 {
31494 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
31495 }
31496
31497 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
31498 static bool emit(BytecodeGenerator* gen)
31499 {
31500 bool didEmit = emitImpl<size, recordOpcode>(gen);
31501 if (shouldAssert == Assert)
31502 ASSERT(didEmit);
31503 return didEmit;
31504 }
31505
31506 template<OpcodeSize size>
31507 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
31508 {
31509
31510 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
31511 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
31512 return;
31513 }
31514 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
31515 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
31516 return;
31517 }
31518 emit<OpcodeSize::Wide32, Assert, true>(gen);
31519 }
31520
31521private:
31522 template<OpcodeSize size>
31523 static bool checkImpl(BytecodeGenerator* gen)
31524 {
31525 UNUSED_PARAM(gen);
31526#if OS(WINDOWS) && ENABLE(C_LOOP)
31527 // FIXME: Disable wide16 optimization for Windows CLoop
31528 // https://bugs.webkit.org/show_bug.cgi?id=198283
31529 if (size == OpcodeSize::Wide16)
31530 return false;
31531#endif
31532 return Fits<OpcodeID, size>::check(opcodeID)
31533 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
31534 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
31535 }
31536
31537 template<OpcodeSize size, bool recordOpcode>
31538 static bool emitImpl(BytecodeGenerator* gen)
31539 {
31540 if (size == OpcodeSize::Wide16)
31541 gen->alignWideOpcode16();
31542 else if (size == OpcodeSize::Wide32)
31543 gen->alignWideOpcode32();
31544 if (checkImpl<size>(gen)) {
31545 if (recordOpcode)
31546 gen->recordOpcode(opcodeID);
31547 if (size == OpcodeSize::Wide16)
31548 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
31549 else if (size == OpcodeSize::Wide32)
31550 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
31551 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
31552 return true;
31553 }
31554 return false;
31555 }
31556
31557public:
31558 template<typename Block>
31559 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
31560 {
31561 dumper->printLocationAndOp(__location, &"**nop"[2 - __sizeShiftAmount]);
31562
31563 }
31564
31565 OpNop(const uint8_t* stream)
31566
31567 {
31568 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31569 }
31570
31571 OpNop(const uint16_t* stream)
31572
31573 {
31574 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31575 }
31576
31577
31578 OpNop(const uint32_t* stream)
31579
31580 {
31581 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31582 }
31583
31584 static OpNop decode(const uint8_t* stream)
31585 {
31586 if (*stream == op_wide32)
31587 return { bitwise_cast<const uint32_t*>(stream + 1) };
31588 if (*stream == op_wide16)
31589 return { bitwise_cast<const uint16_t*>(stream + 1) };
31590 return { stream };
31591 }
31592
31593
31594
31595};
31596
31597struct OpSuperSamplerBegin : public Instruction {
31598 static constexpr OpcodeID opcodeID = op_super_sampler_begin;
31599
31600 static void emit(BytecodeGenerator* gen)
31601 {
31602 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
31603 }
31604
31605 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
31606 static bool emit(BytecodeGenerator* gen)
31607 {
31608 bool didEmit = emitImpl<size, recordOpcode>(gen);
31609 if (shouldAssert == Assert)
31610 ASSERT(didEmit);
31611 return didEmit;
31612 }
31613
31614 template<OpcodeSize size>
31615 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
31616 {
31617
31618 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
31619 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
31620 return;
31621 }
31622 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
31623 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
31624 return;
31625 }
31626 emit<OpcodeSize::Wide32, Assert, true>(gen);
31627 }
31628
31629private:
31630 template<OpcodeSize size>
31631 static bool checkImpl(BytecodeGenerator* gen)
31632 {
31633 UNUSED_PARAM(gen);
31634#if OS(WINDOWS) && ENABLE(C_LOOP)
31635 // FIXME: Disable wide16 optimization for Windows CLoop
31636 // https://bugs.webkit.org/show_bug.cgi?id=198283
31637 if (size == OpcodeSize::Wide16)
31638 return false;
31639#endif
31640 return Fits<OpcodeID, size>::check(opcodeID)
31641 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
31642 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
31643 }
31644
31645 template<OpcodeSize size, bool recordOpcode>
31646 static bool emitImpl(BytecodeGenerator* gen)
31647 {
31648 if (size == OpcodeSize::Wide16)
31649 gen->alignWideOpcode16();
31650 else if (size == OpcodeSize::Wide32)
31651 gen->alignWideOpcode32();
31652 if (checkImpl<size>(gen)) {
31653 if (recordOpcode)
31654 gen->recordOpcode(opcodeID);
31655 if (size == OpcodeSize::Wide16)
31656 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
31657 else if (size == OpcodeSize::Wide32)
31658 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
31659 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
31660 return true;
31661 }
31662 return false;
31663 }
31664
31665public:
31666 template<typename Block>
31667 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
31668 {
31669 dumper->printLocationAndOp(__location, &"**super_sampler_begin"[2 - __sizeShiftAmount]);
31670
31671 }
31672
31673 OpSuperSamplerBegin(const uint8_t* stream)
31674
31675 {
31676 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31677 }
31678
31679 OpSuperSamplerBegin(const uint16_t* stream)
31680
31681 {
31682 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31683 }
31684
31685
31686 OpSuperSamplerBegin(const uint32_t* stream)
31687
31688 {
31689 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31690 }
31691
31692 static OpSuperSamplerBegin decode(const uint8_t* stream)
31693 {
31694 if (*stream == op_wide32)
31695 return { bitwise_cast<const uint32_t*>(stream + 1) };
31696 if (*stream == op_wide16)
31697 return { bitwise_cast<const uint16_t*>(stream + 1) };
31698 return { stream };
31699 }
31700
31701
31702
31703};
31704
31705struct OpSuperSamplerEnd : public Instruction {
31706 static constexpr OpcodeID opcodeID = op_super_sampler_end;
31707
31708 static void emit(BytecodeGenerator* gen)
31709 {
31710 emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
31711 }
31712
31713 template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
31714 static bool emit(BytecodeGenerator* gen)
31715 {
31716 bool didEmit = emitImpl<size, recordOpcode>(gen);
31717 if (shouldAssert == Assert)
31718 ASSERT(didEmit);
31719 return didEmit;
31720 }
31721
31722 template<OpcodeSize size>
31723 static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
31724 {
31725
31726 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
31727 if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
31728 return;
31729 }
31730 if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
31731 if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
31732 return;
31733 }
31734 emit<OpcodeSize::Wide32, Assert, true>(gen);
31735 }
31736
31737private:
31738 template<OpcodeSize size>
31739 static bool checkImpl(BytecodeGenerator* gen)
31740 {
31741 UNUSED_PARAM(gen);
31742#if OS(WINDOWS) && ENABLE(C_LOOP)
31743 // FIXME: Disable wide16 optimization for Windows CLoop
31744 // https://bugs.webkit.org/show_bug.cgi?id=198283
31745 if (size == OpcodeSize::Wide16)
31746 return false;
31747#endif
31748 return Fits<OpcodeID, size>::check(opcodeID)
31749 && (size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
31750 && (size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
31751 }
31752
31753 template<OpcodeSize size, bool recordOpcode>
31754 static bool emitImpl(BytecodeGenerator* gen)
31755 {
31756 if (size == OpcodeSize::Wide16)
31757 gen->alignWideOpcode16();
31758 else if (size == OpcodeSize::Wide32)
31759 gen->alignWideOpcode32();
31760 if (checkImpl<size>(gen)) {
31761 if (recordOpcode)
31762 gen->recordOpcode(opcodeID);
31763 if (size == OpcodeSize::Wide16)
31764 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
31765 else if (size == OpcodeSize::Wide32)
31766 gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
31767 gen->write(Fits<OpcodeID, size>::convert(opcodeID));
31768 return true;
31769 }
31770 return false;
31771 }
31772
31773public:
31774 template<typename Block>
31775 void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
31776 {
31777 dumper->printLocationAndOp(__location, &"**super_sampler_end"[2 - __sizeShiftAmount]);
31778
31779 }
31780
31781 OpSuperSamplerEnd(const uint8_t* stream)
31782
31783 {
31784 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31785 }
31786
31787 OpSuperSamplerEnd(const uint16_t* stream)
31788
31789 {
31790 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31791 }
31792
31793
31794 OpSuperSamplerEnd(const uint32_t* stream)
31795
31796 {
31797 ASSERT_UNUSED(stream, stream[0] == opcodeID);
31798 }
31799
31800 static OpSuperSamplerEnd decode(const uint8_t* stream)
31801 {
31802 if (*stream == op_wide32)
31803 return { bitwise_cast<const uint32_t*>(stream + 1) };
31804 if (*stream == op_wide16)
31805 return { bitwise_cast<const uint16_t*>(stream + 1) };
31806 return { stream };
31807 }
31808
31809
31810
31811};
31812
31813template<typename Block>
31814static void dumpBytecode(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, const Instruction* __instruction)
31815{
31816 switch (__instruction->opcodeID()) {
31817 case op_create_this:
31818 __instruction->as<OpCreateThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
31819 break;
31820 case op_get_argument:
31821 __instruction->as<OpGetArgument>().dump(dumper, __location, __instruction->sizeShiftAmount());
31822 break;
31823 case op_to_this:
31824 __instruction->as<OpToThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
31825 break;
31826 case op_new_object:
31827 __instruction->as<OpNewObject>().dump(dumper, __location, __instruction->sizeShiftAmount());
31828 break;
31829 case op_new_array:
31830 __instruction->as<OpNewArray>().dump(dumper, __location, __instruction->sizeShiftAmount());
31831 break;
31832 case op_new_array_with_size:
31833 __instruction->as<OpNewArrayWithSize>().dump(dumper, __location, __instruction->sizeShiftAmount());
31834 break;
31835 case op_new_array_buffer:
31836 __instruction->as<OpNewArrayBuffer>().dump(dumper, __location, __instruction->sizeShiftAmount());
31837 break;
31838 case op_add:
31839 __instruction->as<OpAdd>().dump(dumper, __location, __instruction->sizeShiftAmount());
31840 break;
31841 case op_mul:
31842 __instruction->as<OpMul>().dump(dumper, __location, __instruction->sizeShiftAmount());
31843 break;
31844 case op_div:
31845 __instruction->as<OpDiv>().dump(dumper, __location, __instruction->sizeShiftAmount());
31846 break;
31847 case op_sub:
31848 __instruction->as<OpSub>().dump(dumper, __location, __instruction->sizeShiftAmount());
31849 break;
31850 case op_bitand:
31851 __instruction->as<OpBitand>().dump(dumper, __location, __instruction->sizeShiftAmount());
31852 break;
31853 case op_bitor:
31854 __instruction->as<OpBitor>().dump(dumper, __location, __instruction->sizeShiftAmount());
31855 break;
31856 case op_bitxor:
31857 __instruction->as<OpBitxor>().dump(dumper, __location, __instruction->sizeShiftAmount());
31858 break;
31859 case op_bitnot:
31860 __instruction->as<OpBitnot>().dump(dumper, __location, __instruction->sizeShiftAmount());
31861 break;
31862 case op_to_object:
31863 __instruction->as<OpToObject>().dump(dumper, __location, __instruction->sizeShiftAmount());
31864 break;
31865 case op_to_number:
31866 __instruction->as<OpToNumber>().dump(dumper, __location, __instruction->sizeShiftAmount());
31867 break;
31868 case op_negate:
31869 __instruction->as<OpNegate>().dump(dumper, __location, __instruction->sizeShiftAmount());
31870 break;
31871 case op_in_by_val:
31872 __instruction->as<OpInByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
31873 break;
31874 case op_get_by_id:
31875 __instruction->as<OpGetById>().dump(dumper, __location, __instruction->sizeShiftAmount());
31876 break;
31877 case op_get_by_id_with_this:
31878 __instruction->as<OpGetByIdWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
31879 break;
31880 case op_get_by_val_with_this:
31881 __instruction->as<OpGetByValWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
31882 break;
31883 case op_get_by_id_direct:
31884 __instruction->as<OpGetByIdDirect>().dump(dumper, __location, __instruction->sizeShiftAmount());
31885 break;
31886 case op_try_get_by_id:
31887 __instruction->as<OpTryGetById>().dump(dumper, __location, __instruction->sizeShiftAmount());
31888 break;
31889 case op_put_by_id:
31890 __instruction->as<OpPutById>().dump(dumper, __location, __instruction->sizeShiftAmount());
31891 break;
31892 case op_get_by_val:
31893 __instruction->as<OpGetByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
31894 break;
31895 case op_put_by_val:
31896 __instruction->as<OpPutByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
31897 break;
31898 case op_put_by_val_direct:
31899 __instruction->as<OpPutByValDirect>().dump(dumper, __location, __instruction->sizeShiftAmount());
31900 break;
31901 case op_jneq_ptr:
31902 __instruction->as<OpJneqPtr>().dump(dumper, __location, __instruction->sizeShiftAmount());
31903 break;
31904 case op_call:
31905 __instruction->as<OpCall>().dump(dumper, __location, __instruction->sizeShiftAmount());
31906 break;
31907 case op_tail_call:
31908 __instruction->as<OpTailCall>().dump(dumper, __location, __instruction->sizeShiftAmount());
31909 break;
31910 case op_call_eval:
31911 __instruction->as<OpCallEval>().dump(dumper, __location, __instruction->sizeShiftAmount());
31912 break;
31913 case op_call_varargs:
31914 __instruction->as<OpCallVarargs>().dump(dumper, __location, __instruction->sizeShiftAmount());
31915 break;
31916 case op_tail_call_varargs:
31917 __instruction->as<OpTailCallVarargs>().dump(dumper, __location, __instruction->sizeShiftAmount());
31918 break;
31919 case op_tail_call_forward_arguments:
31920 __instruction->as<OpTailCallForwardArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
31921 break;
31922 case op_construct:
31923 __instruction->as<OpConstruct>().dump(dumper, __location, __instruction->sizeShiftAmount());
31924 break;
31925 case op_construct_varargs:
31926 __instruction->as<OpConstructVarargs>().dump(dumper, __location, __instruction->sizeShiftAmount());
31927 break;
31928 case op_resolve_scope:
31929 __instruction->as<OpResolveScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
31930 break;
31931 case op_get_from_scope:
31932 __instruction->as<OpGetFromScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
31933 break;
31934 case op_put_to_scope:
31935 __instruction->as<OpPutToScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
31936 break;
31937 case op_get_from_arguments:
31938 __instruction->as<OpGetFromArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
31939 break;
31940 case op_catch:
31941 __instruction->as<OpCatch>().dump(dumper, __location, __instruction->sizeShiftAmount());
31942 break;
31943 case op_profile_type:
31944 __instruction->as<OpProfileType>().dump(dumper, __location, __instruction->sizeShiftAmount());
31945 break;
31946 case op_profile_control_flow:
31947 __instruction->as<OpProfileControlFlow>().dump(dumper, __location, __instruction->sizeShiftAmount());
31948 break;
31949 case op_has_indexed_property:
31950 __instruction->as<OpHasIndexedProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
31951 break;
31952 case op_get_direct_pname:
31953 __instruction->as<OpGetDirectPname>().dump(dumper, __location, __instruction->sizeShiftAmount());
31954 break;
31955 case op_wide16:
31956 __instruction->as<OpWide16>().dump(dumper, __location, __instruction->sizeShiftAmount());
31957 break;
31958 case op_wide32:
31959 __instruction->as<OpWide32>().dump(dumper, __location, __instruction->sizeShiftAmount());
31960 break;
31961 case op_enter:
31962 __instruction->as<OpEnter>().dump(dumper, __location, __instruction->sizeShiftAmount());
31963 break;
31964 case op_get_scope:
31965 __instruction->as<OpGetScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
31966 break;
31967 case op_create_direct_arguments:
31968 __instruction->as<OpCreateDirectArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
31969 break;
31970 case op_create_scoped_arguments:
31971 __instruction->as<OpCreateScopedArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
31972 break;
31973 case op_create_cloned_arguments:
31974 __instruction->as<OpCreateClonedArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
31975 break;
31976 case op_argument_count:
31977 __instruction->as<OpArgumentCount>().dump(dumper, __location, __instruction->sizeShiftAmount());
31978 break;
31979 case op_check_tdz:
31980 __instruction->as<OpCheckTdz>().dump(dumper, __location, __instruction->sizeShiftAmount());
31981 break;
31982 case op_new_array_with_spread:
31983 __instruction->as<OpNewArrayWithSpread>().dump(dumper, __location, __instruction->sizeShiftAmount());
31984 break;
31985 case op_spread:
31986 __instruction->as<OpSpread>().dump(dumper, __location, __instruction->sizeShiftAmount());
31987 break;
31988 case op_new_regexp:
31989 __instruction->as<OpNewRegexp>().dump(dumper, __location, __instruction->sizeShiftAmount());
31990 break;
31991 case op_mov:
31992 __instruction->as<OpMov>().dump(dumper, __location, __instruction->sizeShiftAmount());
31993 break;
31994 case op_eq:
31995 __instruction->as<OpEq>().dump(dumper, __location, __instruction->sizeShiftAmount());
31996 break;
31997 case op_neq:
31998 __instruction->as<OpNeq>().dump(dumper, __location, __instruction->sizeShiftAmount());
31999 break;
32000 case op_stricteq:
32001 __instruction->as<OpStricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32002 break;
32003 case op_nstricteq:
32004 __instruction->as<OpNstricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32005 break;
32006 case op_less:
32007 __instruction->as<OpLess>().dump(dumper, __location, __instruction->sizeShiftAmount());
32008 break;
32009 case op_lesseq:
32010 __instruction->as<OpLesseq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32011 break;
32012 case op_greater:
32013 __instruction->as<OpGreater>().dump(dumper, __location, __instruction->sizeShiftAmount());
32014 break;
32015 case op_greatereq:
32016 __instruction->as<OpGreatereq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32017 break;
32018 case op_below:
32019 __instruction->as<OpBelow>().dump(dumper, __location, __instruction->sizeShiftAmount());
32020 break;
32021 case op_beloweq:
32022 __instruction->as<OpBeloweq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32023 break;
32024 case op_mod:
32025 __instruction->as<OpMod>().dump(dumper, __location, __instruction->sizeShiftAmount());
32026 break;
32027 case op_pow:
32028 __instruction->as<OpPow>().dump(dumper, __location, __instruction->sizeShiftAmount());
32029 break;
32030 case op_lshift:
32031 __instruction->as<OpLshift>().dump(dumper, __location, __instruction->sizeShiftAmount());
32032 break;
32033 case op_rshift:
32034 __instruction->as<OpRshift>().dump(dumper, __location, __instruction->sizeShiftAmount());
32035 break;
32036 case op_urshift:
32037 __instruction->as<OpUrshift>().dump(dumper, __location, __instruction->sizeShiftAmount());
32038 break;
32039 case op_eq_null:
32040 __instruction->as<OpEqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
32041 break;
32042 case op_neq_null:
32043 __instruction->as<OpNeqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
32044 break;
32045 case op_to_string:
32046 __instruction->as<OpToString>().dump(dumper, __location, __instruction->sizeShiftAmount());
32047 break;
32048 case op_unsigned:
32049 __instruction->as<OpUnsigned>().dump(dumper, __location, __instruction->sizeShiftAmount());
32050 break;
32051 case op_is_empty:
32052 __instruction->as<OpIsEmpty>().dump(dumper, __location, __instruction->sizeShiftAmount());
32053 break;
32054 case op_is_undefined:
32055 __instruction->as<OpIsUndefined>().dump(dumper, __location, __instruction->sizeShiftAmount());
32056 break;
32057 case op_is_undefined_or_null:
32058 __instruction->as<OpIsUndefinedOrNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
32059 break;
32060 case op_is_boolean:
32061 __instruction->as<OpIsBoolean>().dump(dumper, __location, __instruction->sizeShiftAmount());
32062 break;
32063 case op_is_number:
32064 __instruction->as<OpIsNumber>().dump(dumper, __location, __instruction->sizeShiftAmount());
32065 break;
32066 case op_is_object:
32067 __instruction->as<OpIsObject>().dump(dumper, __location, __instruction->sizeShiftAmount());
32068 break;
32069 case op_is_object_or_null:
32070 __instruction->as<OpIsObjectOrNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
32071 break;
32072 case op_is_function:
32073 __instruction->as<OpIsFunction>().dump(dumper, __location, __instruction->sizeShiftAmount());
32074 break;
32075 case op_inc:
32076 __instruction->as<OpInc>().dump(dumper, __location, __instruction->sizeShiftAmount());
32077 break;
32078 case op_dec:
32079 __instruction->as<OpDec>().dump(dumper, __location, __instruction->sizeShiftAmount());
32080 break;
32081 case op_not:
32082 __instruction->as<OpNot>().dump(dumper, __location, __instruction->sizeShiftAmount());
32083 break;
32084 case op_identity_with_profile:
32085 __instruction->as<OpIdentityWithProfile>().dump(dumper, __location, __instruction->sizeShiftAmount());
32086 break;
32087 case op_overrides_has_instance:
32088 __instruction->as<OpOverridesHasInstance>().dump(dumper, __location, __instruction->sizeShiftAmount());
32089 break;
32090 case op_instanceof:
32091 __instruction->as<OpInstanceof>().dump(dumper, __location, __instruction->sizeShiftAmount());
32092 break;
32093 case op_instanceof_custom:
32094 __instruction->as<OpInstanceofCustom>().dump(dumper, __location, __instruction->sizeShiftAmount());
32095 break;
32096 case op_typeof:
32097 __instruction->as<OpTypeof>().dump(dumper, __location, __instruction->sizeShiftAmount());
32098 break;
32099 case op_is_cell_with_type:
32100 __instruction->as<OpIsCellWithType>().dump(dumper, __location, __instruction->sizeShiftAmount());
32101 break;
32102 case op_in_by_id:
32103 __instruction->as<OpInById>().dump(dumper, __location, __instruction->sizeShiftAmount());
32104 break;
32105 case op_put_by_id_with_this:
32106 __instruction->as<OpPutByIdWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
32107 break;
32108 case op_del_by_id:
32109 __instruction->as<OpDelById>().dump(dumper, __location, __instruction->sizeShiftAmount());
32110 break;
32111 case op_put_by_val_with_this:
32112 __instruction->as<OpPutByValWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
32113 break;
32114 case op_del_by_val:
32115 __instruction->as<OpDelByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
32116 break;
32117 case op_put_getter_by_id:
32118 __instruction->as<OpPutGetterById>().dump(dumper, __location, __instruction->sizeShiftAmount());
32119 break;
32120 case op_put_setter_by_id:
32121 __instruction->as<OpPutSetterById>().dump(dumper, __location, __instruction->sizeShiftAmount());
32122 break;
32123 case op_put_getter_setter_by_id:
32124 __instruction->as<OpPutGetterSetterById>().dump(dumper, __location, __instruction->sizeShiftAmount());
32125 break;
32126 case op_put_getter_by_val:
32127 __instruction->as<OpPutGetterByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
32128 break;
32129 case op_put_setter_by_val:
32130 __instruction->as<OpPutSetterByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
32131 break;
32132 case op_define_data_property:
32133 __instruction->as<OpDefineDataProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
32134 break;
32135 case op_define_accessor_property:
32136 __instruction->as<OpDefineAccessorProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
32137 break;
32138 case op_jmp:
32139 __instruction->as<OpJmp>().dump(dumper, __location, __instruction->sizeShiftAmount());
32140 break;
32141 case op_jtrue:
32142 __instruction->as<OpJtrue>().dump(dumper, __location, __instruction->sizeShiftAmount());
32143 break;
32144 case op_jfalse:
32145 __instruction->as<OpJfalse>().dump(dumper, __location, __instruction->sizeShiftAmount());
32146 break;
32147 case op_jeq_null:
32148 __instruction->as<OpJeqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
32149 break;
32150 case op_jneq_null:
32151 __instruction->as<OpJneqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
32152 break;
32153 case op_jeq:
32154 __instruction->as<OpJeq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32155 break;
32156 case op_jstricteq:
32157 __instruction->as<OpJstricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32158 break;
32159 case op_jneq:
32160 __instruction->as<OpJneq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32161 break;
32162 case op_jnstricteq:
32163 __instruction->as<OpJnstricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32164 break;
32165 case op_jless:
32166 __instruction->as<OpJless>().dump(dumper, __location, __instruction->sizeShiftAmount());
32167 break;
32168 case op_jlesseq:
32169 __instruction->as<OpJlesseq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32170 break;
32171 case op_jgreater:
32172 __instruction->as<OpJgreater>().dump(dumper, __location, __instruction->sizeShiftAmount());
32173 break;
32174 case op_jgreatereq:
32175 __instruction->as<OpJgreatereq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32176 break;
32177 case op_jnless:
32178 __instruction->as<OpJnless>().dump(dumper, __location, __instruction->sizeShiftAmount());
32179 break;
32180 case op_jnlesseq:
32181 __instruction->as<OpJnlesseq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32182 break;
32183 case op_jngreater:
32184 __instruction->as<OpJngreater>().dump(dumper, __location, __instruction->sizeShiftAmount());
32185 break;
32186 case op_jngreatereq:
32187 __instruction->as<OpJngreatereq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32188 break;
32189 case op_jbelow:
32190 __instruction->as<OpJbelow>().dump(dumper, __location, __instruction->sizeShiftAmount());
32191 break;
32192 case op_jbeloweq:
32193 __instruction->as<OpJbeloweq>().dump(dumper, __location, __instruction->sizeShiftAmount());
32194 break;
32195 case op_loop_hint:
32196 __instruction->as<OpLoopHint>().dump(dumper, __location, __instruction->sizeShiftAmount());
32197 break;
32198 case op_switch_imm:
32199 __instruction->as<OpSwitchImm>().dump(dumper, __location, __instruction->sizeShiftAmount());
32200 break;
32201 case op_switch_char:
32202 __instruction->as<OpSwitchChar>().dump(dumper, __location, __instruction->sizeShiftAmount());
32203 break;
32204 case op_switch_string:
32205 __instruction->as<OpSwitchString>().dump(dumper, __location, __instruction->sizeShiftAmount());
32206 break;
32207 case op_new_func:
32208 __instruction->as<OpNewFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
32209 break;
32210 case op_new_func_exp:
32211 __instruction->as<OpNewFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
32212 break;
32213 case op_new_generator_func:
32214 __instruction->as<OpNewGeneratorFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
32215 break;
32216 case op_new_generator_func_exp:
32217 __instruction->as<OpNewGeneratorFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
32218 break;
32219 case op_new_async_func:
32220 __instruction->as<OpNewAsyncFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
32221 break;
32222 case op_new_async_func_exp:
32223 __instruction->as<OpNewAsyncFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
32224 break;
32225 case op_new_async_generator_func:
32226 __instruction->as<OpNewAsyncGeneratorFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
32227 break;
32228 case op_new_async_generator_func_exp:
32229 __instruction->as<OpNewAsyncGeneratorFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
32230 break;
32231 case op_set_function_name:
32232 __instruction->as<OpSetFunctionName>().dump(dumper, __location, __instruction->sizeShiftAmount());
32233 break;
32234 case op_ret:
32235 __instruction->as<OpRet>().dump(dumper, __location, __instruction->sizeShiftAmount());
32236 break;
32237 case op_strcat:
32238 __instruction->as<OpStrcat>().dump(dumper, __location, __instruction->sizeShiftAmount());
32239 break;
32240 case op_to_primitive:
32241 __instruction->as<OpToPrimitive>().dump(dumper, __location, __instruction->sizeShiftAmount());
32242 break;
32243 case op_put_to_arguments:
32244 __instruction->as<OpPutToArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
32245 break;
32246 case op_push_with_scope:
32247 __instruction->as<OpPushWithScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
32248 break;
32249 case op_create_lexical_environment:
32250 __instruction->as<OpCreateLexicalEnvironment>().dump(dumper, __location, __instruction->sizeShiftAmount());
32251 break;
32252 case op_create_generator_frame_environment:
32253 __instruction->as<OpCreateGeneratorFrameEnvironment>().dump(dumper, __location, __instruction->sizeShiftAmount());
32254 break;
32255 case op_get_parent_scope:
32256 __instruction->as<OpGetParentScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
32257 break;
32258 case op_throw:
32259 __instruction->as<OpThrow>().dump(dumper, __location, __instruction->sizeShiftAmount());
32260 break;
32261 case op_throw_static_error:
32262 __instruction->as<OpThrowStaticError>().dump(dumper, __location, __instruction->sizeShiftAmount());
32263 break;
32264 case op_debug:
32265 __instruction->as<OpDebug>().dump(dumper, __location, __instruction->sizeShiftAmount());
32266 break;
32267 case op_end:
32268 __instruction->as<OpEnd>().dump(dumper, __location, __instruction->sizeShiftAmount());
32269 break;
32270 case op_get_enumerable_length:
32271 __instruction->as<OpGetEnumerableLength>().dump(dumper, __location, __instruction->sizeShiftAmount());
32272 break;
32273 case op_has_structure_property:
32274 __instruction->as<OpHasStructureProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
32275 break;
32276 case op_has_generic_property:
32277 __instruction->as<OpHasGenericProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
32278 break;
32279 case op_get_property_enumerator:
32280 __instruction->as<OpGetPropertyEnumerator>().dump(dumper, __location, __instruction->sizeShiftAmount());
32281 break;
32282 case op_enumerator_structure_pname:
32283 __instruction->as<OpEnumeratorStructurePname>().dump(dumper, __location, __instruction->sizeShiftAmount());
32284 break;
32285 case op_enumerator_generic_pname:
32286 __instruction->as<OpEnumeratorGenericPname>().dump(dumper, __location, __instruction->sizeShiftAmount());
32287 break;
32288 case op_to_index_string:
32289 __instruction->as<OpToIndexString>().dump(dumper, __location, __instruction->sizeShiftAmount());
32290 break;
32291 case op_unreachable:
32292 __instruction->as<OpUnreachable>().dump(dumper, __location, __instruction->sizeShiftAmount());
32293 break;
32294 case op_create_rest:
32295 __instruction->as<OpCreateRest>().dump(dumper, __location, __instruction->sizeShiftAmount());
32296 break;
32297 case op_get_rest_length:
32298 __instruction->as<OpGetRestLength>().dump(dumper, __location, __instruction->sizeShiftAmount());
32299 break;
32300 case op_yield:
32301 __instruction->as<OpYield>().dump(dumper, __location, __instruction->sizeShiftAmount());
32302 break;
32303 case op_check_traps:
32304 __instruction->as<OpCheckTraps>().dump(dumper, __location, __instruction->sizeShiftAmount());
32305 break;
32306 case op_log_shadow_chicken_prologue:
32307 __instruction->as<OpLogShadowChickenPrologue>().dump(dumper, __location, __instruction->sizeShiftAmount());
32308 break;
32309 case op_log_shadow_chicken_tail:
32310 __instruction->as<OpLogShadowChickenTail>().dump(dumper, __location, __instruction->sizeShiftAmount());
32311 break;
32312 case op_resolve_scope_for_hoisting_func_decl_in_eval:
32313 __instruction->as<OpResolveScopeForHoistingFuncDeclInEval>().dump(dumper, __location, __instruction->sizeShiftAmount());
32314 break;
32315 case op_nop:
32316 __instruction->as<OpNop>().dump(dumper, __location, __instruction->sizeShiftAmount());
32317 break;
32318 case op_super_sampler_begin:
32319 __instruction->as<OpSuperSamplerBegin>().dump(dumper, __location, __instruction->sizeShiftAmount());
32320 break;
32321 case op_super_sampler_end:
32322 __instruction->as<OpSuperSamplerEnd>().dump(dumper, __location, __instruction->sizeShiftAmount());
32323 break;
32324 default:
32325 ASSERT_NOT_REACHED();
32326 }
32327}
32328
32329} // namespace JSC
32330