a73ffddafa4f9bad93f0cd4682cda204e9516b45
[WebKit-https.git] / Source / JavaScriptCore / bytecode / BytecodeDumper.cpp
1 /*
2  * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "BytecodeDumper.h"
28
29 #include "ArithProfile.h"
30 #include "CallLinkStatus.h"
31 #include "CodeBlock.h"
32 #include "Error.h"
33 #include "HeapInlines.h"
34 #include "InterpreterInlines.h"
35 #include "PolymorphicAccess.h"
36 #include "PutByIdFlags.h"
37 #include "StructureInlines.h"
38 #include "ToThisStatus.h"
39 #include "UnlinkedCodeBlock.h"
40
41 namespace JSC {
42
43 static StructureID getStructureID(const Instruction& instruction)
44 {
45     return instruction.u.structureID;
46 }
47
48 static StructureID getStructureID(const UnlinkedInstruction&)
49 {
50     return 0;
51 }
52
53 static Special::Pointer getSpecialPointer(const Instruction& instruction)
54 {
55     return instruction.u.specialPointer;
56 }
57
58 static Special::Pointer getSpecialPointer(const UnlinkedInstruction& instruction)
59 {
60     return static_cast<Special::Pointer>(instruction.u.operand);
61 }
62
63 static PutByIdFlags getPutByIdFlags(const Instruction& instruction)
64 {
65     return instruction.u.putByIdFlags;
66 }
67
68 static PutByIdFlags getPutByIdFlags(const UnlinkedInstruction& instruction)
69 {
70     return static_cast<PutByIdFlags>(instruction.u.operand);
71 }
72
73 static ToThisStatus getToThisStatus(const Instruction& instruction)
74 {
75     return instruction.u.toThisStatus;
76 }
77
78 static ToThisStatus getToThisStatus(const UnlinkedInstruction& instruction)
79 {
80     return static_cast<ToThisStatus>(instruction.u.operand);
81 }
82
83 static void* getPointer(const Instruction& instruction)
84 {
85     return instruction.u.pointer;
86 }
87
88 static void* getPointer(const UnlinkedInstruction&)
89 {
90     return nullptr;
91 }
92
93 static StructureChain* getStructureChain(const Instruction& instruction)
94 {
95     return instruction.u.structureChain.get();
96 }
97
98 static StructureChain* getStructureChain(const UnlinkedInstruction&)
99 {
100     return nullptr;
101 }
102
103 static Structure* getStructure(const Instruction& instruction)
104 {
105     return instruction.u.structure.get();
106 }
107
108 static Structure* getStructure(const UnlinkedInstruction&)
109 {
110     return nullptr;
111 }
112
113 static LLIntCallLinkInfo* getCallLinkInfo(const Instruction& instruction)
114 {
115     return instruction.u.callLinkInfo;
116 }
117
118 static LLIntCallLinkInfo* getCallLinkInfo(const UnlinkedInstruction&)
119 {
120     return nullptr;
121 }
122
123 static BasicBlockLocation* getBasicBlockLocation(const Instruction& instruction)
124 {
125     return instruction.u.basicBlockLocation;
126 }
127
128 static BasicBlockLocation* getBasicBlockLocation(const UnlinkedInstruction&)
129 {
130     return nullptr;
131 }
132
133 template<class Block>
134 void* BytecodeDumper<Block>::actualPointerFor(Special::Pointer) const
135 {
136     return nullptr;
137 }
138
139 template<>
140 void* BytecodeDumper<CodeBlock>::actualPointerFor(Special::Pointer pointer) const
141 {
142     return block()->globalObject()->actualPointerFor(pointer);
143 }
144
145 static void beginDumpProfiling(PrintStream& out, bool& hasPrintedProfiling)
146 {
147     if (hasPrintedProfiling) {
148         out.print("; ");
149         return;
150     }
151
152     out.print("    ");
153     hasPrintedProfiling = true;
154 }
155
156 template<class Block>
157 void BytecodeDumper<Block>::dumpValueProfiling(PrintStream&, const typename Block::Instruction*& it, bool&)
158 {
159     ++it;
160 }
161
162 template<>
163 void BytecodeDumper<CodeBlock>::dumpValueProfiling(PrintStream& out, const typename CodeBlock::Instruction*& it, bool& hasPrintedProfiling)
164 {
165     ConcurrentJSLocker locker(block()->m_lock);
166
167     ++it;
168     CString description = it->u.profile->briefDescription(locker);
169     if (!description.length())
170         return;
171     beginDumpProfiling(out, hasPrintedProfiling);
172     out.print(description);
173 }
174
175 template<class Block>
176 void BytecodeDumper<Block>::dumpArrayProfiling(PrintStream&, const typename Block::Instruction*& it, bool&)
177 {
178     ++it;
179 }
180
181 template<>
182 void BytecodeDumper<CodeBlock>::dumpArrayProfiling(PrintStream& out, const typename CodeBlock::Instruction*& it, bool& hasPrintedProfiling)
183 {
184     ConcurrentJSLocker locker(block()->m_lock);
185
186     ++it;
187     if (!it->u.arrayProfile)
188         return;
189     CString description = it->u.arrayProfile->briefDescription(locker, block());
190     if (!description.length())
191         return;
192     beginDumpProfiling(out, hasPrintedProfiling);
193     out.print(description);
194 }
195
196 template<class Block>
197 void BytecodeDumper<Block>::dumpProfilesForBytecodeOffset(PrintStream&, unsigned, bool&)
198 {
199 }
200
201 static void dumpRareCaseProfile(PrintStream& out, const char* name, RareCaseProfile* profile, bool& hasPrintedProfiling)
202 {
203     if (!profile || !profile->m_counter)
204         return;
205
206     beginDumpProfiling(out, hasPrintedProfiling);
207     out.print(name, profile->m_counter);
208 }
209
210 static void dumpArithProfile(PrintStream& out, ArithProfile* profile, bool& hasPrintedProfiling)
211 {
212     if (!profile)
213         return;
214
215     beginDumpProfiling(out, hasPrintedProfiling);
216     out.print("results: ", *profile);
217 }
218
219 template<>
220 void BytecodeDumper<CodeBlock>::dumpProfilesForBytecodeOffset(PrintStream& out, unsigned location, bool& hasPrintedProfiling)
221 {
222     dumpRareCaseProfile(out, "rare case: ", block()->rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
223     {
224         dumpArithProfile(out, block()->arithProfileForBytecodeOffset(location), hasPrintedProfiling);
225     }
226
227 #if ENABLE(DFG_JIT)
228     Vector<DFG::FrequentExitSite> exitSites = block()->exitProfile().exitSitesFor(location);
229     if (!exitSites.isEmpty()) {
230         out.print(" !! frequent exits: ");
231         CommaPrinter comma;
232         for (auto& exitSite : exitSites)
233             out.print(comma, exitSite.kind(), " ", exitSite.jitType());
234     }
235 #else // ENABLE(DFG_JIT)
236     UNUSED_PARAM(location);
237 #endif // ENABLE(DFG_JIT)
238 }
239
240 template<class Block>
241 VM* BytecodeDumper<Block>::vm() const
242 {
243     return block()->vm();
244 }
245
246 template<class Block>
247 const Identifier& BytecodeDumper<Block>::identifier(int index) const
248 {
249     return block()->identifier(index);
250 }
251
252 static CString regexpToSourceString(RegExp* regExp)
253 {
254     char postfix[5] = { '/', 0, 0, 0, 0 };
255     int index = 1;
256     if (regExp->global())
257         postfix[index++] = 'g';
258     if (regExp->ignoreCase())
259         postfix[index++] = 'i';
260     if (regExp->multiline())
261         postfix[index] = 'm';
262     if (regExp->sticky())
263         postfix[index++] = 'y';
264     if (regExp->unicode())
265         postfix[index++] = 'u';
266
267     return toCString("/", regExp->pattern().impl(), postfix);
268 }
269
270 static CString regexpName(int re, RegExp* regexp)
271 {
272     return toCString(regexpToSourceString(regexp), "(@re", re, ")");
273 }
274
275 template<class Instruction>
276 static void printLocationAndOp(PrintStream& out, int location, const Instruction*&, const char* op)
277 {
278     out.printf("[%4d] %-17s ", location, op);
279 }
280
281 static ALWAYS_INLINE bool isConstantRegisterIndex(int index)
282 {
283     return index >= FirstConstantRegisterIndex;
284 }
285
286 NEVER_INLINE static const char* debugHookName(int debugHookType)
287 {
288     switch (static_cast<DebugHookType>(debugHookType)) {
289     case DidEnterCallFrame:
290         return "didEnterCallFrame";
291     case WillLeaveCallFrame:
292         return "willLeaveCallFrame";
293     case WillExecuteStatement:
294         return "willExecuteStatement";
295     case WillExecuteExpression:
296         return "willExecuteExpression";
297     case WillExecuteProgram:
298         return "willExecuteProgram";
299     case DidExecuteProgram:
300         return "didExecuteProgram";
301     case DidReachBreakpoint:
302         return "didReachBreakpoint";
303     }
304
305     RELEASE_ASSERT_NOT_REACHED();
306     return "";
307 }
308
309 template<class Block>
310 CString BytecodeDumper<Block>::registerName(int r) const
311 {
312     if (isConstantRegisterIndex(r))
313         return constantName(r);
314
315     return toCString(VirtualRegister(r));
316 }
317
318 static CString idName(int id0, const Identifier& ident)
319 {
320     return toCString(ident.impl(), "(@id", id0, ")");
321 }
322
323 template<class Block>
324 CString BytecodeDumper<Block>::constantName(int index) const
325 {
326     JSValue value = block()->getConstant(index);
327     return toCString(value, "(", VirtualRegister(index), ")");
328 }
329
330 template<class Block>
331 void BytecodeDumper<Block>::printUnaryOp(PrintStream& out, int location, const typename Block::Instruction*& it, const char* op)
332 {
333     int r0 = (++it)->u.operand;
334     int r1 = (++it)->u.operand;
335
336     printLocationAndOp(out, location, it, op);
337     out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
338 }
339
340 template<class Block>
341 void BytecodeDumper<Block>::printBinaryOp(PrintStream& out, int location, const typename Block::Instruction*& it, const char* op)
342 {
343     int r0 = (++it)->u.operand;
344     int r1 = (++it)->u.operand;
345     int r2 = (++it)->u.operand;
346     printLocationAndOp(out, location, it, op);
347     out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
348 }
349
350 template<class Block>
351 void BytecodeDumper<Block>::printConditionalJump(PrintStream& out, const typename Block::Instruction*, const typename Block::Instruction*& it, int location, const char* op)
352 {
353     int r0 = (++it)->u.operand;
354     int offset = (++it)->u.operand;
355     printLocationAndOp(out, location, it, op);
356     out.printf("%s, %d(->%d)", registerName(r0).data(), offset, location + offset);
357 }
358
359 template<class Block>
360 void BytecodeDumper<Block>::printGetByIdOp(PrintStream& out, int location, const typename Block::Instruction*& it)
361 {
362     const char* op;
363     switch (vm()->interpreter->getOpcodeID(*it)) {
364     case op_get_by_id:
365         op = "get_by_id";
366         break;
367     case op_get_by_id_proto_load:
368         op = "get_by_id_proto_load";
369         break;
370     case op_get_by_id_unset:
371         op = "get_by_id_unset";
372         break;
373     case op_get_array_length:
374         op = "array_length";
375         break;
376     default:
377         RELEASE_ASSERT_NOT_REACHED();
378 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
379         op = 0;
380 #endif
381     }
382     int r0 = (++it)->u.operand;
383     int r1 = (++it)->u.operand;
384     int id0 = (++it)->u.operand;
385     printLocationAndOp(out, location, it, op);
386     out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
387     it += 4; // Increment up to the value profiler.
388 }
389
390 static void dumpStructure(PrintStream& out, const char* name, Structure* structure, const Identifier& ident)
391 {
392     if (!structure)
393         return;
394
395     out.printf("%s = %p", name, structure);
396
397     PropertyOffset offset = structure->getConcurrently(ident.impl());
398     if (offset != invalidOffset)
399         out.printf(" (offset = %d)", offset);
400 }
401
402 static void dumpChain(PrintStream& out, StructureChain* chain, const Identifier& ident)
403 {
404     out.printf("chain = %p: [", chain);
405     bool first = true;
406     for (WriteBarrier<Structure>* currentStructure = chain->head(); *currentStructure; ++currentStructure) {
407         if (first)
408             first = false;
409         else
410             out.printf(", ");
411         dumpStructure(out, "struct", currentStructure->get(), ident);
412     }
413     out.printf("]");
414 }
415
416 template<class Block>
417 void BytecodeDumper<Block>::printGetByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
418 {
419     const auto* instruction = instructionsBegin() + location;
420
421     const Identifier& ident = identifier(instruction[3].u.operand);
422
423     UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
424
425     if (vm()->interpreter->getOpcodeID(instruction[0]) == op_get_array_length)
426         out.printf(" llint(array_length)");
427     else if (StructureID structureID = getStructureID(instruction[4])) {
428         Structure* structure = vm()->heap.structureIDTable().get(structureID);
429         out.printf(" llint(");
430         dumpStructure(out, "struct", structure, ident);
431         out.printf(")");
432         if (vm()->interpreter->getOpcodeID(instruction[0]) == op_get_by_id_proto_load)
433             out.printf(" proto(%p)", getPointer(instruction[6]));
434     }
435
436 #if ENABLE(JIT)
437     if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
438         StructureStubInfo& stubInfo = *stubPtr;
439         if (stubInfo.resetByGC)
440             out.print(" (Reset By GC)");
441
442         out.printf(" jit(");
443
444         Structure* baseStructure = nullptr;
445         PolymorphicAccess* stub = nullptr;
446
447         switch (stubInfo.cacheType) {
448         case CacheType::GetByIdSelf:
449             out.printf("self");
450             baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get();
451             break;
452         case CacheType::Stub:
453             out.printf("stub");
454             stub = stubInfo.u.stub;
455             break;
456         case CacheType::Unset:
457             out.printf("unset");
458             break;
459         case CacheType::ArrayLength:
460             out.printf("ArrayLength");
461             break;
462         default:
463             RELEASE_ASSERT_NOT_REACHED();
464             break;
465         }
466
467         if (baseStructure) {
468             out.printf(", ");
469             dumpStructure(out, "struct", baseStructure, ident);
470         }
471
472         if (stub)
473             out.print(", ", *stub);
474
475         out.printf(")");
476     }
477 #else
478     UNUSED_PARAM(map);
479 #endif
480 }
481
482 template<class Block>
483 void BytecodeDumper<Block>::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
484 {
485     const auto* instruction = instructionsBegin() + location;
486
487     const Identifier& ident = identifier(instruction[2].u.operand);
488
489     UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
490
491     out.print(", ", getPutByIdFlags(instruction[8]));
492
493     if (StructureID structureID = getStructureID(instruction[4])) {
494         Structure* structure = vm()->heap.structureIDTable().get(structureID);
495         out.print(" llint(");
496         if (StructureID newStructureID = getStructureID(instruction[6])) {
497             Structure* newStructure = vm()->heap.structureIDTable().get(newStructureID);
498             dumpStructure(out, "prev", structure, ident);
499             out.print(", ");
500             dumpStructure(out, "next", newStructure, ident);
501             if (StructureChain* chain = getStructureChain(instruction[7])) {
502                 out.print(", ");
503                 dumpChain(out, chain, ident);
504             }
505         } else
506             dumpStructure(out, "struct", structure, ident);
507         out.print(")");
508     }
509
510 #if ENABLE(JIT)
511     if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
512         StructureStubInfo& stubInfo = *stubPtr;
513         if (stubInfo.resetByGC)
514             out.print(" (Reset By GC)");
515
516         out.printf(" jit(");
517
518         switch (stubInfo.cacheType) {
519         case CacheType::PutByIdReplace:
520             out.print("replace, ");
521             dumpStructure(out, "struct", stubInfo.u.byIdSelf.baseObjectStructure.get(), ident);
522             break;
523         case CacheType::Stub: {
524             out.print("stub, ", *stubInfo.u.stub);
525             break;
526         }
527         case CacheType::Unset:
528             out.printf("unset");
529             break;
530         default:
531             RELEASE_ASSERT_NOT_REACHED();
532             break;
533         }
534         out.printf(")");
535     }
536 #else
537     UNUSED_PARAM(map);
538 #endif
539 }
540
541 #if ENABLE(JIT)
542 template<typename Block>
543 void BytecodeDumper<Block>::dumpCallLinkStatus(PrintStream&, unsigned, const CallLinkInfoMap&)
544 {
545 }
546
547 template<>
548 void BytecodeDumper<CodeBlock>::dumpCallLinkStatus(PrintStream& out, unsigned location, const CallLinkInfoMap& map)
549 {
550     if (block()->jitType() != JITCode::FTLJIT)
551         out.print(" status(", CallLinkStatus::computeFor(block(), location, map), ")");
552 }
553 #endif
554
555 template<class Block>
556 void BytecodeDumper<Block>::printCallOp(PrintStream& out, int location, const typename Block::Instruction*& it, const char* op, CacheDumpMode cacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap& map)
557 {
558     int dst = (++it)->u.operand;
559     int func = (++it)->u.operand;
560     int argCount = (++it)->u.operand;
561     int registerOffset = (++it)->u.operand;
562     printLocationAndOp(out, location, it, op);
563     out.print(registerName(dst), ", ", registerName(func), ", ", argCount, ", ", registerOffset);
564     out.print(" (this at ", virtualRegisterForArgument(0, -registerOffset), ")");
565     if (cacheDumpMode == DumpCaches) {
566         LLIntCallLinkInfo* callLinkInfo = getCallLinkInfo(it[1]);
567         if (callLinkInfo->lastSeenCallee) {
568             out.printf(
569                 " llint(%p, exec %p)",
570                 callLinkInfo->lastSeenCallee.get(),
571                 callLinkInfo->lastSeenCallee->executable());
572         }
573 #if ENABLE(JIT)
574         if (CallLinkInfo* info = map.get(CodeOrigin(location))) {
575             JSFunction* target = info->lastSeenCallee();
576             if (target)
577                 out.printf(" jit(%p, exec %p)", target, target->executable());
578         }
579
580         dumpCallLinkStatus(out, location, map);
581 #else
582         UNUSED_PARAM(map);
583 #endif
584     }
585     ++it;
586     ++it;
587     dumpArrayProfiling(out, it, hasPrintedProfiling);
588     dumpValueProfiling(out, it, hasPrintedProfiling);
589 }
590
591 template<class Block>
592 void BytecodeDumper<Block>::printPutByIdOp(PrintStream& out, int location, const typename Block::Instruction*& it, const char* op)
593 {
594     int r0 = (++it)->u.operand;
595     int id0 = (++it)->u.operand;
596     int r1 = (++it)->u.operand;
597     printLocationAndOp(out, location, it, op);
598     out.printf("%s, %s, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), registerName(r1).data());
599     it += 5;
600 }
601
602 template<class Block>
603 void BytecodeDumper<Block>::printLocationOpAndRegisterOperand(PrintStream& out, int location, const typename Block::Instruction*& it, const char* op, int operand)
604 {
605     printLocationAndOp(out, location, it, op);
606     out.printf("%s", registerName(operand).data());
607 }
608
609 template<class Block>
610 void BytecodeDumper<Block>::dumpBytecode(PrintStream& out, const typename Block::Instruction* begin, const typename Block::Instruction*& it, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
611 {
612     int location = it - begin;
613     bool hasPrintedProfiling = false;
614     OpcodeID opcode = vm()->interpreter->getOpcodeID(*it);
615     switch (opcode) {
616     case op_enter: {
617         printLocationAndOp(out, location, it, "enter");
618         break;
619     }
620     case op_get_scope: {
621         int r0 = (++it)->u.operand;
622         printLocationOpAndRegisterOperand(out, location, it, "get_scope", r0);
623         break;
624     }
625     case op_create_direct_arguments: {
626         int r0 = (++it)->u.operand;
627         printLocationAndOp(out, location, it, "create_direct_arguments");
628         out.printf("%s", registerName(r0).data());
629         break;
630     }
631     case op_create_scoped_arguments: {
632         int r0 = (++it)->u.operand;
633         int r1 = (++it)->u.operand;
634         printLocationAndOp(out, location, it, "create_scoped_arguments");
635         out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
636         break;
637     }
638     case op_create_cloned_arguments: {
639         int r0 = (++it)->u.operand;
640         printLocationAndOp(out, location, it, "create_cloned_arguments");
641         out.printf("%s", registerName(r0).data());
642         break;
643     }
644     case op_argument_count: {
645         int r0 = (++it)->u.operand;
646         printLocationOpAndRegisterOperand(out, location, it, "argument_count", r0);
647         break;
648     }
649     case op_get_argument: {
650         int r0 = (++it)->u.operand;
651         int index = (++it)->u.operand;
652         printLocationOpAndRegisterOperand(out, location, it, "argument", r0);
653         out.printf(", %d", index);
654         dumpValueProfiling(out, it, hasPrintedProfiling);
655         break;
656     }
657     case op_create_rest: {
658         int r0 = (++it)->u.operand;
659         int r1 = (++it)->u.operand;
660         unsigned argumentOffset = (++it)->u.unsignedValue;
661         printLocationAndOp(out, location, it, "create_rest");
662         out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data());
663         out.printf("ArgumentsOffset: %u", argumentOffset);
664         break;
665     }
666     case op_get_rest_length: {
667         int r0 = (++it)->u.operand;
668         printLocationAndOp(out, location, it, "get_rest_length");
669         out.printf("%s, ", registerName(r0).data());
670         unsigned argumentOffset = (++it)->u.unsignedValue;
671         out.printf("ArgumentsOffset: %u", argumentOffset);
672         break;
673     }
674     case op_create_this: {
675         int r0 = (++it)->u.operand;
676         int r1 = (++it)->u.operand;
677         unsigned inferredInlineCapacity = (++it)->u.operand;
678         unsigned cachedFunction = (++it)->u.operand;
679         printLocationAndOp(out, location, it, "create_this");
680         out.printf("%s, %s, %u, %u", registerName(r0).data(), registerName(r1).data(), inferredInlineCapacity, cachedFunction);
681         break;
682     }
683     case op_to_this: {
684         int r0 = (++it)->u.operand;
685         printLocationOpAndRegisterOperand(out, location, it, "to_this", r0);
686         Structure* structure = getStructure(*(++it));
687         if (structure)
688             out.print(", cache(struct = ", RawPointer(structure), ")");
689         out.print(", ", getToThisStatus(*(++it)));
690         break;
691     }
692     case op_check_tdz: {
693         int r0 = (++it)->u.operand;
694         printLocationOpAndRegisterOperand(out, location, it, "op_check_tdz", r0);
695         break;
696     }
697     case op_new_object: {
698         int r0 = (++it)->u.operand;
699         unsigned inferredInlineCapacity = (++it)->u.operand;
700         printLocationAndOp(out, location, it, "new_object");
701         out.printf("%s, %u", registerName(r0).data(), inferredInlineCapacity);
702         ++it; // Skip object allocation profile.
703         break;
704     }
705     case op_new_array: {
706         int dst = (++it)->u.operand;
707         int argv = (++it)->u.operand;
708         int argc = (++it)->u.operand;
709         printLocationAndOp(out, location, it, "new_array");
710         out.printf("%s, %s, %d", registerName(dst).data(), registerName(argv).data(), argc);
711         ++it; // Skip array allocation profile.
712         break;
713     }
714     case op_new_array_with_spread: {
715         int dst = (++it)->u.operand;
716         int argv = (++it)->u.operand;
717         int argc = (++it)->u.operand;
718         printLocationAndOp(out, location, it, "new_array_with_spread");
719         out.printf("%s, %s, %d, ", registerName(dst).data(), registerName(argv).data(), argc);
720         unsigned bitVectorIndex = (++it)->u.unsignedValue;
721         const BitVector& bitVector = block()->bitVector(bitVectorIndex);
722         out.print("BitVector:", bitVectorIndex, ":");
723         for (unsigned i = 0; i < static_cast<unsigned>(argc); i++) {
724             if (bitVector.get(i))
725                 out.print("1");
726             else
727                 out.print("0");
728         }
729         break;
730     }
731     case op_spread: {
732         int dst = (++it)->u.operand;
733         int arg = (++it)->u.operand;
734         printLocationAndOp(out, location, it, "spread");
735         out.printf("%s, %s", registerName(dst).data(), registerName(arg).data());
736         break;
737     }
738     case op_new_array_with_size: {
739         int dst = (++it)->u.operand;
740         int length = (++it)->u.operand;
741         printLocationAndOp(out, location, it, "new_array_with_size");
742         out.printf("%s, %s", registerName(dst).data(), registerName(length).data());
743         ++it; // Skip array allocation profile.
744         break;
745     }
746     case op_new_array_buffer: {
747         int dst = (++it)->u.operand;
748         int argv = (++it)->u.operand;
749         int argc = (++it)->u.operand;
750         printLocationAndOp(out, location, it, "new_array_buffer");
751         out.printf("%s, %d, %d", registerName(dst).data(), argv, argc);
752         ++it; // Skip array allocation profile.
753         break;
754     }
755     case op_new_regexp: {
756         int r0 = (++it)->u.operand;
757         int re0 = (++it)->u.operand;
758         printLocationAndOp(out, location, it, "new_regexp");
759         out.printf("%s, ", registerName(r0).data());
760         if (r0 >=0 && r0 < (int)block()->numberOfRegExps())
761             out.printf("%s", regexpName(re0, block()->regexp(re0)).data());
762         else
763             out.printf("bad_regexp(%d)", re0);
764         break;
765     }
766     case op_mov: {
767         int r0 = (++it)->u.operand;
768         int r1 = (++it)->u.operand;
769         printLocationAndOp(out, location, it, "mov");
770         out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
771         break;
772     }
773     case op_profile_type: {
774         int r0 = (++it)->u.operand;
775         ++it;
776         ++it;
777         ++it;
778         ++it;
779         printLocationAndOp(out, location, it, "op_profile_type");
780         out.printf("%s", registerName(r0).data());
781         break;
782     }
783     case op_profile_control_flow: {
784         BasicBlockLocation* basicBlockLocation = getBasicBlockLocation(*(++it));
785         printLocationAndOp(out, location, it, "profile_control_flow");
786         if (basicBlockLocation)
787             out.printf("[%d, %d]", basicBlockLocation->startOffset(), basicBlockLocation->endOffset());
788         break;
789     }
790     case op_not: {
791         printUnaryOp(out, location, it, "not");
792         break;
793     }
794     case op_eq: {
795         printBinaryOp(out, location, it, "eq");
796         break;
797     }
798     case op_eq_null: {
799         printUnaryOp(out, location, it, "eq_null");
800         break;
801     }
802     case op_neq: {
803         printBinaryOp(out, location, it, "neq");
804         break;
805     }
806     case op_neq_null: {
807         printUnaryOp(out, location, it, "neq_null");
808         break;
809     }
810     case op_stricteq: {
811         printBinaryOp(out, location, it, "stricteq");
812         break;
813     }
814     case op_nstricteq: {
815         printBinaryOp(out, location, it, "nstricteq");
816         break;
817     }
818     case op_less: {
819         printBinaryOp(out, location, it, "less");
820         break;
821     }
822     case op_lesseq: {
823         printBinaryOp(out, location, it, "lesseq");
824         break;
825     }
826     case op_greater: {
827         printBinaryOp(out, location, it, "greater");
828         break;
829     }
830     case op_greatereq: {
831         printBinaryOp(out, location, it, "greatereq");
832         break;
833     }
834     case op_inc: {
835         int r0 = (++it)->u.operand;
836         printLocationOpAndRegisterOperand(out, location, it, "inc", r0);
837         break;
838     }
839     case op_dec: {
840         int r0 = (++it)->u.operand;
841         printLocationOpAndRegisterOperand(out, location, it, "dec", r0);
842         break;
843     }
844     case op_to_number: {
845         printUnaryOp(out, location, it, "to_number");
846         dumpValueProfiling(out, it, hasPrintedProfiling);
847         break;
848     }
849     case op_to_string: {
850         printUnaryOp(out, location, it, "to_string");
851         break;
852     }
853     case op_negate: {
854         printUnaryOp(out, location, it, "negate");
855         ++it; // op_negate has an extra operand for the ArithProfile.
856         break;
857     }
858     case op_add: {
859         printBinaryOp(out, location, it, "add");
860         ++it;
861         break;
862     }
863     case op_mul: {
864         printBinaryOp(out, location, it, "mul");
865         ++it;
866         break;
867     }
868     case op_div: {
869         printBinaryOp(out, location, it, "div");
870         ++it;
871         break;
872     }
873     case op_mod: {
874         printBinaryOp(out, location, it, "mod");
875         break;
876     }
877     case op_pow: {
878         printBinaryOp(out, location, it, "pow");
879         break;
880     }
881     case op_sub: {
882         printBinaryOp(out, location, it, "sub");
883         ++it;
884         break;
885     }
886     case op_lshift: {
887         printBinaryOp(out, location, it, "lshift");
888         break;
889     }
890     case op_rshift: {
891         printBinaryOp(out, location, it, "rshift");
892         break;
893     }
894     case op_urshift: {
895         printBinaryOp(out, location, it, "urshift");
896         break;
897     }
898     case op_bitand: {
899         printBinaryOp(out, location, it, "bitand");
900         ++it;
901         break;
902     }
903     case op_bitxor: {
904         printBinaryOp(out, location, it, "bitxor");
905         ++it;
906         break;
907     }
908     case op_bitor: {
909         printBinaryOp(out, location, it, "bitor");
910         ++it;
911         break;
912     }
913     case op_overrides_has_instance: {
914         int r0 = (++it)->u.operand;
915         int r1 = (++it)->u.operand;
916         int r2 = (++it)->u.operand;
917         printLocationAndOp(out, location, it, "overrides_has_instance");
918         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
919         break;
920     }
921     case op_instanceof: {
922         int r0 = (++it)->u.operand;
923         int r1 = (++it)->u.operand;
924         int r2 = (++it)->u.operand;
925         printLocationAndOp(out, location, it, "instanceof");
926         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
927         break;
928     }
929     case op_instanceof_custom: {
930         int r0 = (++it)->u.operand;
931         int r1 = (++it)->u.operand;
932         int r2 = (++it)->u.operand;
933         int r3 = (++it)->u.operand;
934         printLocationAndOp(out, location, it, "instanceof_custom");
935         out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
936         break;
937     }
938     case op_unsigned: {
939         printUnaryOp(out, location, it, "unsigned");
940         break;
941     }
942     case op_typeof: {
943         printUnaryOp(out, location, it, "typeof");
944         break;
945     }
946     case op_is_empty: {
947         printUnaryOp(out, location, it, "is_empty");
948         break;
949     }
950     case op_is_undefined: {
951         printUnaryOp(out, location, it, "is_undefined");
952         break;
953     }
954     case op_is_boolean: {
955         printUnaryOp(out, location, it, "is_boolean");
956         break;
957     }
958     case op_is_number: {
959         printUnaryOp(out, location, it, "is_number");
960         break;
961     }
962     case op_is_cell_with_type: {
963         int r0 = (++it)->u.operand;
964         int r1 = (++it)->u.operand;
965         int type = (++it)->u.operand;
966         printLocationAndOp(out, location, it, "is_cell_with_type");
967         out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), type);
968         break;
969     }
970     case op_is_object: {
971         printUnaryOp(out, location, it, "is_object");
972         break;
973     }
974     case op_is_object_or_null: {
975         printUnaryOp(out, location, it, "is_object_or_null");
976         break;
977     }
978     case op_is_function: {
979         printUnaryOp(out, location, it, "is_function");
980         break;
981     }
982     case op_in: {
983         printBinaryOp(out, location, it, "in");
984         dumpArrayProfiling(out, it, hasPrintedProfiling);
985         break;
986     }
987     case op_try_get_by_id: {
988         int r0 = (++it)->u.operand;
989         int r1 = (++it)->u.operand;
990         int id0 = (++it)->u.operand;
991         printLocationAndOp(out, location, it, "try_get_by_id");
992         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
993         dumpValueProfiling(out, it, hasPrintedProfiling);
994         break;
995     }
996     case op_get_by_id:
997     case op_get_by_id_proto_load:
998     case op_get_by_id_unset:
999     case op_get_array_length: {
1000         printGetByIdOp(out, location, it);
1001         printGetByIdCacheStatus(out, location, stubInfos);
1002         dumpValueProfiling(out, it, hasPrintedProfiling);
1003         break;
1004     }
1005     case op_get_by_id_with_this: {
1006         printLocationAndOp(out, location, it, "get_by_id_with_this");
1007         int r0 = (++it)->u.operand;
1008         int r1 = (++it)->u.operand;
1009         int r2 = (++it)->u.operand;
1010         int id0 = (++it)->u.operand;
1011         out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), idName(id0, identifier(id0)).data());
1012         dumpValueProfiling(out, it, hasPrintedProfiling);
1013         break;
1014     }
1015     case op_get_by_val_with_this: {
1016         int r0 = (++it)->u.operand;
1017         int r1 = (++it)->u.operand;
1018         int r2 = (++it)->u.operand;
1019         int r3 = (++it)->u.operand;
1020         printLocationAndOp(out, location, it, "get_by_val_with_this");
1021         out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
1022         dumpValueProfiling(out, it, hasPrintedProfiling);
1023         break;
1024     }
1025     case op_put_by_id: {
1026         printPutByIdOp(out, location, it, "put_by_id");
1027         printPutByIdCacheStatus(out, location, stubInfos);
1028         break;
1029     }
1030     case op_put_by_id_with_this: {
1031         int r0 = (++it)->u.operand;
1032         int r1 = (++it)->u.operand;
1033         int id0 = (++it)->u.operand;
1034         int r2 = (++it)->u.operand;
1035         printLocationAndOp(out, location, it, "put_by_id_with_this");
1036         out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data(), registerName(r2).data());
1037         break;
1038     }
1039     case op_put_by_val_with_this: {
1040         int r0 = (++it)->u.operand;
1041         int r1 = (++it)->u.operand;
1042         int r2 = (++it)->u.operand;
1043         int r3 = (++it)->u.operand;
1044         printLocationAndOp(out, location, it, "put_by_val_with_this");
1045         out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
1046         break;
1047     }
1048     case op_put_getter_by_id: {
1049         int r0 = (++it)->u.operand;
1050         int id0 = (++it)->u.operand;
1051         int n0 = (++it)->u.operand;
1052         int r1 = (++it)->u.operand;
1053         printLocationAndOp(out, location, it, "put_getter_by_id");
1054         out.printf("%s, %s, %d, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data());
1055         break;
1056     }
1057     case op_put_setter_by_id: {
1058         int r0 = (++it)->u.operand;
1059         int id0 = (++it)->u.operand;
1060         int n0 = (++it)->u.operand;
1061         int r1 = (++it)->u.operand;
1062         printLocationAndOp(out, location, it, "put_setter_by_id");
1063         out.printf("%s, %s, %d, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data());
1064         break;
1065     }
1066     case op_put_getter_setter_by_id: {
1067         int r0 = (++it)->u.operand;
1068         int id0 = (++it)->u.operand;
1069         int n0 = (++it)->u.operand;
1070         int r1 = (++it)->u.operand;
1071         int r2 = (++it)->u.operand;
1072         printLocationAndOp(out, location, it, "put_getter_setter_by_id");
1073         out.printf("%s, %s, %d, %s, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data(), registerName(r2).data());
1074         break;
1075     }
1076     case op_put_getter_by_val: {
1077         int r0 = (++it)->u.operand;
1078         int r1 = (++it)->u.operand;
1079         int n0 = (++it)->u.operand;
1080         int r2 = (++it)->u.operand;
1081         printLocationAndOp(out, location, it, "put_getter_by_val");
1082         out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
1083         break;
1084     }
1085     case op_put_setter_by_val: {
1086         int r0 = (++it)->u.operand;
1087         int r1 = (++it)->u.operand;
1088         int n0 = (++it)->u.operand;
1089         int r2 = (++it)->u.operand;
1090         printLocationAndOp(out, location, it, "put_setter_by_val");
1091         out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
1092         break;
1093     }
1094     case op_define_data_property: {
1095         int r0 = (++it)->u.operand;
1096         int r1 = (++it)->u.operand;
1097         int r2 = (++it)->u.operand;
1098         int r3 = (++it)->u.operand;
1099         printLocationAndOp(out, location, it, "define_data_property");
1100         out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
1101         break;
1102     }
1103     case op_define_accessor_property: {
1104         int r0 = (++it)->u.operand;
1105         int r1 = (++it)->u.operand;
1106         int r2 = (++it)->u.operand;
1107         int r3 = (++it)->u.operand;
1108         int r4 = (++it)->u.operand;
1109         printLocationAndOp(out, location, it, "define_accessor_property");
1110         out.printf("%s, %s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data(), registerName(r4).data());
1111         break;
1112     }
1113     case op_del_by_id: {
1114         int r0 = (++it)->u.operand;
1115         int r1 = (++it)->u.operand;
1116         int id0 = (++it)->u.operand;
1117         printLocationAndOp(out, location, it, "del_by_id");
1118         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
1119         break;
1120     }
1121     case op_get_by_val: {
1122         int r0 = (++it)->u.operand;
1123         int r1 = (++it)->u.operand;
1124         int r2 = (++it)->u.operand;
1125         printLocationAndOp(out, location, it, "get_by_val");
1126         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
1127         dumpArrayProfiling(out, it, hasPrintedProfiling);
1128         dumpValueProfiling(out, it, hasPrintedProfiling);
1129         break;
1130     }
1131     case op_put_by_val: {
1132         int r0 = (++it)->u.operand;
1133         int r1 = (++it)->u.operand;
1134         int r2 = (++it)->u.operand;
1135         printLocationAndOp(out, location, it, "put_by_val");
1136         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
1137         dumpArrayProfiling(out, it, hasPrintedProfiling);
1138         break;
1139     }
1140     case op_put_by_val_direct: {
1141         int r0 = (++it)->u.operand;
1142         int r1 = (++it)->u.operand;
1143         int r2 = (++it)->u.operand;
1144         printLocationAndOp(out, location, it, "put_by_val_direct");
1145         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
1146         dumpArrayProfiling(out, it, hasPrintedProfiling);
1147         break;
1148     }
1149     case op_del_by_val: {
1150         int r0 = (++it)->u.operand;
1151         int r1 = (++it)->u.operand;
1152         int r2 = (++it)->u.operand;
1153         printLocationAndOp(out, location, it, "del_by_val");
1154         out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
1155         break;
1156     }
1157     case op_put_by_index: {
1158         int r0 = (++it)->u.operand;
1159         unsigned n0 = (++it)->u.operand;
1160         int r1 = (++it)->u.operand;
1161         printLocationAndOp(out, location, it, "put_by_index");
1162         out.printf("%s, %u, %s", registerName(r0).data(), n0, registerName(r1).data());
1163         break;
1164     }
1165     case op_jmp: {
1166         int offset = (++it)->u.operand;
1167         printLocationAndOp(out, location, it, "jmp");
1168         out.printf("%d(->%d)", offset, location + offset);
1169         break;
1170     }
1171     case op_jtrue: {
1172         printConditionalJump(out, begin, it, location, "jtrue");
1173         break;
1174     }
1175     case op_jfalse: {
1176         printConditionalJump(out, begin, it, location, "jfalse");
1177         break;
1178     }
1179     case op_jeq_null: {
1180         printConditionalJump(out, begin, it, location, "jeq_null");
1181         break;
1182     }
1183     case op_jneq_null: {
1184         printConditionalJump(out, begin, it, location, "jneq_null");
1185         break;
1186     }
1187     case op_jneq_ptr: {
1188         int r0 = (++it)->u.operand;
1189         Special::Pointer pointer = getSpecialPointer(*(++it));
1190         int offset = (++it)->u.operand;
1191         printLocationAndOp(out, location, it, "jneq_ptr");
1192         out.printf("%s, %d (%p), %d(->%d)", registerName(r0).data(), pointer, actualPointerFor(pointer), offset, location + offset);
1193         ++it;
1194         break;
1195     }
1196     case op_jless: {
1197         int r0 = (++it)->u.operand;
1198         int r1 = (++it)->u.operand;
1199         int offset = (++it)->u.operand;
1200         printLocationAndOp(out, location, it, "jless");
1201         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1202         break;
1203     }
1204     case op_jlesseq: {
1205         int r0 = (++it)->u.operand;
1206         int r1 = (++it)->u.operand;
1207         int offset = (++it)->u.operand;
1208         printLocationAndOp(out, location, it, "jlesseq");
1209         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1210         break;
1211     }
1212     case op_jgreater: {
1213         int r0 = (++it)->u.operand;
1214         int r1 = (++it)->u.operand;
1215         int offset = (++it)->u.operand;
1216         printLocationAndOp(out, location, it, "jgreater");
1217         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1218         break;
1219     }
1220     case op_jgreatereq: {
1221         int r0 = (++it)->u.operand;
1222         int r1 = (++it)->u.operand;
1223         int offset = (++it)->u.operand;
1224         printLocationAndOp(out, location, it, "jgreatereq");
1225         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1226         break;
1227     }
1228     case op_jnless: {
1229         int r0 = (++it)->u.operand;
1230         int r1 = (++it)->u.operand;
1231         int offset = (++it)->u.operand;
1232         printLocationAndOp(out, location, it, "jnless");
1233         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1234         break;
1235     }
1236     case op_jnlesseq: {
1237         int r0 = (++it)->u.operand;
1238         int r1 = (++it)->u.operand;
1239         int offset = (++it)->u.operand;
1240         printLocationAndOp(out, location, it, "jnlesseq");
1241         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1242         break;
1243     }
1244     case op_jngreater: {
1245         int r0 = (++it)->u.operand;
1246         int r1 = (++it)->u.operand;
1247         int offset = (++it)->u.operand;
1248         printLocationAndOp(out, location, it, "jngreater");
1249         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1250         break;
1251     }
1252     case op_jngreatereq: {
1253         int r0 = (++it)->u.operand;
1254         int r1 = (++it)->u.operand;
1255         int offset = (++it)->u.operand;
1256         printLocationAndOp(out, location, it, "jngreatereq");
1257         out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
1258         break;
1259     }
1260     case op_loop_hint: {
1261         printLocationAndOp(out, location, it, "loop_hint");
1262         break;
1263     }
1264     case op_check_traps: {
1265         printLocationAndOp(out, location, it, "check_traps");
1266         break;
1267     }
1268     case op_log_shadow_chicken_prologue: {
1269         int r0 = (++it)->u.operand;
1270         printLocationAndOp(out, location, it, "log_shadow_chicken_prologue");
1271         out.printf("%s", registerName(r0).data());
1272         break;
1273     }
1274     case op_log_shadow_chicken_tail: {
1275         int r0 = (++it)->u.operand;
1276         int r1 = (++it)->u.operand;
1277         printLocationAndOp(out, location, it, "log_shadow_chicken_tail");
1278         out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
1279         break;
1280     }
1281     case op_switch_imm: {
1282         int tableIndex = (++it)->u.operand;
1283         int defaultTarget = (++it)->u.operand;
1284         int scrutineeRegister = (++it)->u.operand;
1285         printLocationAndOp(out, location, it, "switch_imm");
1286         out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
1287         break;
1288     }
1289     case op_switch_char: {
1290         int tableIndex = (++it)->u.operand;
1291         int defaultTarget = (++it)->u.operand;
1292         int scrutineeRegister = (++it)->u.operand;
1293         printLocationAndOp(out, location, it, "switch_char");
1294         out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
1295         break;
1296     }
1297     case op_switch_string: {
1298         int tableIndex = (++it)->u.operand;
1299         int defaultTarget = (++it)->u.operand;
1300         int scrutineeRegister = (++it)->u.operand;
1301         printLocationAndOp(out, location, it, "switch_string");
1302         out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
1303         break;
1304     }
1305     case op_new_func: {
1306         int r0 = (++it)->u.operand;
1307         int r1 = (++it)->u.operand;
1308         int f0 = (++it)->u.operand;
1309         printLocationAndOp(out, location, it, "new_func");
1310         out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
1311         break;
1312     }
1313     case op_new_generator_func: {
1314         int r0 = (++it)->u.operand;
1315         int r1 = (++it)->u.operand;
1316         int f0 = (++it)->u.operand;
1317         printLocationAndOp(out, location, it, "new_generator_func");
1318         out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
1319         break;
1320     }
1321     case op_new_async_func: {
1322         int r0 = (++it)->u.operand;
1323         int r1 = (++it)->u.operand;
1324         int f0 = (++it)->u.operand;
1325         printLocationAndOp(out, location, it, "new_async_func");
1326         out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
1327         break;
1328     }
1329     case op_new_func_exp: {
1330         int r0 = (++it)->u.operand;
1331         int r1 = (++it)->u.operand;
1332         int f0 = (++it)->u.operand;
1333         printLocationAndOp(out, location, it, "new_func_exp");
1334         out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
1335         break;
1336     }
1337     case op_new_generator_func_exp: {
1338         int r0 = (++it)->u.operand;
1339         int r1 = (++it)->u.operand;
1340         int f0 = (++it)->u.operand;
1341         printLocationAndOp(out, location, it, "new_generator_func_exp");
1342         out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
1343         break;
1344     }
1345     case op_new_async_func_exp: {
1346         int r0 = (++it)->u.operand;
1347         int r1 = (++it)->u.operand;
1348         int f0 = (++it)->u.operand;
1349         printLocationAndOp(out, location, it, "new_async_func_exp");
1350         out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
1351         break;
1352     }
1353     case op_set_function_name: {
1354         int funcReg = (++it)->u.operand;
1355         int nameReg = (++it)->u.operand;
1356         printLocationAndOp(out, location, it, "set_function_name");
1357         out.printf("%s, %s", registerName(funcReg).data(), registerName(nameReg).data());
1358         break;
1359     }
1360     case op_call: {
1361         printCallOp(out, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos);
1362         break;
1363     }
1364     case op_tail_call: {
1365         printCallOp(out, location, it, "tail_call", DumpCaches, hasPrintedProfiling, callLinkInfos);
1366         break;
1367     }
1368     case op_call_eval: {
1369         printCallOp(out, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, callLinkInfos);
1370         break;
1371     }
1372
1373     case op_construct_varargs:
1374     case op_call_varargs:
1375     case op_tail_call_varargs:
1376     case op_tail_call_forward_arguments: {
1377         int result = (++it)->u.operand;
1378         int callee = (++it)->u.operand;
1379         int thisValue = (++it)->u.operand;
1380         int arguments = (++it)->u.operand;
1381         int firstFreeRegister = (++it)->u.operand;
1382         int varArgOffset = (++it)->u.operand;
1383         ++it;
1384         const char* opName;
1385         if (opcode == op_call_varargs)
1386             opName = "call_varargs";
1387         else if (opcode == op_construct_varargs)
1388             opName = "construct_varargs";
1389         else if (opcode == op_tail_call_varargs)
1390             opName = "tail_call_varargs";
1391         else if (opcode == op_tail_call_forward_arguments)
1392             opName = "tail_call_forward_arguments";
1393         else
1394             RELEASE_ASSERT_NOT_REACHED();
1395
1396         printLocationAndOp(out, location, it, opName);
1397         out.printf("%s, %s, %s, %s, %d, %d", registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset);
1398         dumpValueProfiling(out, it, hasPrintedProfiling);
1399         break;
1400     }
1401
1402     case op_ret: {
1403         int r0 = (++it)->u.operand;
1404         printLocationOpAndRegisterOperand(out, location, it, "ret", r0);
1405         break;
1406     }
1407     case op_construct: {
1408         printCallOp(out, location, it, "construct", DumpCaches, hasPrintedProfiling, callLinkInfos);
1409         break;
1410     }
1411     case op_strcat: {
1412         int r0 = (++it)->u.operand;
1413         int r1 = (++it)->u.operand;
1414         int count = (++it)->u.operand;
1415         printLocationAndOp(out, location, it, "strcat");
1416         out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), count);
1417         break;
1418     }
1419     case op_to_primitive: {
1420         int r0 = (++it)->u.operand;
1421         int r1 = (++it)->u.operand;
1422         printLocationAndOp(out, location, it, "to_primitive");
1423         out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
1424         break;
1425     }
1426     case op_get_enumerable_length: {
1427         int dst = it[1].u.operand;
1428         int base = it[2].u.operand;
1429         printLocationAndOp(out, location, it, "op_get_enumerable_length");
1430         out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
1431         it += OPCODE_LENGTH(op_get_enumerable_length) - 1;
1432         break;
1433     }
1434     case op_has_indexed_property: {
1435         int dst = (++it)->u.operand;
1436         int base = (++it)->u.operand;
1437         int propertyName = (++it)->u.operand;
1438         printLocationAndOp(out, location, it, "op_has_indexed_property");
1439         out.printf("%s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data());
1440         dumpArrayProfiling(out, it, hasPrintedProfiling);
1441         break;
1442     }
1443     case op_has_structure_property: {
1444         int dst = it[1].u.operand;
1445         int base = it[2].u.operand;
1446         int propertyName = it[3].u.operand;
1447         int enumerator = it[4].u.operand;
1448         printLocationAndOp(out, location, it, "op_has_structure_property");
1449         out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(enumerator).data());
1450         it += OPCODE_LENGTH(op_has_structure_property) - 1;
1451         break;
1452     }
1453     case op_has_generic_property: {
1454         int dst = it[1].u.operand;
1455         int base = it[2].u.operand;
1456         int propertyName = it[3].u.operand;
1457         printLocationAndOp(out, location, it, "op_has_generic_property");
1458         out.printf("%s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data());
1459         it += OPCODE_LENGTH(op_has_generic_property) - 1;
1460         break;
1461     }
1462     case op_get_direct_pname: {
1463         int dst = (++it)->u.operand;
1464         int base = (++it)->u.operand;
1465         int propertyName = (++it)->u.operand;
1466         int index = (++it)->u.operand;
1467         int enumerator = (++it)->u.operand;
1468         printLocationAndOp(out, location, it, "op_get_direct_pname");
1469         out.printf("%s, %s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(index).data(), registerName(enumerator).data());
1470         dumpValueProfiling(out, it, hasPrintedProfiling);
1471         break;
1472
1473     }
1474     case op_get_property_enumerator: {
1475         int dst = it[1].u.operand;
1476         int base = it[2].u.operand;
1477         printLocationAndOp(out, location, it, "op_get_property_enumerator");
1478         out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
1479         it += OPCODE_LENGTH(op_get_property_enumerator) - 1;
1480         break;
1481     }
1482     case op_enumerator_structure_pname: {
1483         int dst = it[1].u.operand;
1484         int enumerator = it[2].u.operand;
1485         int index = it[3].u.operand;
1486         printLocationAndOp(out, location, it, "op_enumerator_structure_pname");
1487         out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
1488         it += OPCODE_LENGTH(op_enumerator_structure_pname) - 1;
1489         break;
1490     }
1491     case op_enumerator_generic_pname: {
1492         int dst = it[1].u.operand;
1493         int enumerator = it[2].u.operand;
1494         int index = it[3].u.operand;
1495         printLocationAndOp(out, location, it, "op_enumerator_generic_pname");
1496         out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
1497         it += OPCODE_LENGTH(op_enumerator_generic_pname) - 1;
1498         break;
1499     }
1500     case op_to_index_string: {
1501         int dst = it[1].u.operand;
1502         int index = it[2].u.operand;
1503         printLocationAndOp(out, location, it, "op_to_index_string");
1504         out.printf("%s, %s", registerName(dst).data(), registerName(index).data());
1505         it += OPCODE_LENGTH(op_to_index_string) - 1;
1506         break;
1507     }
1508     case op_push_with_scope: {
1509         int dst = (++it)->u.operand;
1510         int newScope = (++it)->u.operand;
1511         int currentScope = (++it)->u.operand;
1512         printLocationAndOp(out, location, it, "push_with_scope");
1513         out.printf("%s, %s, %s", registerName(dst).data(), registerName(newScope).data(), registerName(currentScope).data());
1514         break;
1515     }
1516     case op_get_parent_scope: {
1517         int dst = (++it)->u.operand;
1518         int parentScope = (++it)->u.operand;
1519         printLocationAndOp(out, location, it, "get_parent_scope");
1520         out.printf("%s, %s", registerName(dst).data(), registerName(parentScope).data());
1521         break;
1522     }
1523     case op_create_lexical_environment: {
1524         int dst = (++it)->u.operand;
1525         int scope = (++it)->u.operand;
1526         int symbolTable = (++it)->u.operand;
1527         int initialValue = (++it)->u.operand;
1528         printLocationAndOp(out, location, it, "create_lexical_environment");
1529         out.printf("%s, %s, %s, %s",
1530             registerName(dst).data(), registerName(scope).data(), registerName(symbolTable).data(), registerName(initialValue).data());
1531         break;
1532     }
1533     case op_catch: {
1534         int r0 = (++it)->u.operand;
1535         int r1 = (++it)->u.operand;
1536         printLocationAndOp(out, location, it, "catch");
1537         out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
1538         break;
1539     }
1540     case op_throw: {
1541         int r0 = (++it)->u.operand;
1542         printLocationOpAndRegisterOperand(out, location, it, "throw", r0);
1543         break;
1544     }
1545     case op_throw_static_error: {
1546         int k0 = (++it)->u.operand;
1547         ErrorType k1 = static_cast<ErrorType>((++it)->u.unsignedValue);
1548         printLocationAndOp(out, location, it, "throw_static_error");
1549         out.printf("%s, ", constantName(k0).data());
1550         out.print(k1);
1551         break;
1552     }
1553     case op_debug: {
1554         int debugHookType = (++it)->u.operand;
1555         int hasBreakpointFlag = (++it)->u.operand;
1556         printLocationAndOp(out, location, it, "debug");
1557         out.printf("%s, %d", debugHookName(debugHookType), hasBreakpointFlag);
1558         break;
1559     }
1560     case op_assert: {
1561         int condition = (++it)->u.operand;
1562         int line = (++it)->u.operand;
1563         printLocationAndOp(out, location, it, "assert");
1564         out.printf("%s, %d", registerName(condition).data(), line);
1565         break;
1566     }
1567     case op_end: {
1568         int r0 = (++it)->u.operand;
1569         printLocationOpAndRegisterOperand(out, location, it, "end", r0);
1570         break;
1571     }
1572     case op_resolve_scope_for_hoisting_func_decl_in_eval: {
1573         int r0 = (++it)->u.operand;
1574         int scope = (++it)->u.operand;
1575         int id0 = (++it)->u.operand;
1576         printLocationAndOp(out, location, it, "resolve_scope_for_hoisting_func_decl_in_eval");
1577         out.printf("%s, %s, %s", registerName(r0).data(), registerName(scope).data(), idName(id0, identifier(id0)).data());
1578         break;
1579     }
1580     case op_resolve_scope: {
1581         int r0 = (++it)->u.operand;
1582         int scope = (++it)->u.operand;
1583         int id0 = (++it)->u.operand;
1584         ResolveType resolveType = static_cast<ResolveType>((++it)->u.operand);
1585         int depth = (++it)->u.operand;
1586         void* pointer = getPointer(*(++it));
1587         printLocationAndOp(out, location, it, "resolve_scope");
1588         out.printf("%s, %s, %s, <%s>, %d, %p", registerName(r0).data(), registerName(scope).data(), idName(id0, identifier(id0)).data(), resolveTypeName(resolveType), depth, pointer);
1589         break;
1590     }
1591     case op_get_from_scope: {
1592         int r0 = (++it)->u.operand;
1593         int r1 = (++it)->u.operand;
1594         int id0 = (++it)->u.operand;
1595         GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
1596         ++it; // Structure
1597         int operand = (++it)->u.operand; // Operand
1598         printLocationAndOp(out, location, it, "get_from_scope");
1599         out.print(registerName(r0), ", ", registerName(r1));
1600         if (static_cast<unsigned>(id0) == UINT_MAX)
1601             out.print(", anonymous");
1602         else
1603             out.print(", ", idName(id0, identifier(id0)));
1604         out.print(", ", getPutInfo.operand(), "<", resolveModeName(getPutInfo.resolveMode()), "|", resolveTypeName(getPutInfo.resolveType()), "|", initializationModeName(getPutInfo.initializationMode()), ">, ", operand);
1605         dumpValueProfiling(out, it, hasPrintedProfiling);
1606         break;
1607     }
1608     case op_put_to_scope: {
1609         int r0 = (++it)->u.operand;
1610         int id0 = (++it)->u.operand;
1611         int r1 = (++it)->u.operand;
1612         GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
1613         ++it; // Structure
1614         int operand = (++it)->u.operand; // Operand
1615         printLocationAndOp(out, location, it, "put_to_scope");
1616         out.print(registerName(r0));
1617         if (static_cast<unsigned>(id0) == UINT_MAX)
1618             out.print(", anonymous");
1619         else
1620             out.print(", ", idName(id0, identifier(id0)));
1621         out.print(", ", registerName(r1), ", ", getPutInfo.operand(), "<", resolveModeName(getPutInfo.resolveMode()), "|", resolveTypeName(getPutInfo.resolveType()), "|", initializationModeName(getPutInfo.initializationMode()), ">, <structure>, ", operand);
1622         break;
1623     }
1624     case op_get_from_arguments: {
1625         int r0 = (++it)->u.operand;
1626         int r1 = (++it)->u.operand;
1627         int offset = (++it)->u.operand;
1628         printLocationAndOp(out, location, it, "get_from_arguments");
1629         out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), offset);
1630         dumpValueProfiling(out, it, hasPrintedProfiling);
1631         break;
1632     }
1633     case op_put_to_arguments: {
1634         int r0 = (++it)->u.operand;
1635         int offset = (++it)->u.operand;
1636         int r1 = (++it)->u.operand;
1637         printLocationAndOp(out, location, it, "put_to_arguments");
1638         out.printf("%s, %d, %s", registerName(r0).data(), offset, registerName(r1).data());
1639         break;
1640     }
1641     case op_yield: {
1642         int r0 = (++it)->u.operand;
1643         unsigned yieldPoint = (++it)->u.unsignedValue;
1644         int r1 = (++it)->u.operand;
1645         printLocationAndOp(out, location, it, "yield");
1646         out.printf("%s, %u, %s", registerName(r0).data(), yieldPoint, registerName(r1).data());
1647         break;
1648     }
1649     default:
1650         RELEASE_ASSERT_NOT_REACHED();
1651     }
1652     dumpProfilesForBytecodeOffset(out, location, hasPrintedProfiling);
1653     out.print("\n");
1654 }
1655
1656 template<class Block>
1657 void BytecodeDumper<Block>::dumpBytecode(Block* block, PrintStream& out, const typename Block::Instruction* begin, const typename Block::Instruction*& it, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
1658 {
1659     BytecodeDumper dumper(block, begin);
1660     dumper.dumpBytecode(out, begin, it, stubInfos, callLinkInfos);
1661 }
1662
1663 template<class Block>
1664 void BytecodeDumper<Block>::dumpIdentifiers(PrintStream& out)
1665 {
1666     if (size_t count = block()->numberOfIdentifiers()) {
1667         out.printf("\nIdentifiers:\n");
1668         size_t i = 0;
1669         do {
1670             out.printf("  id%u = %s\n", static_cast<unsigned>(i), identifier(i).string().utf8().data());
1671             ++i;
1672         } while (i != count);
1673     }
1674 }
1675
1676 template<class Block>
1677 void BytecodeDumper<Block>::dumpConstants(PrintStream& out)
1678 {
1679     if (!block()->constantRegisters().isEmpty()) {
1680         out.printf("\nConstants:\n");
1681         size_t i = 0;
1682         for (const auto& constant : block()->constantRegisters()) {
1683             const char* sourceCodeRepresentationDescription = nullptr;
1684             switch (block()->constantsSourceCodeRepresentation()[i]) {
1685             case SourceCodeRepresentation::Double:
1686                 sourceCodeRepresentationDescription = ": in source as double";
1687                 break;
1688             case SourceCodeRepresentation::Integer:
1689                 sourceCodeRepresentationDescription = ": in source as integer";
1690                 break;
1691             case SourceCodeRepresentation::Other:
1692                 sourceCodeRepresentationDescription = "";
1693                 break;
1694             }
1695             out.printf("   k%u = %s%s\n", static_cast<unsigned>(i), toCString(constant.get()).data(), sourceCodeRepresentationDescription);
1696             ++i;
1697         }
1698     }
1699 }
1700
1701 template<class Block>
1702 void BytecodeDumper<Block>::dumpRegExps(PrintStream& out)
1703 {
1704     if (size_t count = block()->numberOfRegExps()) {
1705         out.printf("\nm_regexps:\n");
1706         size_t i = 0;
1707         do {
1708             out.printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(block()->regexp(i)).data());
1709             ++i;
1710         } while (i < count);
1711     }
1712 }
1713
1714 template<class Block>
1715 void BytecodeDumper<Block>::dumpExceptionHandlers(PrintStream& out)
1716 {
1717     if (unsigned count = block()->numberOfExceptionHandlers()) {
1718         out.printf("\nException Handlers:\n");
1719         unsigned i = 0;
1720         do {
1721             const auto& handler = block()->exceptionHandler(i);
1722             out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] } %s\n", i + 1, handler.start, handler.end, handler.target, handler.typeName());
1723             ++i;
1724         } while (i < count);
1725     }
1726 }
1727
1728 template<class Block>
1729 void BytecodeDumper<Block>::dumpSwitchJumpTables(PrintStream& out)
1730 {
1731     if (unsigned count = block()->numberOfSwitchJumpTables()) {
1732         out.printf("Switch Jump Tables:\n");
1733         unsigned i = 0;
1734         do {
1735             out.printf("  %1d = {\n", i);
1736             const auto& switchJumpTable = block()->switchJumpTable(i);
1737             int entry = 0;
1738             auto end = switchJumpTable.branchOffsets.end();
1739             for (auto iter = switchJumpTable.branchOffsets.begin(); iter != end; ++iter, ++entry) {
1740                 if (!*iter)
1741                     continue;
1742                 out.printf("\t\t%4d => %04d\n", entry + switchJumpTable.min, *iter);
1743             }
1744             out.printf("      }\n");
1745             ++i;
1746         } while (i < count);
1747     }
1748 }
1749
1750 template<class Block>
1751 void BytecodeDumper<Block>::dumpStringSwitchJumpTables(PrintStream& out)
1752 {
1753     if (unsigned count = block()->numberOfStringSwitchJumpTables()) {
1754         out.printf("\nString Switch Jump Tables:\n");
1755         unsigned i = 0;
1756         do {
1757             out.printf("  %1d = {\n", i);
1758             const auto& stringSwitchJumpTable = block()->stringSwitchJumpTable(i);
1759             auto end = stringSwitchJumpTable.offsetTable.end();
1760             for (auto iter = stringSwitchJumpTable.offsetTable.begin(); iter != end; ++iter)
1761                 out.printf("\t\t\"%s\" => %04d\n", iter->key->utf8().data(), iter->value.branchOffset);
1762             out.printf("      }\n");
1763             ++i;
1764         } while (i < count);
1765     }
1766 }
1767
1768 template<class Block>
1769 void BytecodeDumper<Block>::dumpBlock(Block* block, const typename Block::UnpackedInstructions& instructions, PrintStream& out, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
1770 {
1771     VM& vm = *block->vm();
1772     size_t instructionCount = 0;
1773
1774     for (size_t i = 0; i < instructions.size(); i += opcodeLengths[vm.interpreter->getOpcodeID(instructions[i])])
1775         ++instructionCount;
1776
1777     out.print(*block);
1778     out.printf(
1779         ": %lu m_instructions; %lu bytes; %d parameter(s); %d callee register(s); %d variable(s)",
1780         static_cast<unsigned long>(instructions.size()),
1781         static_cast<unsigned long>(instructions.size() * sizeof(Instruction)),
1782         block->numParameters(), block->numCalleeLocals(), block->m_numVars);
1783     out.print("; scope at ", block->scopeRegister());
1784     out.printf("\n");
1785
1786     const auto* begin = instructions.begin();
1787     const auto* end = instructions.end();
1788     BytecodeDumper<Block> dumper(block, begin);
1789     for (const auto* it = begin; it != end; ++it)
1790         dumper.dumpBytecode(out, begin, it, stubInfos, callLinkInfos);
1791
1792     dumper.dumpIdentifiers(out);
1793     dumper.dumpConstants(out);
1794     dumper.dumpRegExps(out);
1795     dumper.dumpExceptionHandlers(out);
1796     dumper.dumpSwitchJumpTables(out);
1797     dumper.dumpStringSwitchJumpTables(out);
1798
1799     out.printf("\n");
1800 }
1801
1802 template class BytecodeDumper<UnlinkedCodeBlock>;
1803 template class BytecodeDumper<CodeBlock>;
1804
1805 }