Roll out r108309, r108323, and r108326
[WebKit-https.git] / Source / JavaScriptCore / bytecode / CodeBlock.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
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  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "CodeBlock.h"
32
33 #include "BytecodeGenerator.h"
34 #include "DFGCapabilities.h"
35 #include "DFGNode.h"
36 #include "DFGRepatch.h"
37 #include "Debugger.h"
38 #include "Interpreter.h"
39 #include "JIT.h"
40 #include "JITStubs.h"
41 #include "JSActivation.h"
42 #include "JSFunction.h"
43 #include "JSStaticScopeObject.h"
44 #include "JSValue.h"
45 #include "RepatchBuffer.h"
46 #include "UStringConcatenate.h"
47 #include <stdio.h>
48 #include <wtf/StringExtras.h>
49
50 #if ENABLE(DFG_JIT)
51 #include "DFGOperations.h"
52 #endif
53
54 #define DUMP_CODE_BLOCK_STATISTICS 0
55
56 namespace JSC {
57
58 #if ENABLE(DFG_JIT)
59 using namespace DFG;
60 #endif
61
62 static UString escapeQuotes(const UString& str)
63 {
64     UString result = str;
65     size_t pos = 0;
66     while ((pos = result.find('\"', pos)) != notFound) {
67         result = makeUString(result.substringSharingImpl(0, pos), "\"\\\"\"", result.substringSharingImpl(pos + 1));
68         pos += 4;
69     }
70     return result;
71 }
72
73 static UString valueToSourceString(ExecState* exec, JSValue val)
74 {
75     if (!val)
76         return "0";
77
78     if (val.isString())
79         return makeUString("\"", escapeQuotes(val.toString(exec)->value(exec)), "\"");
80
81     return val.description();
82 }
83
84 static CString constantName(ExecState* exec, int k, JSValue value)
85 {
86     return makeUString(valueToSourceString(exec, value), "(@k", UString::number(k - FirstConstantRegisterIndex), ")").utf8();
87 }
88
89 static CString idName(int id0, const Identifier& ident)
90 {
91     return makeUString(ident.ustring(), "(@id", UString::number(id0), ")").utf8();
92 }
93
94 CString CodeBlock::registerName(ExecState* exec, int r) const
95 {
96     if (r == missingThisObjectMarker())
97         return "<null>";
98
99     if (isConstantRegisterIndex(r))
100         return constantName(exec, r, getConstant(r));
101
102     return makeUString("r", UString::number(r)).utf8();
103 }
104
105 static UString regexpToSourceString(RegExp* regExp)
106 {
107     char postfix[5] = { '/', 0, 0, 0, 0 };
108     int index = 1;
109     if (regExp->global())
110         postfix[index++] = 'g';
111     if (regExp->ignoreCase())
112         postfix[index++] = 'i';
113     if (regExp->multiline())
114         postfix[index] = 'm';
115
116     return makeUString("/", regExp->pattern(), postfix);
117 }
118
119 static CString regexpName(int re, RegExp* regexp)
120 {
121     return makeUString(regexpToSourceString(regexp), "(@re", UString::number(re), ")").utf8();
122 }
123
124 static UString pointerToSourceString(void* p)
125 {
126     char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
127     snprintf(buffer, sizeof(buffer), "%p", p);
128     return buffer;
129 }
130
131 NEVER_INLINE static const char* debugHookName(int debugHookID)
132 {
133     switch (static_cast<DebugHookID>(debugHookID)) {
134         case DidEnterCallFrame:
135             return "didEnterCallFrame";
136         case WillLeaveCallFrame:
137             return "willLeaveCallFrame";
138         case WillExecuteStatement:
139             return "willExecuteStatement";
140         case WillExecuteProgram:
141             return "willExecuteProgram";
142         case DidExecuteProgram:
143             return "didExecuteProgram";
144         case DidReachBreakpoint:
145             return "didReachBreakpoint";
146     }
147
148     ASSERT_NOT_REACHED();
149     return "";
150 }
151
152 void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
153 {
154     int r0 = (++it)->u.operand;
155     int r1 = (++it)->u.operand;
156
157     dataLog("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data());
158 }
159
160 void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
161 {
162     int r0 = (++it)->u.operand;
163     int r1 = (++it)->u.operand;
164     int r2 = (++it)->u.operand;
165     dataLog("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
166 }
167
168 void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) const
169 {
170     int r0 = (++it)->u.operand;
171     int offset = (++it)->u.operand;
172     dataLog("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset);
173 }
174
175 void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
176 {
177     int r0 = (++it)->u.operand;
178     int r1 = (++it)->u.operand;
179     int id0 = (++it)->u.operand;
180     dataLog("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
181     it += 5;
182 }
183
184 void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
185 {
186     int func = (++it)->u.operand;
187     int argCount = (++it)->u.operand;
188     int registerOffset = (++it)->u.operand;
189     dataLog("[%4d] %s\t %s, %d, %d\n", location, op, registerName(exec, func).data(), argCount, registerOffset);
190     it += 2;
191 }
192
193 void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
194 {
195     int r0 = (++it)->u.operand;
196     int id0 = (++it)->u.operand;
197     int r1 = (++it)->u.operand;
198     dataLog("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
199     it += 5;
200 }
201
202 #if ENABLE(JIT)
203 static bool isGlobalResolve(OpcodeID opcodeID)
204 {
205     return opcodeID == op_resolve_global || opcodeID == op_resolve_global_dynamic;
206 }
207
208 static bool isPropertyAccess(OpcodeID opcodeID)
209 {
210     switch (opcodeID) {
211         case op_get_by_id_self:
212         case op_get_by_id_proto:
213         case op_get_by_id_chain:
214         case op_put_by_id_transition:
215         case op_put_by_id_replace:
216         case op_get_by_id:
217         case op_put_by_id:
218         case op_get_by_id_generic:
219         case op_put_by_id_generic:
220         case op_get_array_length:
221         case op_get_string_length:
222             return true;
223         default:
224             return false;
225     }
226 }
227
228 static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
229 {
230     size_t i = 0;
231     while (i < instructions.size()) {
232         OpcodeID currentOpcode = exec->interpreter()->getOpcodeID(instructions[i].u.opcode);
233         if (predicate(currentOpcode)) {
234             if (!--nth)
235                 return i;
236         }
237         i += opcodeLengths[currentOpcode];
238     }
239
240     ASSERT_NOT_REACHED();
241     return 0;
242 }
243
244 static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
245 {
246     dataLog("  [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).utf8().data());
247 }
248
249 static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
250 {
251     switch (stubInfo.accessType) {
252     case access_get_by_id_self:
253         dataLog("  [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).utf8().data());
254         return;
255     case access_get_by_id_proto:
256         dataLog("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).utf8().data(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).utf8().data());
257         return;
258     case access_get_by_id_chain:
259         dataLog("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).utf8().data(), pointerToSourceString(stubInfo.u.getByIdChain.chain).utf8().data());
260         return;
261     case access_get_by_id_self_list:
262         dataLog("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).utf8().data(), stubInfo.u.getByIdSelfList.listSize);
263         return;
264     case access_get_by_id_proto_list:
265         dataLog("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).utf8().data(), stubInfo.u.getByIdProtoList.listSize);
266         return;
267     case access_put_by_id_transition_normal:
268     case access_put_by_id_transition_direct:
269         dataLog("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).utf8().data(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).utf8().data(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).utf8().data());
270         return;
271     case access_put_by_id_replace:
272         dataLog("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).utf8().data());
273         return;
274     case access_unset:
275         dataLog("  [%4d] %s\n", instructionOffset, "unset");
276         return;
277     case access_get_by_id_generic:
278         dataLog("  [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
279         return;
280     case access_put_by_id_generic:
281         dataLog("  [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
282         return;
283     case access_get_array_length:
284         dataLog("  [%4d] %s\n", instructionOffset, "op_get_array_length");
285         return;
286     case access_get_string_length:
287         dataLog("  [%4d] %s\n", instructionOffset, "op_get_string_length");
288         return;
289     default:
290         ASSERT_NOT_REACHED();
291     }
292 }
293 #endif
294
295 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
296 {
297     unsigned instructionOffset = vPC - instructions().begin();
298     dataLog("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data());
299 }
300
301 void CodeBlock::printStructures(const Instruction* vPC) const
302 {
303     Interpreter* interpreter = m_globalData->interpreter;
304     unsigned instructionOffset = vPC - instructions().begin();
305
306     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
307         printStructure("get_by_id", vPC, 4);
308         return;
309     }
310     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
311         printStructure("get_by_id_self", vPC, 4);
312         return;
313     }
314     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
315         dataLog("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data());
316         return;
317     }
318     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
319         dataLog("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data(), pointerToSourceString(vPC[6].u.structureChain).utf8().data());
320         return;
321     }
322     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
323         dataLog("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structureChain).utf8().data());
324         return;
325     }
326     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
327         printStructure("put_by_id", vPC, 4);
328         return;
329     }
330     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
331         printStructure("put_by_id_replace", vPC, 4);
332         return;
333     }
334     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
335         printStructure("resolve_global", vPC, 4);
336         return;
337     }
338     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) {
339         printStructure("resolve_global_dynamic", vPC, 4);
340         return;
341     }
342
343     // These m_instructions doesn't ref Structures.
344     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct));
345 }
346
347 void CodeBlock::dump(ExecState* exec) const
348 {
349     if (!m_instructions) {
350         dataLog("No instructions available.\n");
351         return;
352     }
353
354     size_t instructionCount = 0;
355
356     for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
357         ++instructionCount;
358
359     dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
360         static_cast<unsigned long>(instructionCount),
361         static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
362         this, m_numParameters, m_numCalleeRegisters);
363
364     Vector<Instruction>::const_iterator begin = instructions().begin();
365     Vector<Instruction>::const_iterator end = instructions().end();
366     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
367         dump(exec, begin, it);
368
369     if (!m_identifiers.isEmpty()) {
370         dataLog("\nIdentifiers:\n");
371         size_t i = 0;
372         do {
373             dataLog("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ustring().utf8().data());
374             ++i;
375         } while (i != m_identifiers.size());
376     }
377
378     if (!m_constantRegisters.isEmpty()) {
379         dataLog("\nConstants:\n");
380         size_t i = 0;
381         do {
382             dataLog("   k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data());
383             ++i;
384         } while (i < m_constantRegisters.size());
385     }
386
387     if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
388         dataLog("\nm_regexps:\n");
389         size_t i = 0;
390         do {
391             dataLog("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).utf8().data());
392             ++i;
393         } while (i < m_rareData->m_regexps.size());
394     }
395
396 #if ENABLE(JIT)
397     if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
398         dataLog("\nStructures:\n");
399
400     if (!m_globalResolveInfos.isEmpty()) {
401         size_t i = 0;
402         do {
403              printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isGlobalResolve));
404              ++i;
405         } while (i < m_globalResolveInfos.size());
406     }
407     if (!m_structureStubInfos.isEmpty()) {
408         size_t i = 0;
409         do {
410             printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isPropertyAccess));
411              ++i;
412         } while (i < m_structureStubInfos.size());
413     }
414 #endif
415 #if ENABLE(CLASSIC_INTERPRETER)
416     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
417         dataLog("\nStructures:\n");
418
419     if (!m_globalResolveInstructions.isEmpty()) {
420         size_t i = 0;
421         do {
422              printStructures(&instructions()[m_globalResolveInstructions[i]]);
423              ++i;
424         } while (i < m_globalResolveInstructions.size());
425     }
426     if (!m_propertyAccessInstructions.isEmpty()) {
427         size_t i = 0;
428         do {
429             printStructures(&instructions()[m_propertyAccessInstructions[i]]);
430              ++i;
431         } while (i < m_propertyAccessInstructions.size());
432     }
433 #endif
434
435     if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
436         dataLog("\nException Handlers:\n");
437         unsigned i = 0;
438         do {
439             dataLog("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target);
440             ++i;
441         } while (i < m_rareData->m_exceptionHandlers.size());
442     }
443     
444     if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
445         dataLog("Immediate Switch Jump Tables:\n");
446         unsigned i = 0;
447         do {
448             dataLog("  %1d = {\n", i);
449             int entry = 0;
450             Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
451             for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
452                 if (!*iter)
453                     continue;
454                 dataLog("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
455             }
456             dataLog("      }\n");
457             ++i;
458         } while (i < m_rareData->m_immediateSwitchJumpTables.size());
459     }
460     
461     if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
462         dataLog("\nCharacter Switch Jump Tables:\n");
463         unsigned i = 0;
464         do {
465             dataLog("  %1d = {\n", i);
466             int entry = 0;
467             Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
468             for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
469                 if (!*iter)
470                     continue;
471                 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
472                 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
473                 dataLog("\t\t\"%s\" => %04d\n", UString(&ch, 1).utf8().data(), *iter);
474         }
475             dataLog("      }\n");
476             ++i;
477         } while (i < m_rareData->m_characterSwitchJumpTables.size());
478     }
479     
480     if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
481         dataLog("\nString Switch Jump Tables:\n");
482         unsigned i = 0;
483         do {
484             dataLog("  %1d = {\n", i);
485             StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
486             for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
487                 dataLog("\t\t\"%s\" => %04d\n", UString(iter->first).utf8().data(), iter->second.branchOffset);
488             dataLog("      }\n");
489             ++i;
490         } while (i < m_rareData->m_stringSwitchJumpTables.size());
491     }
492
493     dataLog("\n");
494 }
495
496 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
497 {
498     int location = it - begin;
499     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
500         case op_enter: {
501             dataLog("[%4d] enter\n", location);
502             break;
503         }
504         case op_create_activation: {
505             int r0 = (++it)->u.operand;
506             dataLog("[%4d] create_activation %s\n", location, registerName(exec, r0).data());
507             break;
508         }
509         case op_create_arguments: {
510             int r0 = (++it)->u.operand;
511             dataLog("[%4d] create_arguments\t %s\n", location, registerName(exec, r0).data());
512             break;
513         }
514         case op_init_lazy_reg: {
515             int r0 = (++it)->u.operand;
516             dataLog("[%4d] init_lazy_reg\t %s\n", location, registerName(exec, r0).data());
517             break;
518         }
519         case op_get_callee: {
520             int r0 = (++it)->u.operand;
521             dataLog("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data());
522             break;
523         }
524         case op_create_this: {
525             int r0 = (++it)->u.operand;
526             int r1 = (++it)->u.operand;
527             dataLog("[%4d] create_this %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
528             break;
529         }
530         case op_convert_this: {
531             int r0 = (++it)->u.operand;
532             dataLog("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data());
533             break;
534         }
535         case op_new_object: {
536             int r0 = (++it)->u.operand;
537             dataLog("[%4d] new_object\t %s\n", location, registerName(exec, r0).data());
538             break;
539         }
540         case op_new_array: {
541             int dst = (++it)->u.operand;
542             int argv = (++it)->u.operand;
543             int argc = (++it)->u.operand;
544             dataLog("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc);
545             break;
546         }
547         case op_new_array_buffer: {
548             int dst = (++it)->u.operand;
549             int argv = (++it)->u.operand;
550             int argc = (++it)->u.operand;
551             dataLog("[%4d] new_array_buffer %s, %d, %d\n", location, registerName(exec, dst).data(), argv, argc);
552             break;
553         }
554         case op_new_regexp: {
555             int r0 = (++it)->u.operand;
556             int re0 = (++it)->u.operand;
557             dataLog("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data());
558             if (r0 >=0 && r0 < (int)numberOfRegExps())
559                 dataLog("%s\n", regexpName(re0, regexp(re0)).data());
560             else
561                 dataLog("bad_regexp(%d)\n", re0);
562             break;
563         }
564         case op_mov: {
565             int r0 = (++it)->u.operand;
566             int r1 = (++it)->u.operand;
567             dataLog("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
568             break;
569         }
570         case op_not: {
571             printUnaryOp(exec, location, it, "not");
572             break;
573         }
574         case op_eq: {
575             printBinaryOp(exec, location, it, "eq");
576             break;
577         }
578         case op_eq_null: {
579             printUnaryOp(exec, location, it, "eq_null");
580             break;
581         }
582         case op_neq: {
583             printBinaryOp(exec, location, it, "neq");
584             break;
585         }
586         case op_neq_null: {
587             printUnaryOp(exec, location, it, "neq_null");
588             break;
589         }
590         case op_stricteq: {
591             printBinaryOp(exec, location, it, "stricteq");
592             break;
593         }
594         case op_nstricteq: {
595             printBinaryOp(exec, location, it, "nstricteq");
596             break;
597         }
598         case op_less: {
599             printBinaryOp(exec, location, it, "less");
600             break;
601         }
602         case op_lesseq: {
603             printBinaryOp(exec, location, it, "lesseq");
604             break;
605         }
606         case op_greater: {
607             printBinaryOp(exec, location, it, "greater");
608             break;
609         }
610         case op_greatereq: {
611             printBinaryOp(exec, location, it, "greatereq");
612             break;
613         }
614         case op_pre_inc: {
615             int r0 = (++it)->u.operand;
616             dataLog("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).data());
617             break;
618         }
619         case op_pre_dec: {
620             int r0 = (++it)->u.operand;
621             dataLog("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).data());
622             break;
623         }
624         case op_post_inc: {
625             printUnaryOp(exec, location, it, "post_inc");
626             break;
627         }
628         case op_post_dec: {
629             printUnaryOp(exec, location, it, "post_dec");
630             break;
631         }
632         case op_to_jsnumber: {
633             printUnaryOp(exec, location, it, "to_jsnumber");
634             break;
635         }
636         case op_negate: {
637             printUnaryOp(exec, location, it, "negate");
638             break;
639         }
640         case op_add: {
641             printBinaryOp(exec, location, it, "add");
642             ++it;
643             break;
644         }
645         case op_mul: {
646             printBinaryOp(exec, location, it, "mul");
647             ++it;
648             break;
649         }
650         case op_div: {
651             printBinaryOp(exec, location, it, "div");
652             ++it;
653             break;
654         }
655         case op_mod: {
656             printBinaryOp(exec, location, it, "mod");
657             break;
658         }
659         case op_sub: {
660             printBinaryOp(exec, location, it, "sub");
661             ++it;
662             break;
663         }
664         case op_lshift: {
665             printBinaryOp(exec, location, it, "lshift");
666             break;            
667         }
668         case op_rshift: {
669             printBinaryOp(exec, location, it, "rshift");
670             break;
671         }
672         case op_urshift: {
673             printBinaryOp(exec, location, it, "urshift");
674             break;
675         }
676         case op_bitand: {
677             printBinaryOp(exec, location, it, "bitand");
678             ++it;
679             break;
680         }
681         case op_bitxor: {
682             printBinaryOp(exec, location, it, "bitxor");
683             ++it;
684             break;
685         }
686         case op_bitor: {
687             printBinaryOp(exec, location, it, "bitor");
688             ++it;
689             break;
690         }
691         case op_bitnot: {
692             printUnaryOp(exec, location, it, "bitnot");
693             break;
694         }
695         case op_check_has_instance: {
696             int base = (++it)->u.operand;
697             dataLog("[%4d] check_has_instance\t\t %s\n", location, registerName(exec, base).data());
698             break;
699         }
700         case op_instanceof: {
701             int r0 = (++it)->u.operand;
702             int r1 = (++it)->u.operand;
703             int r2 = (++it)->u.operand;
704             int r3 = (++it)->u.operand;
705             dataLog("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data());
706             break;
707         }
708         case op_typeof: {
709             printUnaryOp(exec, location, it, "typeof");
710             break;
711         }
712         case op_is_undefined: {
713             printUnaryOp(exec, location, it, "is_undefined");
714             break;
715         }
716         case op_is_boolean: {
717             printUnaryOp(exec, location, it, "is_boolean");
718             break;
719         }
720         case op_is_number: {
721             printUnaryOp(exec, location, it, "is_number");
722             break;
723         }
724         case op_is_string: {
725             printUnaryOp(exec, location, it, "is_string");
726             break;
727         }
728         case op_is_object: {
729             printUnaryOp(exec, location, it, "is_object");
730             break;
731         }
732         case op_is_function: {
733             printUnaryOp(exec, location, it, "is_function");
734             break;
735         }
736         case op_in: {
737             printBinaryOp(exec, location, it, "in");
738             break;
739         }
740         case op_resolve: {
741             int r0 = (++it)->u.operand;
742             int id0 = (++it)->u.operand;
743             dataLog("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
744             it++;
745             break;
746         }
747         case op_resolve_skip: {
748             int r0 = (++it)->u.operand;
749             int id0 = (++it)->u.operand;
750             int skipLevels = (++it)->u.operand;
751             dataLog("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels);
752             it++;
753             break;
754         }
755         case op_resolve_global: {
756             int r0 = (++it)->u.operand;
757             int id0 = (++it)->u.operand;
758             dataLog("[%4d] resolve_global\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
759             it += 3;
760             break;
761         }
762         case op_resolve_global_dynamic: {
763             int r0 = (++it)->u.operand;
764             int id0 = (++it)->u.operand;
765             JSValue scope = JSValue((++it)->u.jsCell.get());
766             ++it;
767             int depth = (++it)->u.operand;
768             dataLog("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth);
769             ++it;
770             break;
771         }
772         case op_get_scoped_var: {
773             int r0 = (++it)->u.operand;
774             int index = (++it)->u.operand;
775             int skipLevels = (++it)->u.operand;
776             dataLog("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels);
777             it++;
778             break;
779         }
780         case op_put_scoped_var: {
781             int index = (++it)->u.operand;
782             int skipLevels = (++it)->u.operand;
783             int r0 = (++it)->u.operand;
784             dataLog("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).data());
785             break;
786         }
787         case op_get_global_var: {
788             int r0 = (++it)->u.operand;
789             int index = (++it)->u.operand;
790             dataLog("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index);
791             it++;
792             break;
793         }
794         case op_put_global_var: {
795             int index = (++it)->u.operand;
796             int r0 = (++it)->u.operand;
797             dataLog("[%4d] put_global_var\t %d, %s\n", location, index, registerName(exec, r0).data());
798             break;
799         }
800         case op_resolve_base: {
801             int r0 = (++it)->u.operand;
802             int id0 = (++it)->u.operand;
803             int isStrict = (++it)->u.operand;
804             dataLog("[%4d] resolve_base%s\t %s, %s\n", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
805             it++;
806             break;
807         }
808         case op_ensure_property_exists: {
809             int r0 = (++it)->u.operand;
810             int id0 = (++it)->u.operand;
811             dataLog("[%4d] ensure_property_exists\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
812             break;
813         }
814         case op_resolve_with_base: {
815             int r0 = (++it)->u.operand;
816             int r1 = (++it)->u.operand;
817             int id0 = (++it)->u.operand;
818             dataLog("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
819             it++;
820             break;
821         }
822         case op_resolve_with_this: {
823             int r0 = (++it)->u.operand;
824             int r1 = (++it)->u.operand;
825             int id0 = (++it)->u.operand;
826             dataLog("[%4d] resolve_with_this %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
827             it++;
828             break;
829         }
830         case op_get_by_id: {
831             printGetByIdOp(exec, location, it, "get_by_id");
832             break;
833         }
834         case op_get_by_id_self: {
835             printGetByIdOp(exec, location, it, "get_by_id_self");
836             break;
837         }
838         case op_get_by_id_proto: {
839             printGetByIdOp(exec, location, it, "get_by_id_proto");
840             break;
841         }
842         case op_get_by_id_chain: {
843             printGetByIdOp(exec, location, it, "get_by_id_chain");
844             break;
845         }
846         case op_get_by_id_getter_self: {
847             printGetByIdOp(exec, location, it, "get_by_id_getter_self");
848             break;
849         }
850         case op_get_by_id_getter_proto: {
851             printGetByIdOp(exec, location, it, "get_by_id_getter_proto");
852             break;
853         }
854         case op_get_by_id_getter_chain: {
855             printGetByIdOp(exec, location, it, "get_by_id_getter_chain");
856             break;
857         }
858         case op_get_by_id_custom_self: {
859             printGetByIdOp(exec, location, it, "get_by_id_custom_self");
860             break;
861         }
862         case op_get_by_id_custom_proto: {
863             printGetByIdOp(exec, location, it, "get_by_id_custom_proto");
864             break;
865         }
866         case op_get_by_id_custom_chain: {
867             printGetByIdOp(exec, location, it, "get_by_id_custom_chain");
868             break;
869         }
870         case op_get_by_id_generic: {
871             printGetByIdOp(exec, location, it, "get_by_id_generic");
872             break;
873         }
874         case op_get_array_length: {
875             printGetByIdOp(exec, location, it, "get_array_length");
876             break;
877         }
878         case op_get_string_length: {
879             printGetByIdOp(exec, location, it, "get_string_length");
880             break;
881         }
882         case op_get_arguments_length: {
883             printUnaryOp(exec, location, it, "get_arguments_length");
884             it++;
885             break;
886         }
887         case op_put_by_id: {
888             printPutByIdOp(exec, location, it, "put_by_id");
889             break;
890         }
891         case op_put_by_id_replace: {
892             printPutByIdOp(exec, location, it, "put_by_id_replace");
893             break;
894         }
895         case op_put_by_id_transition: {
896             printPutByIdOp(exec, location, it, "put_by_id_transition");
897             break;
898         }
899         case op_put_by_id_generic: {
900             printPutByIdOp(exec, location, it, "put_by_id_generic");
901             break;
902         }
903         case op_put_getter_setter: {
904             int r0 = (++it)->u.operand;
905             int id0 = (++it)->u.operand;
906             int r1 = (++it)->u.operand;
907             int r2 = (++it)->u.operand;
908             dataLog("[%4d] put_getter_setter\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
909             break;
910         }
911         case op_method_check: {
912             dataLog("[%4d] method_check\n", location);
913             break;
914         }
915         case op_del_by_id: {
916             int r0 = (++it)->u.operand;
917             int r1 = (++it)->u.operand;
918             int id0 = (++it)->u.operand;
919             dataLog("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
920             break;
921         }
922         case op_get_by_val: {
923             int r0 = (++it)->u.operand;
924             int r1 = (++it)->u.operand;
925             int r2 = (++it)->u.operand;
926             dataLog("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
927             it++;
928             break;
929         }
930         case op_get_argument_by_val: {
931             int r0 = (++it)->u.operand;
932             int r1 = (++it)->u.operand;
933             int r2 = (++it)->u.operand;
934             dataLog("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
935             ++it;
936             break;
937         }
938         case op_get_by_pname: {
939             int r0 = (++it)->u.operand;
940             int r1 = (++it)->u.operand;
941             int r2 = (++it)->u.operand;
942             int r3 = (++it)->u.operand;
943             int r4 = (++it)->u.operand;
944             int r5 = (++it)->u.operand;
945             dataLog("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data());
946             break;
947         }
948         case op_put_by_val: {
949             int r0 = (++it)->u.operand;
950             int r1 = (++it)->u.operand;
951             int r2 = (++it)->u.operand;
952             dataLog("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
953             break;
954         }
955         case op_del_by_val: {
956             int r0 = (++it)->u.operand;
957             int r1 = (++it)->u.operand;
958             int r2 = (++it)->u.operand;
959             dataLog("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
960             break;
961         }
962         case op_put_by_index: {
963             int r0 = (++it)->u.operand;
964             unsigned n0 = (++it)->u.operand;
965             int r1 = (++it)->u.operand;
966             dataLog("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data());
967             break;
968         }
969         case op_jmp: {
970             int offset = (++it)->u.operand;
971             dataLog("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset);
972             break;
973         }
974         case op_loop: {
975             int offset = (++it)->u.operand;
976             dataLog("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset);
977             break;
978         }
979         case op_jtrue: {
980             printConditionalJump(exec, begin, it, location, "jtrue");
981             break;
982         }
983         case op_loop_if_true: {
984             printConditionalJump(exec, begin, it, location, "loop_if_true");
985             break;
986         }
987         case op_loop_if_false: {
988             printConditionalJump(exec, begin, it, location, "loop_if_false");
989             break;
990         }
991         case op_jfalse: {
992             printConditionalJump(exec, begin, it, location, "jfalse");
993             break;
994         }
995         case op_jeq_null: {
996             printConditionalJump(exec, begin, it, location, "jeq_null");
997             break;
998         }
999         case op_jneq_null: {
1000             printConditionalJump(exec, begin, it, location, "jneq_null");
1001             break;
1002         }
1003         case op_jneq_ptr: {
1004             int r0 = (++it)->u.operand;
1005             int r1 = (++it)->u.operand;
1006             int offset = (++it)->u.operand;
1007             dataLog("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1008             break;
1009         }
1010         case op_jless: {
1011             int r0 = (++it)->u.operand;
1012             int r1 = (++it)->u.operand;
1013             int offset = (++it)->u.operand;
1014             dataLog("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1015             break;
1016         }
1017         case op_jlesseq: {
1018             int r0 = (++it)->u.operand;
1019             int r1 = (++it)->u.operand;
1020             int offset = (++it)->u.operand;
1021             dataLog("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1022             break;
1023         }
1024         case op_jgreater: {
1025             int r0 = (++it)->u.operand;
1026             int r1 = (++it)->u.operand;
1027             int offset = (++it)->u.operand;
1028             dataLog("[%4d] jgreater\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1029             break;
1030         }
1031         case op_jgreatereq: {
1032             int r0 = (++it)->u.operand;
1033             int r1 = (++it)->u.operand;
1034             int offset = (++it)->u.operand;
1035             dataLog("[%4d] jgreatereq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1036             break;
1037         }
1038         case op_jnless: {
1039             int r0 = (++it)->u.operand;
1040             int r1 = (++it)->u.operand;
1041             int offset = (++it)->u.operand;
1042             dataLog("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1043             break;
1044         }
1045         case op_jnlesseq: {
1046             int r0 = (++it)->u.operand;
1047             int r1 = (++it)->u.operand;
1048             int offset = (++it)->u.operand;
1049             dataLog("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1050             break;
1051         }
1052         case op_jngreater: {
1053             int r0 = (++it)->u.operand;
1054             int r1 = (++it)->u.operand;
1055             int offset = (++it)->u.operand;
1056             dataLog("[%4d] jngreater\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1057             break;
1058         }
1059         case op_jngreatereq: {
1060             int r0 = (++it)->u.operand;
1061             int r1 = (++it)->u.operand;
1062             int offset = (++it)->u.operand;
1063             dataLog("[%4d] jngreatereq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1064             break;
1065         }
1066         case op_loop_if_less: {
1067             int r0 = (++it)->u.operand;
1068             int r1 = (++it)->u.operand;
1069             int offset = (++it)->u.operand;
1070             dataLog("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1071             break;
1072         }
1073         case op_loop_if_lesseq: {
1074             int r0 = (++it)->u.operand;
1075             int r1 = (++it)->u.operand;
1076             int offset = (++it)->u.operand;
1077             dataLog("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1078             break;
1079         }
1080         case op_loop_if_greater: {
1081             int r0 = (++it)->u.operand;
1082             int r1 = (++it)->u.operand;
1083             int offset = (++it)->u.operand;
1084             dataLog("[%4d] loop_if_greater\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1085             break;
1086         }
1087         case op_loop_if_greatereq: {
1088             int r0 = (++it)->u.operand;
1089             int r1 = (++it)->u.operand;
1090             int offset = (++it)->u.operand;
1091             dataLog("[%4d] loop_if_greatereq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
1092             break;
1093         }
1094         case op_loop_hint: {
1095             dataLog("[%4d] loop_hint\n", location);
1096             break;
1097         }
1098         case op_switch_imm: {
1099             int tableIndex = (++it)->u.operand;
1100             int defaultTarget = (++it)->u.operand;
1101             int scrutineeRegister = (++it)->u.operand;
1102             dataLog("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
1103             break;
1104         }
1105         case op_switch_char: {
1106             int tableIndex = (++it)->u.operand;
1107             int defaultTarget = (++it)->u.operand;
1108             int scrutineeRegister = (++it)->u.operand;
1109             dataLog("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
1110             break;
1111         }
1112         case op_switch_string: {
1113             int tableIndex = (++it)->u.operand;
1114             int defaultTarget = (++it)->u.operand;
1115             int scrutineeRegister = (++it)->u.operand;
1116             dataLog("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
1117             break;
1118         }
1119         case op_new_func: {
1120             int r0 = (++it)->u.operand;
1121             int f0 = (++it)->u.operand;
1122             int shouldCheck = (++it)->u.operand;
1123             dataLog("[%4d] new_func\t\t %s, f%d, %s\n", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>");
1124             break;
1125         }
1126         case op_new_func_exp: {
1127             int r0 = (++it)->u.operand;
1128             int f0 = (++it)->u.operand;
1129             dataLog("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).data(), f0);
1130             break;
1131         }
1132         case op_call: {
1133             printCallOp(exec, location, it, "call");
1134             break;
1135         }
1136         case op_call_eval: {
1137             printCallOp(exec, location, it, "call_eval");
1138             break;
1139         }
1140         case op_call_varargs: {
1141             int callee = (++it)->u.operand;
1142             int thisValue = (++it)->u.operand;
1143             int arguments = (++it)->u.operand;
1144             int firstFreeRegister = (++it)->u.operand;
1145             dataLog("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister);
1146             break;
1147         }
1148         case op_tear_off_activation: {
1149             int r0 = (++it)->u.operand;
1150             int r1 = (++it)->u.operand;
1151             dataLog("[%4d] tear_off_activation\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
1152             break;
1153         }
1154         case op_tear_off_arguments: {
1155             int r0 = (++it)->u.operand;
1156             dataLog("[%4d] tear_off_arguments %s\n", location, registerName(exec, r0).data());
1157             break;
1158         }
1159         case op_ret: {
1160             int r0 = (++it)->u.operand;
1161             dataLog("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data());
1162             break;
1163         }
1164         case op_call_put_result: {
1165             int r0 = (++it)->u.operand;
1166             dataLog("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());
1167             it++;
1168             break;
1169         }
1170         case op_ret_object_or_this: {
1171             int r0 = (++it)->u.operand;
1172             int r1 = (++it)->u.operand;
1173             dataLog("[%4d] constructor_ret\t\t %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
1174             break;
1175         }
1176         case op_construct: {
1177             printCallOp(exec, location, it, "construct");
1178             break;
1179         }
1180         case op_strcat: {
1181             int r0 = (++it)->u.operand;
1182             int r1 = (++it)->u.operand;
1183             int count = (++it)->u.operand;
1184             dataLog("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count);
1185             break;
1186         }
1187         case op_to_primitive: {
1188             int r0 = (++it)->u.operand;
1189             int r1 = (++it)->u.operand;
1190             dataLog("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
1191             break;
1192         }
1193         case op_get_pnames: {
1194             int r0 = it[1].u.operand;
1195             int r1 = it[2].u.operand;
1196             int r2 = it[3].u.operand;
1197             int r3 = it[4].u.operand;
1198             int offset = it[5].u.operand;
1199             dataLog("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset);
1200             it += OPCODE_LENGTH(op_get_pnames) - 1;
1201             break;
1202         }
1203         case op_next_pname: {
1204             int dest = it[1].u.operand;
1205             int base = it[2].u.operand;
1206             int i = it[3].u.operand;
1207             int size = it[4].u.operand;
1208             int iter = it[5].u.operand;
1209             int offset = it[6].u.operand;
1210             dataLog("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset);
1211             it += OPCODE_LENGTH(op_next_pname) - 1;
1212             break;
1213         }
1214         case op_push_scope: {
1215             int r0 = (++it)->u.operand;
1216             dataLog("[%4d] push_scope\t %s\n", location, registerName(exec, r0).data());
1217             break;
1218         }
1219         case op_pop_scope: {
1220             dataLog("[%4d] pop_scope\n", location);
1221             break;
1222         }
1223         case op_push_new_scope: {
1224             int r0 = (++it)->u.operand;
1225             int id0 = (++it)->u.operand;
1226             int r1 = (++it)->u.operand;
1227             dataLog("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
1228             break;
1229         }
1230         case op_jmp_scopes: {
1231             int scopeDelta = (++it)->u.operand;
1232             int offset = (++it)->u.operand;
1233             dataLog("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset);
1234             break;
1235         }
1236         case op_catch: {
1237             int r0 = (++it)->u.operand;
1238             dataLog("[%4d] catch\t\t %s\n", location, registerName(exec, r0).data());
1239             break;
1240         }
1241         case op_throw: {
1242             int r0 = (++it)->u.operand;
1243             dataLog("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data());
1244             break;
1245         }
1246         case op_throw_reference_error: {
1247             int k0 = (++it)->u.operand;
1248             dataLog("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data());
1249             break;
1250         }
1251         case op_jsr: {
1252             int retAddrDst = (++it)->u.operand;
1253             int offset = (++it)->u.operand;
1254             dataLog("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).data(), offset, location + offset);
1255             break;
1256         }
1257         case op_sret: {
1258             int retAddrSrc = (++it)->u.operand;
1259             dataLog("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).data());
1260             break;
1261         }
1262         case op_debug: {
1263             int debugHookID = (++it)->u.operand;
1264             int firstLine = (++it)->u.operand;
1265             int lastLine = (++it)->u.operand;
1266             dataLog("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
1267             break;
1268         }
1269         case op_profile_will_call: {
1270             int function = (++it)->u.operand;
1271             dataLog("[%4d] profile_will_call %s\n", location, registerName(exec, function).data());
1272             break;
1273         }
1274         case op_profile_did_call: {
1275             int function = (++it)->u.operand;
1276             dataLog("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data());
1277             break;
1278         }
1279         case op_end: {
1280             int r0 = (++it)->u.operand;
1281             dataLog("[%4d] end\t\t %s\n", location, registerName(exec, r0).data());
1282             break;
1283         }
1284     }
1285 }
1286
1287 #if DUMP_CODE_BLOCK_STATISTICS
1288 static HashSet<CodeBlock*> liveCodeBlockSet;
1289 #endif
1290
1291 #define FOR_EACH_MEMBER_VECTOR(macro) \
1292     macro(instructions) \
1293     macro(globalResolveInfos) \
1294     macro(structureStubInfos) \
1295     macro(callLinkInfos) \
1296     macro(linkedCallerList) \
1297     macro(identifiers) \
1298     macro(functionExpressions) \
1299     macro(constantRegisters)
1300
1301 #define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
1302     macro(regexps) \
1303     macro(functions) \
1304     macro(exceptionHandlers) \
1305     macro(immediateSwitchJumpTables) \
1306     macro(characterSwitchJumpTables) \
1307     macro(stringSwitchJumpTables) \
1308     macro(evalCodeCache) \
1309     macro(expressionInfo) \
1310     macro(lineInfo) \
1311     macro(callReturnIndexVector)
1312
1313 template<typename T>
1314 static size_t sizeInBytes(const Vector<T>& vector)
1315 {
1316     return vector.capacity() * sizeof(T);
1317 }
1318
1319 void CodeBlock::dumpStatistics()
1320 {
1321 #if DUMP_CODE_BLOCK_STATISTICS
1322     #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;
1323         FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)
1324         FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)
1325     #undef DEFINE_VARS
1326
1327     // Non-vector data members
1328     size_t evalCodeCacheIsNotEmpty = 0;
1329
1330     size_t symbolTableIsNotEmpty = 0;
1331     size_t symbolTableTotalSize = 0;
1332
1333     size_t hasRareData = 0;
1334
1335     size_t isFunctionCode = 0;
1336     size_t isGlobalCode = 0;
1337     size_t isEvalCode = 0;
1338
1339     HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end();
1340     for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) {
1341         CodeBlock* codeBlock = *it;
1342
1343         #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); }
1344             FOR_EACH_MEMBER_VECTOR(GET_STATS)
1345         #undef GET_STATS
1346
1347         if (!codeBlock->m_symbolTable.isEmpty()) {
1348             symbolTableIsNotEmpty++;
1349             symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
1350         }
1351
1352         if (codeBlock->m_rareData) {
1353             hasRareData++;
1354             #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }
1355                 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS)
1356             #undef GET_STATS
1357
1358             if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty())
1359                 evalCodeCacheIsNotEmpty++;
1360         }
1361
1362         switch (codeBlock->codeType()) {
1363             case FunctionCode:
1364                 ++isFunctionCode;
1365                 break;
1366             case GlobalCode:
1367                 ++isGlobalCode;
1368                 break;
1369             case EvalCode:
1370                 ++isEvalCode;
1371                 break;
1372         }
1373     }
1374
1375     size_t totalSize = 0;
1376
1377     #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize;
1378         FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE)
1379         FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE)
1380     #undef GET_TOTAL_SIZE
1381
1382     totalSize += symbolTableTotalSize;
1383     totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
1384
1385     dataLog("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
1386     dataLog("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
1387     dataLog("Size of all CodeBlocks: %zu\n", totalSize);
1388     dataLog("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
1389
1390     dataLog("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size());
1391     dataLog("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
1392     dataLog("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
1393
1394     dataLog("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
1395
1396     #define PRINT_STATS(name) dataLog("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); dataLog("Size of all " #name ": %zu\n", name##TotalSize); 
1397         FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
1398         FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
1399     #undef PRINT_STATS
1400
1401     dataLog("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
1402     dataLog("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
1403
1404     dataLog("Size of all symbolTables: %zu\n", symbolTableTotalSize);
1405
1406 #else
1407     dataLog("Dumping CodeBlock statistics is not enabled.\n");
1408 #endif
1409 }
1410
1411 CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
1412     : m_globalObject(other.m_globalObject)
1413     , m_heap(other.m_heap)
1414     , m_numCalleeRegisters(other.m_numCalleeRegisters)
1415     , m_numVars(other.m_numVars)
1416     , m_numCapturedVars(other.m_numCapturedVars)
1417     , m_isConstructor(other.m_isConstructor)
1418     , m_shouldDiscardBytecode(false)
1419     , m_ownerExecutable(*other.m_globalData, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
1420     , m_globalData(other.m_globalData)
1421     , m_instructions(other.m_instructions)
1422     , m_instructionCount(other.m_instructionCount)
1423     , m_thisRegister(other.m_thisRegister)
1424     , m_argumentsRegister(other.m_argumentsRegister)
1425     , m_activationRegister(other.m_activationRegister)
1426     , m_needsFullScopeChain(other.m_needsFullScopeChain)
1427     , m_usesEval(other.m_usesEval)
1428     , m_isNumericCompareFunction(other.m_isNumericCompareFunction)
1429     , m_isStrictMode(other.m_isStrictMode)
1430     , m_codeType(other.m_codeType)
1431     , m_source(other.m_source)
1432     , m_sourceOffset(other.m_sourceOffset)
1433 #if ENABLE(JIT)
1434     , m_globalResolveInfos(other.m_globalResolveInfos)
1435 #endif
1436 #if ENABLE(VALUE_PROFILER)
1437     , m_executionEntryCount(0)
1438 #endif
1439     , m_jumpTargets(other.m_jumpTargets)
1440     , m_loopTargets(other.m_loopTargets)
1441     , m_identifiers(other.m_identifiers)
1442     , m_constantRegisters(other.m_constantRegisters)
1443     , m_functionDecls(other.m_functionDecls)
1444     , m_functionExprs(other.m_functionExprs)
1445     , m_symbolTable(symTab)
1446     , m_speculativeSuccessCounter(0)
1447     , m_speculativeFailCounter(0)
1448     , m_optimizationDelayCounter(0)
1449     , m_reoptimizationRetryCounter(0)
1450 #if ENABLE(JIT)
1451     , m_canCompileWithDFGState(CompileWithDFGUnset)
1452 #endif
1453 {
1454     setNumParameters(other.numParameters());
1455     optimizeAfterWarmUp();
1456     
1457     if (other.m_rareData) {
1458         createRareDataIfNecessary();
1459         
1460         m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
1461         m_rareData->m_regexps = other.m_rareData->m_regexps;
1462         m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
1463         m_rareData->m_immediateSwitchJumpTables = other.m_rareData->m_immediateSwitchJumpTables;
1464         m_rareData->m_characterSwitchJumpTables = other.m_rareData->m_characterSwitchJumpTables;
1465         m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
1466         m_rareData->m_expressionInfo = other.m_rareData->m_expressionInfo;
1467         m_rareData->m_lineInfo = other.m_rareData->m_lineInfo;
1468     }
1469 }
1470
1471 CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor, PassOwnPtr<CodeBlock> alternative)
1472     : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
1473     , m_heap(&m_globalObject->globalData().heap)
1474     , m_numCalleeRegisters(0)
1475     , m_numVars(0)
1476     , m_isConstructor(isConstructor)
1477     , m_shouldDiscardBytecode(false)
1478     , m_numParameters(0)
1479     , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
1480     , m_globalData(0)
1481     , m_instructions(adoptRef(new Instructions))
1482     , m_instructionCount(0)
1483     , m_argumentsRegister(-1)
1484     , m_needsFullScopeChain(ownerExecutable->needsActivation())
1485     , m_usesEval(ownerExecutable->usesEval())
1486     , m_isNumericCompareFunction(false)
1487     , m_isStrictMode(ownerExecutable->isStrictMode())
1488     , m_codeType(codeType)
1489     , m_source(sourceProvider)
1490     , m_sourceOffset(sourceOffset)
1491 #if ENABLE(VALUE_PROFILER)
1492     , m_executionEntryCount(0)
1493 #endif
1494     , m_symbolTable(symTab)
1495     , m_alternative(alternative)
1496     , m_speculativeSuccessCounter(0)
1497     , m_speculativeFailCounter(0)
1498     , m_optimizationDelayCounter(0)
1499     , m_reoptimizationRetryCounter(0)
1500 {
1501     ASSERT(m_source);
1502     
1503     optimizeAfterWarmUp();
1504
1505 #if DUMP_CODE_BLOCK_STATISTICS
1506     liveCodeBlockSet.add(this);
1507 #endif
1508 }
1509
1510 CodeBlock::~CodeBlock()
1511 {
1512 #if ENABLE(DFG_JIT)
1513     // Remove myself from the set of DFG code blocks. Note that I may not be in this set
1514     // (because I'm not a DFG code block), in which case this is a no-op anyway.
1515     m_globalData->heap.m_dfgCodeBlocks.m_set.remove(this);
1516 #endif
1517     
1518 #if ENABLE(VERBOSE_VALUE_PROFILE)
1519     dumpValueProfiles();
1520 #endif
1521     
1522 #if ENABLE(JIT)
1523     // We may be destroyed before any CodeBlocks that refer to us are destroyed.
1524     // Consider that two CodeBlocks become unreachable at the same time. There
1525     // is no guarantee about the order in which the CodeBlocks are destroyed.
1526     // So, if we don't remove incoming calls, and get destroyed before the
1527     // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's
1528     // destructor will try to remove nodes from our (no longer valid) linked list.
1529     while (m_incomingCalls.begin() != m_incomingCalls.end())
1530         m_incomingCalls.begin()->remove();
1531     
1532     // Note that our outgoing calls will be removed from other CodeBlocks'
1533     // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
1534     // destructors.
1535
1536     for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
1537         m_structureStubInfos[i].deref();
1538 #endif // ENABLE(JIT)
1539
1540 #if DUMP_CODE_BLOCK_STATISTICS
1541     liveCodeBlockSet.remove(this);
1542 #endif
1543 }
1544
1545 void CodeBlock::setNumParameters(int newValue)
1546 {
1547     m_numParameters = newValue;
1548
1549 #if ENABLE(VALUE_PROFILER)
1550     m_argumentValueProfiles.resize(newValue);
1551 #endif
1552 }
1553
1554 void CodeBlock::addParameter()
1555 {
1556     m_numParameters++;
1557
1558 #if ENABLE(VALUE_PROFILER)
1559     m_argumentValueProfiles.append(ValueProfile());
1560 #endif
1561 }
1562
1563 void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const
1564 {
1565     Interpreter* interpreter = m_globalData->interpreter;
1566
1567     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) && vPC[4].u.structure) {
1568         visitor.append(&vPC[4].u.structure);
1569         return;
1570     }
1571
1572     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) {
1573         visitor.append(&vPC[4].u.structure);
1574         return;
1575     }
1576     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) {
1577         visitor.append(&vPC[4].u.structure);
1578         visitor.append(&vPC[5].u.structure);
1579         return;
1580     }
1581     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
1582         visitor.append(&vPC[4].u.structure);
1583         visitor.append(&vPC[5].u.structureChain);
1584         return;
1585     }
1586     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
1587         visitor.append(&vPC[4].u.structure);
1588         visitor.append(&vPC[5].u.structure);
1589         visitor.append(&vPC[6].u.structureChain);
1590         return;
1591     }
1592     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) && vPC[4].u.structure) {
1593         visitor.append(&vPC[4].u.structure);
1594         return;
1595     }
1596     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
1597         visitor.append(&vPC[4].u.structure);
1598         return;
1599     }
1600     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global) || vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) {
1601         if (vPC[3].u.structure)
1602             visitor.append(&vPC[3].u.structure);
1603         return;
1604     }
1605
1606     // These instructions don't ref their Structures.
1607     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));
1608 }
1609
1610 void EvalCodeCache::visitAggregate(SlotVisitor& visitor)
1611 {
1612     EvalCacheMap::iterator end = m_cacheMap.end();
1613     for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
1614         visitor.append(&ptr->second);
1615 }
1616
1617 void CodeBlock::visitAggregate(SlotVisitor& visitor)
1618 {
1619     if (!!m_alternative)
1620         m_alternative->visitAggregate(visitor);
1621
1622     // There are three things that may use unconditional finalizers: lazy bytecode freeing,
1623     // inline cache clearing, and jettisoning. The probability of us wanting to do at
1624     // least one of those things is probably quite close to 1. So we add one no matter what
1625     // and when it runs, it figures out whether it has any work to do.
1626     visitor.addUnconditionalFinalizer(this);
1627     
1628     if (shouldImmediatelyAssumeLivenessDuringScan()) {
1629         // This code block is live, so scan all references strongly and return.
1630         stronglyVisitStrongReferences(visitor);
1631         stronglyVisitWeakReferences(visitor);
1632         return;
1633     }
1634     
1635 #if ENABLE(DFG_JIT)
1636     // We get here if we're live in the sense that our owner executable is live,
1637     // but we're not yet live for sure in another sense: we may yet decide that this
1638     // code block should be jettisoned based on its outgoing weak references being
1639     // stale. Set a flag to indicate that we're still assuming that we're dead, and
1640     // perform one round of determining if we're live. The GC may determine, based on
1641     // either us marking additional objects, or by other objects being marked for
1642     // other reasons, that this iteration should run again; it will notify us of this
1643     // decision by calling harvestWeakReferences().
1644     
1645     m_dfgData->livenessHasBeenProved = false;
1646     m_dfgData->allTransitionsHaveBeenMarked = false;
1647     
1648     performTracingFixpointIteration(visitor);
1649
1650     // GC doesn't have enough information yet for us to decide whether to keep our DFG
1651     // data, so we need to register a handler to run again at the end of GC, when more
1652     // information is available.
1653     if (!(m_dfgData->livenessHasBeenProved && m_dfgData->allTransitionsHaveBeenMarked))
1654         visitor.addWeakReferenceHarvester(this);
1655     
1656 #else // ENABLE(DFG_JIT)
1657     ASSERT_NOT_REACHED();
1658 #endif // ENABLE(DFG_JIT)
1659 }
1660
1661 void CodeBlock::performTracingFixpointIteration(SlotVisitor& visitor)
1662 {
1663     UNUSED_PARAM(visitor);
1664     
1665 #if ENABLE(DFG_JIT)
1666     // Evaluate our weak reference transitions, if there are still some to evaluate.
1667     if (!m_dfgData->allTransitionsHaveBeenMarked) {
1668         bool allAreMarkedSoFar = true;
1669         for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) {
1670             if ((!m_dfgData->transitions[i].m_codeOrigin
1671                  || Heap::isMarked(m_dfgData->transitions[i].m_codeOrigin.get()))
1672                 && Heap::isMarked(m_dfgData->transitions[i].m_from.get())) {
1673                 // If the following three things are live, then the target of the
1674                 // transition is also live:
1675                 // - This code block. We know it's live already because otherwise
1676                 //   we wouldn't be scanning ourselves.
1677                 // - The code origin of the transition. Transitions may arise from
1678                 //   code that was inlined. They are not relevant if the user's
1679                 //   object that is required for the inlinee to run is no longer
1680                 //   live.
1681                 // - The source of the transition. The transition checks if some
1682                 //   heap location holds the source, and if so, stores the target.
1683                 //   Hence the source must be live for the transition to be live.
1684                 visitor.append(&m_dfgData->transitions[i].m_to);
1685             } else
1686                 allAreMarkedSoFar = false;
1687         }
1688         
1689         if (allAreMarkedSoFar)
1690             m_dfgData->allTransitionsHaveBeenMarked = true;
1691     }
1692     
1693     // Check if we have any remaining work to do.
1694     if (m_dfgData->livenessHasBeenProved)
1695         return;
1696     
1697     // Now check all of our weak references. If all of them are live, then we
1698     // have proved liveness and so we scan our strong references. If at end of
1699     // GC we still have not proved liveness, then this code block is toast.
1700     bool allAreLiveSoFar = true;
1701     for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) {
1702         if (!Heap::isMarked(m_dfgData->weakReferences[i].get())) {
1703             allAreLiveSoFar = false;
1704             break;
1705         }
1706     }
1707     
1708     // If some weak references are dead, then this fixpoint iteration was
1709     // unsuccessful.
1710     if (!allAreLiveSoFar)
1711         return;
1712     
1713     // All weak references are live. Record this information so we don't
1714     // come back here again, and scan the strong references.
1715     m_dfgData->livenessHasBeenProved = true;
1716     stronglyVisitStrongReferences(visitor);
1717 #endif // ENABLE(DFG_JIT)
1718 }
1719
1720 void CodeBlock::visitWeakReferences(SlotVisitor& visitor)
1721 {
1722     performTracingFixpointIteration(visitor);
1723 }
1724
1725 void CodeBlock::finalizeUnconditionally()
1726 {
1727 #if ENABLE(JIT)
1728 #if ENABLE(JIT_VERBOSE_OSR)
1729     static const bool verboseUnlinking = true;
1730 #else
1731     static const bool verboseUnlinking = false;
1732 #endif
1733 #endif
1734     
1735 #if ENABLE(DFG_JIT)
1736     // Check if we're not live. If we are, then jettison.
1737     if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) {
1738         if (verboseUnlinking)
1739             dataLog("Code block %p has dead weak references, jettisoning during GC.\n", this);
1740
1741         // Make sure that the baseline JIT knows that it should re-warm-up before
1742         // optimizing.
1743         alternative()->optimizeAfterWarmUp();
1744         
1745         jettison();
1746         return;
1747     }
1748 #endif // ENABLE(DFG_JIT)
1749     
1750 #if ENABLE(JIT)
1751     // Handle inline caches.
1752     if (!!getJITCode()) {
1753         RepatchBuffer repatchBuffer(this);
1754         for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) {
1755             if (callLinkInfo(i).isLinked() && !Heap::isMarked(callLinkInfo(i).callee.get())) {
1756                 if (verboseUnlinking)
1757                     dataLog("Clearing call from %p.\n", this);
1758                 callLinkInfo(i).unlink(*m_globalData, repatchBuffer);
1759             }
1760             if (!!callLinkInfo(i).lastSeenCallee
1761                 && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get()))
1762                 callLinkInfo(i).lastSeenCallee.clear();
1763         }
1764         for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
1765             if (m_globalResolveInfos[i].structure && !Heap::isMarked(m_globalResolveInfos[i].structure.get())) {
1766                 if (verboseUnlinking)
1767                     dataLog("Clearing resolve info in %p.\n", this);
1768                 m_globalResolveInfos[i].structure.clear();
1769             }
1770         }
1771
1772         for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) {
1773             StructureStubInfo& stubInfo = m_structureStubInfos[i];
1774             
1775             AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
1776             
1777             if (stubInfo.visitWeakReferences())
1778                 continue;
1779             
1780             if (verboseUnlinking)
1781                 dataLog("Clearing structure cache (kind %d) in %p.\n", stubInfo.accessType, this);
1782             
1783             if (isGetByIdAccess(accessType)) {
1784                 if (getJITCode().jitType() == JITCode::DFGJIT)
1785                     DFG::dfgResetGetByID(repatchBuffer, stubInfo);
1786                 else
1787                     JIT::resetPatchGetById(repatchBuffer, &stubInfo);
1788             } else {
1789                 ASSERT(isPutByIdAccess(accessType));
1790                 if (getJITCode().jitType() == JITCode::DFGJIT)
1791                     DFG::dfgResetPutByID(repatchBuffer, stubInfo);
1792                 else 
1793                     JIT::resetPatchPutById(repatchBuffer, &stubInfo);
1794             }
1795             
1796             stubInfo.reset();
1797         }
1798
1799         for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) {
1800             if (!m_methodCallLinkInfos[i].cachedStructure)
1801                 continue;
1802             
1803             ASSERT(m_methodCallLinkInfos[i].seenOnce());
1804             ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure);
1805
1806             if (!Heap::isMarked(m_methodCallLinkInfos[i].cachedStructure.get())
1807                 || !Heap::isMarked(m_methodCallLinkInfos[i].cachedPrototypeStructure.get())
1808                 || !Heap::isMarked(m_methodCallLinkInfos[i].cachedFunction.get())
1809                 || !Heap::isMarked(m_methodCallLinkInfos[i].cachedPrototype.get())) {
1810                 if (verboseUnlinking)
1811                     dataLog("Clearing method call in %p.\n", this);
1812                 m_methodCallLinkInfos[i].reset(repatchBuffer, getJITType());
1813
1814                 StructureStubInfo& stubInfo = getStubInfo(m_methodCallLinkInfos[i].bytecodeIndex);
1815
1816                 AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
1817
1818                 if (accessType != access_unset) {
1819                     ASSERT(isGetByIdAccess(accessType));
1820                     if (getJITCode().jitType() == JITCode::DFGJIT)
1821                         DFG::dfgResetGetByID(repatchBuffer, stubInfo);
1822                     else
1823                         JIT::resetPatchGetById(repatchBuffer, &stubInfo);
1824                     stubInfo.reset();
1825                 }
1826             }
1827         }
1828     }
1829 #endif
1830
1831     // Handle the bytecode discarding chore.
1832     if (m_shouldDiscardBytecode) {
1833         discardBytecode();
1834         m_shouldDiscardBytecode = false;
1835     }
1836 }
1837
1838 void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
1839 {
1840     visitor.append(&m_globalObject);
1841     visitor.append(&m_ownerExecutable);
1842     if (m_rareData) {
1843         m_rareData->m_evalCodeCache.visitAggregate(visitor);
1844         size_t regExpCount = m_rareData->m_regexps.size();
1845         WriteBarrier<RegExp>* regexps = m_rareData->m_regexps.data();
1846         for (size_t i = 0; i < regExpCount; i++)
1847             visitor.append(regexps + i);
1848     }
1849     visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
1850     for (size_t i = 0; i < m_functionExprs.size(); ++i)
1851         visitor.append(&m_functionExprs[i]);
1852     for (size_t i = 0; i < m_functionDecls.size(); ++i)
1853         visitor.append(&m_functionDecls[i]);
1854 #if ENABLE(CLASSIC_INTERPRETER)
1855     for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
1856         visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]);
1857     for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
1858         visitStructures(visitor, &instructions()[m_globalResolveInstructions[i]]);
1859 #endif
1860
1861 #if ENABLE(DFG_JIT)
1862     if (hasCodeOrigins()) {
1863         // Make sure that executables that we have inlined don't die.
1864         // FIXME: If they would have otherwise died, we should probably trigger recompilation.
1865         for (size_t i = 0; i < inlineCallFrames().size(); ++i) {
1866             visitor.append(&inlineCallFrames()[i].executable);
1867             visitor.append(&inlineCallFrames()[i].callee);
1868         }
1869     }
1870 #endif
1871
1872 #if ENABLE(VALUE_PROFILER)
1873     for (unsigned profileIndex = 0; profileIndex < numberOfArgumentValueProfiles(); ++profileIndex)
1874         valueProfileForArgument(profileIndex)->computeUpdatedPrediction();
1875     for (unsigned profileIndex = 0; profileIndex < numberOfValueProfiles(); ++profileIndex)
1876         valueProfile(profileIndex)->computeUpdatedPrediction();
1877 #endif
1878 }
1879
1880 void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor)
1881 {
1882     UNUSED_PARAM(visitor);
1883
1884 #if ENABLE(DFG_JIT)
1885     if (!m_dfgData)
1886         return;
1887
1888     for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) {
1889         if (!!m_dfgData->transitions[i].m_codeOrigin)
1890             visitor.append(&m_dfgData->transitions[i].m_codeOrigin); // Almost certainly not necessary, since the code origin should also be a weak reference. Better to be safe, though.
1891         visitor.append(&m_dfgData->transitions[i].m_from);
1892         visitor.append(&m_dfgData->transitions[i].m_to);
1893     }
1894     
1895     for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i)
1896         visitor.append(&m_dfgData->weakReferences[i]);
1897 #endif    
1898 }
1899
1900 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
1901 {
1902     ASSERT(bytecodeOffset < m_instructionCount);
1903
1904     if (!m_rareData)
1905         return 0;
1906     
1907     Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
1908     for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
1909         // Handlers are ordered innermost first, so the first handler we encounter
1910         // that contains the source address is the correct handler to use.
1911         if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end >= bytecodeOffset)
1912             return &exceptionHandlers[i];
1913     }
1914
1915     return 0;
1916 }
1917
1918 int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
1919 {
1920     ASSERT(bytecodeOffset < m_instructionCount);
1921
1922     if (!m_rareData)
1923         return m_ownerExecutable->source().firstLine();
1924
1925     Vector<LineInfo>& lineInfo = m_rareData->m_lineInfo;
1926
1927     int low = 0;
1928     int high = lineInfo.size();
1929     while (low < high) {
1930         int mid = low + (high - low) / 2;
1931         if (lineInfo[mid].instructionOffset <= bytecodeOffset)
1932             low = mid + 1;
1933         else
1934             high = mid;
1935     }
1936
1937     if (!low)
1938         return m_ownerExecutable->source().firstLine();
1939     return lineInfo[low - 1].lineNumber;
1940 }
1941
1942 void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
1943 {
1944     ASSERT(bytecodeOffset < m_instructionCount);
1945
1946     if (!m_rareData) {
1947         startOffset = 0;
1948         endOffset = 0;
1949         divot = 0;
1950         return;
1951     }
1952
1953     Vector<ExpressionRangeInfo>& expressionInfo = m_rareData->m_expressionInfo;
1954
1955     int low = 0;
1956     int high = expressionInfo.size();
1957     while (low < high) {
1958         int mid = low + (high - low) / 2;
1959         if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
1960             low = mid + 1;
1961         else
1962             high = mid;
1963     }
1964
1965     ASSERT(low);
1966     if (!low) {
1967         startOffset = 0;
1968         endOffset = 0;
1969         divot = 0;
1970         return;
1971     }
1972
1973     startOffset = expressionInfo[low - 1].startOffset;
1974     endOffset = expressionInfo[low - 1].endOffset;
1975     divot = expressionInfo[low - 1].divotPoint + m_sourceOffset;
1976     return;
1977 }
1978
1979 #if ENABLE(CLASSIC_INTERPRETER)
1980 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
1981 {
1982     if (m_globalResolveInstructions.isEmpty())
1983         return false;
1984
1985     int low = 0;
1986     int high = m_globalResolveInstructions.size();
1987     while (low < high) {
1988         int mid = low + (high - low) / 2;
1989         if (m_globalResolveInstructions[mid] <= bytecodeOffset)
1990             low = mid + 1;
1991         else
1992             high = mid;
1993     }
1994
1995     if (!low || m_globalResolveInstructions[low - 1] != bytecodeOffset)
1996         return false;
1997     return true;
1998 }
1999 #endif
2000 #if ENABLE(JIT)
2001 bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
2002 {
2003     if (m_globalResolveInfos.isEmpty())
2004         return false;
2005
2006     int low = 0;
2007     int high = m_globalResolveInfos.size();
2008     while (low < high) {
2009         int mid = low + (high - low) / 2;
2010         if (m_globalResolveInfos[mid].bytecodeOffset <= bytecodeOffset)
2011             low = mid + 1;
2012         else
2013             high = mid;
2014     }
2015
2016     if (!low || m_globalResolveInfos[low - 1].bytecodeOffset != bytecodeOffset)
2017         return false;
2018     return true;
2019 }
2020 #endif
2021
2022 void CodeBlock::shrinkToFit()
2023 {
2024     instructions().shrinkToFit();
2025
2026 #if ENABLE(CLASSIC_INTERPRETER)
2027     m_propertyAccessInstructions.shrinkToFit();
2028     m_globalResolveInstructions.shrinkToFit();
2029 #endif
2030 #if ENABLE(JIT)
2031     m_structureStubInfos.shrinkToFit();
2032     m_globalResolveInfos.shrinkToFit();
2033     m_callLinkInfos.shrinkToFit();
2034 #endif
2035
2036     m_identifiers.shrinkToFit();
2037     m_functionDecls.shrinkToFit();
2038     m_functionExprs.shrinkToFit();
2039     m_constantRegisters.shrinkToFit();
2040
2041     if (m_rareData) {
2042         m_rareData->m_exceptionHandlers.shrinkToFit();
2043         m_rareData->m_regexps.shrinkToFit();
2044         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
2045         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
2046         m_rareData->m_stringSwitchJumpTables.shrinkToFit();
2047         m_rareData->m_expressionInfo.shrinkToFit();
2048         m_rareData->m_lineInfo.shrinkToFit();
2049     }
2050 }
2051
2052 void CodeBlock::createActivation(CallFrame* callFrame)
2053 {
2054     ASSERT(codeType() == FunctionCode);
2055     ASSERT(needsFullScopeChain());
2056     ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue());
2057     JSActivation* activation = JSActivation::create(callFrame->globalData(), callFrame, static_cast<FunctionExecutable*>(ownerExecutable()));
2058     callFrame->uncheckedR(activationRegister()) = JSValue(activation);
2059     callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
2060 }
2061
2062 unsigned CodeBlock::addOrFindConstant(JSValue v)
2063 {
2064     unsigned numberOfConstants = numberOfConstantRegisters();
2065     for (unsigned i = 0; i < numberOfConstants; ++i) {
2066         if (getConstant(FirstConstantRegisterIndex + i) == v)
2067             return i;
2068     }
2069     return addConstant(v);
2070 }
2071     
2072 #if ENABLE(JIT)
2073 void CodeBlock::unlinkCalls()
2074 {
2075     if (!!m_alternative)
2076         m_alternative->unlinkCalls();
2077     if (!(m_callLinkInfos.size() || m_methodCallLinkInfos.size()))
2078         return;
2079     if (!m_globalData->canUseJIT())
2080         return;
2081     RepatchBuffer repatchBuffer(this);
2082     for (size_t i = 0; i < m_callLinkInfos.size(); i++) {
2083         if (!m_callLinkInfos[i].isLinked())
2084             continue;
2085         m_callLinkInfos[i].unlink(*m_globalData, repatchBuffer);
2086     }
2087 }
2088
2089 void CodeBlock::unlinkIncomingCalls()
2090 {
2091     RepatchBuffer repatchBuffer(this);
2092     while (m_incomingCalls.begin() != m_incomingCalls.end())
2093         m_incomingCalls.begin()->unlink(*m_globalData, repatchBuffer);
2094 }
2095 #endif
2096
2097 void CodeBlock::clearEvalCache()
2098 {
2099     if (!!m_alternative)
2100         m_alternative->clearEvalCache();
2101     if (!m_rareData)
2102         return;
2103     m_rareData->m_evalCodeCache.clear();
2104 }
2105
2106 template<typename T>
2107 inline void replaceExistingEntries(Vector<T>& target, Vector<T>& source)
2108 {
2109     ASSERT(target.size() <= source.size());
2110     for (size_t i = 0; i < target.size(); ++i)
2111         target[i] = source[i];
2112 }
2113
2114 void CodeBlock::copyPostParseDataFrom(CodeBlock* alternative)
2115 {
2116     if (!alternative)
2117         return;
2118     
2119     replaceExistingEntries(m_constantRegisters, alternative->m_constantRegisters);
2120     replaceExistingEntries(m_functionDecls, alternative->m_functionDecls);
2121     replaceExistingEntries(m_functionExprs, alternative->m_functionExprs);
2122     if (!!m_rareData && !!alternative->m_rareData)
2123         replaceExistingEntries(m_rareData->m_constantBuffers, alternative->m_rareData->m_constantBuffers);
2124 }
2125
2126 void CodeBlock::copyPostParseDataFromAlternative()
2127 {
2128     copyPostParseDataFrom(m_alternative.get());
2129 }
2130
2131 #if ENABLE(JIT)
2132 CodeBlock* ProgramCodeBlock::replacement()
2133 {
2134     return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode();
2135 }
2136
2137 CodeBlock* EvalCodeBlock::replacement()
2138 {
2139     return &static_cast<EvalExecutable*>(ownerExecutable())->generatedBytecode();
2140 }
2141
2142 CodeBlock* FunctionCodeBlock::replacement()
2143 {
2144     return &static_cast<FunctionExecutable*>(ownerExecutable())->generatedBytecodeFor(m_isConstructor ? CodeForConstruct : CodeForCall);
2145 }
2146
2147 JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
2148 {
2149     if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
2150         return 0;
2151     JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
2152     return error;
2153 }
2154
2155 JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
2156 {
2157     if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
2158         return 0;
2159     JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scopeChainNode);
2160     return error;
2161 }
2162
2163 JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
2164 {
2165     if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
2166         return 0;
2167     JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scopeChainNode, m_isConstructor ? CodeForConstruct : CodeForCall);
2168     return error;
2169 }
2170
2171 bool ProgramCodeBlock::canCompileWithDFGInternal()
2172 {
2173     return DFG::canCompileProgram(this);
2174 }
2175
2176 bool EvalCodeBlock::canCompileWithDFGInternal()
2177 {
2178     return DFG::canCompileEval(this);
2179 }
2180
2181 bool FunctionCodeBlock::canCompileWithDFGInternal()
2182 {
2183     if (m_isConstructor)
2184         return DFG::canCompileFunctionForConstruct(this);
2185     return DFG::canCompileFunctionForCall(this);
2186 }
2187
2188 void ProgramCodeBlock::jettison()
2189 {
2190     ASSERT(getJITType() != JITCode::BaselineJIT);
2191     ASSERT(this == replacement());
2192     static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
2193 }
2194
2195 void EvalCodeBlock::jettison()
2196 {
2197     ASSERT(getJITType() != JITCode::BaselineJIT);
2198     ASSERT(this == replacement());
2199     static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData());
2200 }
2201
2202 void FunctionCodeBlock::jettison()
2203 {
2204     ASSERT(getJITType() != JITCode::BaselineJIT);
2205     ASSERT(this == replacement());
2206     static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall);
2207 }
2208 #endif
2209
2210 #if ENABLE(VALUE_PROFILER)
2211 bool CodeBlock::shouldOptimizeNow()
2212 {
2213 #if ENABLE(JIT_VERBOSE_OSR)
2214     dataLog("Considering optimizing %p...\n", this);
2215 #endif
2216
2217 #if ENABLE(VERBOSE_VALUE_PROFILE)
2218     dumpValueProfiles();
2219 #endif
2220
2221     if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay)
2222         return true;
2223     
2224     unsigned numberOfLiveNonArgumentValueProfiles = 0;
2225     unsigned numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
2226     for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
2227         ValueProfile* profile = getFromAllValueProfiles(i);
2228         unsigned numSamples = profile->totalNumberOfSamples();
2229         if (numSamples > ValueProfile::numberOfBuckets)
2230             numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
2231         numberOfSamplesInProfiles += numSamples;
2232         if (profile->m_bytecodeOffset < 0) {
2233             profile->computeUpdatedPrediction();
2234             continue;
2235         }
2236         if (profile->numberOfSamples() || profile->m_prediction != PredictNone)
2237             numberOfLiveNonArgumentValueProfiles++;
2238         profile->computeUpdatedPrediction();
2239     }
2240
2241 #if ENABLE(JIT_VERBOSE_OSR)
2242     dataLog("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles());
2243 #endif
2244
2245     if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate)
2246         && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate)
2247         && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay)
2248         return true;
2249     
2250     ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max());
2251     m_optimizationDelayCounter++;
2252     optimizeAfterWarmUp();
2253     return false;
2254 }
2255 #endif
2256
2257 #if ENABLE(DFG_JIT)
2258 void CodeBlock::tallyFrequentExitSites()
2259 {
2260     ASSERT(getJITType() == JITCode::DFGJIT);
2261     ASSERT(alternative()->getJITType() == JITCode::BaselineJIT);
2262     ASSERT(!!m_dfgData);
2263     
2264     CodeBlock* profiledBlock = alternative();
2265     
2266     for (unsigned i = 0; i < m_dfgData->osrExit.size(); ++i) {
2267         DFG::OSRExit& exit = m_dfgData->osrExit[i];
2268         
2269         if (!exit.considerAddingAsFrequentExitSite(this, profiledBlock))
2270             continue;
2271         
2272 #if DFG_ENABLE(DEBUG_VERBOSE)
2273         dataLog("OSR exit #%u (bc#%u, @%u, %s) for code block %p occurred frequently; counting as frequent exit site.\n", i, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex, DFG::exitKindToString(exit.m_kind), this);
2274 #endif
2275     }
2276 }
2277 #endif // ENABLE(DFG_JIT)
2278
2279 #if ENABLE(VERBOSE_VALUE_PROFILE)
2280 void CodeBlock::dumpValueProfiles()
2281 {
2282     dataLog("ValueProfile for %p:\n", this);
2283     for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
2284         ValueProfile* profile = getFromAllValueProfiles(i);
2285         if (profile->m_bytecodeOffset < 0) {
2286             ASSERT(profile->m_bytecodeOffset == -1);
2287             dataLog("   arg = %u: ", i);
2288         } else
2289             dataLog("   bc = %d: ", profile->m_bytecodeOffset);
2290         if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) {
2291             dataLog("<empty>\n");
2292             continue;
2293         }
2294         profile->dump(WTF::dataFile());
2295         dataLog("\n");
2296     }
2297     dataLog("RareCaseProfile for %p:\n", this);
2298     for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) {
2299         RareCaseProfile* profile = rareCaseProfile(i);
2300         dataLog("   bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
2301     }
2302     dataLog("SpecialFastCaseProfile for %p:\n", this);
2303     for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) {
2304         RareCaseProfile* profile = specialFastCaseProfile(i);
2305         dataLog("   bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
2306     }
2307 }
2308 #endif
2309
2310 #ifndef NDEBUG
2311 bool CodeBlock::usesOpcode(OpcodeID opcodeID)
2312 {
2313     Interpreter* interpreter = globalData()->interpreter;
2314     Instruction* instructionsBegin = instructions().begin();
2315     unsigned instructionCount = instructions().size();
2316     
2317     for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
2318         switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
2319 #define DEFINE_OP(curOpcode, length)        \
2320         case curOpcode:                     \
2321             if (curOpcode == opcodeID)      \
2322                 return true;                \
2323             bytecodeOffset += length;       \
2324             break;
2325             FOR_EACH_OPCODE_ID(DEFINE_OP)
2326 #undef DEFINE_OP
2327         default:
2328             ASSERT_NOT_REACHED();
2329             break;
2330         }
2331     }
2332     
2333     return false;
2334 }
2335 #endif
2336
2337 } // namespace JSC