• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 2009 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 "JIT.h"
34 #include "JSValue.h"
35 #include "Interpreter.h"
36 #include "Debugger.h"
37 #include "BytecodeGenerator.h"
38 #include <stdio.h>
39 #include <wtf/StringExtras.h>
40 
41 #define DUMP_CODE_BLOCK_STATISTICS 0
42 
43 namespace JSC {
44 
45 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
46 
escapeQuotes(const UString & str)47 static UString escapeQuotes(const UString& str)
48 {
49     UString result = str;
50     int pos = 0;
51     while ((pos = result.find('\"', pos)) >= 0) {
52         result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1);
53         pos += 4;
54     }
55     return result;
56 }
57 
valueToSourceString(ExecState * exec,JSValuePtr val)58 static UString valueToSourceString(ExecState* exec, JSValuePtr val)
59 {
60     if (val.isString()) {
61         UString result("\"");
62         result += escapeQuotes(val.toString(exec)) + "\"";
63         return result;
64     }
65 
66     return val.toString(exec);
67 }
68 
registerName(int r)69 static CString registerName(int r)
70 {
71     if (r == missingThisObjectMarker())
72         return "<null>";
73 
74     return (UString("r") + UString::from(r)).UTF8String();
75 }
76 
constantName(ExecState * exec,int k,JSValuePtr value)77 static CString constantName(ExecState* exec, int k, JSValuePtr value)
78 {
79     return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();
80 }
81 
idName(int id0,const Identifier & ident)82 static CString idName(int id0, const Identifier& ident)
83 {
84     return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String();
85 }
86 
regexpToSourceString(RegExp * regExp)87 static UString regexpToSourceString(RegExp* regExp)
88 {
89     UString pattern = UString("/") + regExp->pattern() + "/";
90     if (regExp->global())
91         pattern += "g";
92     if (regExp->ignoreCase())
93         pattern += "i";
94     if (regExp->multiline())
95         pattern += "m";
96 
97     return pattern;
98 }
99 
regexpName(int re,RegExp * regexp)100 static CString regexpName(int re, RegExp* regexp)
101 {
102     return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String();
103 }
104 
pointerToSourceString(void * p)105 static UString pointerToSourceString(void* p)
106 {
107     char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
108     snprintf(buffer, sizeof(buffer), "%p", p);
109     return buffer;
110 }
111 
debugHookName(int debugHookID)112 NEVER_INLINE static const char* debugHookName(int debugHookID)
113 {
114     switch (static_cast<DebugHookID>(debugHookID)) {
115         case DidEnterCallFrame:
116             return "didEnterCallFrame";
117         case WillLeaveCallFrame:
118             return "willLeaveCallFrame";
119         case WillExecuteStatement:
120             return "willExecuteStatement";
121         case WillExecuteProgram:
122             return "willExecuteProgram";
123         case DidExecuteProgram:
124             return "didExecuteProgram";
125         case DidReachBreakpoint:
126             return "didReachBreakpoint";
127     }
128 
129     ASSERT_NOT_REACHED();
130     return "";
131 }
132 
locationForOffset(const Vector<Instruction>::const_iterator & begin,Vector<Instruction>::const_iterator & it,int offset)133 static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset)
134 {
135     return it - begin + offset;
136 }
137 
printUnaryOp(int location,Vector<Instruction>::const_iterator & it,const char * op)138 static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
139 {
140     int r0 = (++it)->u.operand;
141     int r1 = (++it)->u.operand;
142 
143     printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str());
144 }
145 
printBinaryOp(int location,Vector<Instruction>::const_iterator & it,const char * op)146 static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
147 {
148     int r0 = (++it)->u.operand;
149     int r1 = (++it)->u.operand;
150     int r2 = (++it)->u.operand;
151     printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
152 }
153 
printConditionalJump(const Vector<Instruction>::const_iterator & begin,Vector<Instruction>::const_iterator & it,int location,const char * op)154 static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op)
155 {
156     int r0 = (++it)->u.operand;
157     int offset = (++it)->u.operand;
158     printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset));
159 }
160 
printGetByIdOp(int location,Vector<Instruction>::const_iterator & it,const Vector<Identifier> & m_identifiers,const char * op)161 static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
162 {
163     int r0 = (++it)->u.operand;
164     int r1 = (++it)->u.operand;
165     int id0 = (++it)->u.operand;
166     printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
167     it += 4;
168 }
169 
printPutByIdOp(int location,Vector<Instruction>::const_iterator & it,const Vector<Identifier> & m_identifiers,const char * op)170 static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
171 {
172     int r0 = (++it)->u.operand;
173     int id0 = (++it)->u.operand;
174     int r1 = (++it)->u.operand;
175     printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
176     it += 4;
177 }
178 
179 #if ENABLE(JIT)
isGlobalResolve(OpcodeID opcodeID)180 static bool isGlobalResolve(OpcodeID opcodeID)
181 {
182     return opcodeID == op_resolve_global;
183 }
184 
isPropertyAccess(OpcodeID opcodeID)185 static bool isPropertyAccess(OpcodeID opcodeID)
186 {
187     switch (opcodeID) {
188         case op_get_by_id_self:
189         case op_get_by_id_proto:
190         case op_get_by_id_chain:
191         case op_get_by_id_self_list:
192         case op_get_by_id_proto_list:
193         case op_put_by_id_transition:
194         case op_put_by_id_replace:
195         case op_get_by_id:
196         case op_put_by_id:
197         case op_get_by_id_generic:
198         case op_put_by_id_generic:
199         case op_get_array_length:
200         case op_get_string_length:
201             return true;
202         default:
203             return false;
204     }
205 }
206 
instructionOffsetForNth(ExecState * exec,const Vector<Instruction> & instructions,int nth,bool (* predicate)(OpcodeID))207 static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
208 {
209     size_t i = 0;
210     while (i < instructions.size()) {
211         OpcodeID currentOpcode = exec->interpreter()->getOpcodeID(instructions[i].u.opcode);
212         if (predicate(currentOpcode)) {
213             if (!--nth)
214                 return i;
215         }
216         i += opcodeLengths[currentOpcode];
217     }
218 
219     ASSERT_NOT_REACHED();
220     return 0;
221 }
222 
printGlobalResolveInfo(const GlobalResolveInfo & resolveInfo,unsigned instructionOffset)223 static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
224 {
225     printf("  [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().c_str());
226 }
227 
printStructureStubInfo(const StructureStubInfo & stubInfo,unsigned instructionOffset)228 static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
229 {
230     switch (stubInfo.opcodeID) {
231     case op_get_by_id_self:
232         printf("  [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str());
233         return;
234     case op_get_by_id_proto:
235         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str());
236         return;
237     case op_get_by_id_chain:
238         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str());
239         return;
240     case op_get_by_id_self_list:
241         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize);
242         return;
243     case op_get_by_id_proto_list:
244         printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize);
245         return;
246     case op_put_by_id_transition:
247         printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str());
248         return;
249     case op_put_by_id_replace:
250         printf("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str());
251         return;
252     case op_get_by_id:
253         printf("  [%4d] %s\n", instructionOffset, "get_by_id");
254         return;
255     case op_put_by_id:
256         printf("  [%4d] %s\n", instructionOffset, "put_by_id");
257         return;
258     case op_get_by_id_generic:
259         printf("  [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
260         return;
261     case op_put_by_id_generic:
262         printf("  [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
263         return;
264     case op_get_array_length:
265         printf("  [%4d] %s\n", instructionOffset, "op_get_array_length");
266         return;
267     case op_get_string_length:
268         printf("  [%4d] %s\n", instructionOffset, "op_get_string_length");
269         return;
270     default:
271         ASSERT_NOT_REACHED();
272     }
273 }
274 #endif
275 
printStructure(const char * name,const Instruction * vPC,int operand) const276 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
277 {
278     unsigned instructionOffset = vPC - m_instructions.begin();
279     printf("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str());
280 }
281 
printStructures(const Instruction * vPC) const282 void CodeBlock::printStructures(const Instruction* vPC) const
283 {
284     Interpreter* interpreter = m_globalData->interpreter;
285     unsigned instructionOffset = vPC - m_instructions.begin();
286 
287     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
288         printStructure("get_by_id", vPC, 4);
289         return;
290     }
291     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
292         printStructure("get_by_id_self", vPC, 4);
293         return;
294     }
295     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
296         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str());
297         return;
298     }
299     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
300         printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());
301         return;
302     }
303     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
304         printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str());
305         return;
306     }
307     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
308         printStructure("put_by_id", vPC, 4);
309         return;
310     }
311     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
312         printStructure("put_by_id_replace", vPC, 4);
313         return;
314     }
315     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
316         printStructure("resolve_global", vPC, 4);
317         return;
318     }
319 
320     // These m_instructions doesn't ref Structures.
321     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));
322 }
323 
dump(ExecState * exec) const324 void CodeBlock::dump(ExecState* exec) const
325 {
326     if (m_instructions.isEmpty()) {
327         printf("No instructions available.\n");
328         return;
329     }
330 
331     size_t instructionCount = 0;
332 
333     for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)])
334         ++instructionCount;
335 
336     printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
337         static_cast<unsigned long>(instructionCount),
338         static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
339         this, m_numParameters, m_numCalleeRegisters);
340 
341     Vector<Instruction>::const_iterator begin = m_instructions.begin();
342     Vector<Instruction>::const_iterator end = m_instructions.end();
343     for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
344         dump(exec, begin, it);
345 
346     if (!m_identifiers.isEmpty()) {
347         printf("\nIdentifiers:\n");
348         size_t i = 0;
349         do {
350             printf("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());
351             ++i;
352         } while (i != m_identifiers.size());
353     }
354 
355     if (!m_constantRegisters.isEmpty()) {
356         printf("\nConstants:\n");
357         unsigned registerIndex = m_numVars;
358         size_t i = 0;
359         do {
360             printf("   r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii());
361             ++i;
362             ++registerIndex;
363         } while (i < m_constantRegisters.size());
364     }
365 
366     if (m_rareData && !m_rareData->m_unexpectedConstants.isEmpty()) {
367         printf("\nUnexpected Constants:\n");
368         size_t i = 0;
369         do {
370             printf("  k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_rareData->m_unexpectedConstants[i]).ascii());
371             ++i;
372         } while (i < m_rareData->m_unexpectedConstants.size());
373     }
374 
375     if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
376         printf("\nm_regexps:\n");
377         size_t i = 0;
378         do {
379             printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii());
380             ++i;
381         } while (i < m_rareData->m_regexps.size());
382     }
383 
384 #if ENABLE(JIT)
385     if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
386         printf("\nStructures:\n");
387 
388     if (!m_globalResolveInfos.isEmpty()) {
389         size_t i = 0;
390         do {
391              printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve));
392              ++i;
393         } while (i < m_globalResolveInfos.size());
394     }
395     if (!m_structureStubInfos.isEmpty()) {
396         size_t i = 0;
397         do {
398             printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess));
399              ++i;
400         } while (i < m_structureStubInfos.size());
401     }
402 #else
403     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
404         printf("\nStructures:\n");
405 
406     if (!m_globalResolveInstructions.isEmpty()) {
407         size_t i = 0;
408         do {
409              printStructures(&m_instructions[m_globalResolveInstructions[i]]);
410              ++i;
411         } while (i < m_globalResolveInstructions.size());
412     }
413     if (!m_propertyAccessInstructions.isEmpty()) {
414         size_t i = 0;
415         do {
416             printStructures(&m_instructions[m_propertyAccessInstructions[i]]);
417              ++i;
418         } while (i < m_propertyAccessInstructions.size());
419     }
420 #endif
421 
422     if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
423         printf("\nException Handlers:\n");
424         unsigned i = 0;
425         do {
426             printf("\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);
427             ++i;
428         } while (i < m_rareData->m_exceptionHandlers.size());
429     }
430 
431     if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
432         printf("Immediate Switch Jump Tables:\n");
433         unsigned i = 0;
434         do {
435             printf("  %1d = {\n", i);
436             int entry = 0;
437             Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
438             for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
439                 if (!*iter)
440                     continue;
441                 printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
442             }
443             printf("      }\n");
444             ++i;
445         } while (i < m_rareData->m_immediateSwitchJumpTables.size());
446     }
447 
448     if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
449         printf("\nCharacter Switch Jump Tables:\n");
450         unsigned i = 0;
451         do {
452             printf("  %1d = {\n", i);
453             int entry = 0;
454             Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
455             for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
456                 if (!*iter)
457                     continue;
458                 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
459                 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
460                 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
461         }
462             printf("      }\n");
463             ++i;
464         } while (i < m_rareData->m_characterSwitchJumpTables.size());
465     }
466 
467     if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
468         printf("\nString Switch Jump Tables:\n");
469         unsigned i = 0;
470         do {
471             printf("  %1d = {\n", i);
472             StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
473             for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
474                 printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);
475             printf("      }\n");
476             ++i;
477         } while (i < m_rareData->m_stringSwitchJumpTables.size());
478     }
479 
480     printf("\n");
481 }
482 
dump(ExecState * exec,const Vector<Instruction>::const_iterator & begin,Vector<Instruction>::const_iterator & it) const483 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
484 {
485     int location = it - begin;
486     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
487         case op_enter: {
488             printf("[%4d] enter\n", location);
489             break;
490         }
491         case op_enter_with_activation: {
492             int r0 = (++it)->u.operand;
493             printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());
494             break;
495         }
496         case op_create_arguments: {
497             printf("[%4d] create_arguments\n", location);
498             break;
499         }
500         case op_convert_this: {
501             int r0 = (++it)->u.operand;
502             printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());
503             break;
504         }
505         case op_unexpected_load: {
506             int r0 = (++it)->u.operand;
507             int k0 = (++it)->u.operand;
508             printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, unexpectedConstant(k0)).c_str());
509             break;
510         }
511         case op_new_object: {
512             int r0 = (++it)->u.operand;
513             printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());
514             break;
515         }
516         case op_new_array: {
517             int dst = (++it)->u.operand;
518             int argv = (++it)->u.operand;
519             int argc = (++it)->u.operand;
520             printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);
521             break;
522         }
523         case op_new_regexp: {
524             int r0 = (++it)->u.operand;
525             int re0 = (++it)->u.operand;
526             printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str());
527             break;
528         }
529         case op_mov: {
530             int r0 = (++it)->u.operand;
531             int r1 = (++it)->u.operand;
532             printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
533             break;
534         }
535         case op_not: {
536             printUnaryOp(location, it, "not");
537             break;
538         }
539         case op_eq: {
540             printBinaryOp(location, it, "eq");
541             break;
542         }
543         case op_eq_null: {
544             printUnaryOp(location, it, "eq_null");
545             break;
546         }
547         case op_neq: {
548             printBinaryOp(location, it, "neq");
549             break;
550         }
551         case op_neq_null: {
552             printUnaryOp(location, it, "neq_null");
553             break;
554         }
555         case op_stricteq: {
556             printBinaryOp(location, it, "stricteq");
557             break;
558         }
559         case op_nstricteq: {
560             printBinaryOp(location, it, "nstricteq");
561             break;
562         }
563         case op_less: {
564             printBinaryOp(location, it, "less");
565             break;
566         }
567         case op_lesseq: {
568             printBinaryOp(location, it, "lesseq");
569             break;
570         }
571         case op_pre_inc: {
572             int r0 = (++it)->u.operand;
573             printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());
574             break;
575         }
576         case op_pre_dec: {
577             int r0 = (++it)->u.operand;
578             printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());
579             break;
580         }
581         case op_post_inc: {
582             printUnaryOp(location, it, "post_inc");
583             break;
584         }
585         case op_post_dec: {
586             printUnaryOp(location, it, "post_dec");
587             break;
588         }
589         case op_to_jsnumber: {
590             printUnaryOp(location, it, "to_jsnumber");
591             break;
592         }
593         case op_negate: {
594             printUnaryOp(location, it, "negate");
595             break;
596         }
597         case op_add: {
598             printBinaryOp(location, it, "add");
599             ++it;
600             break;
601         }
602         case op_mul: {
603             printBinaryOp(location, it, "mul");
604             ++it;
605             break;
606         }
607         case op_div: {
608             printBinaryOp(location, it, "div");
609             break;
610         }
611         case op_mod: {
612             printBinaryOp(location, it, "mod");
613             break;
614         }
615         case op_sub: {
616             printBinaryOp(location, it, "sub");
617             ++it;
618             break;
619         }
620         case op_lshift: {
621             printBinaryOp(location, it, "lshift");
622             break;
623         }
624         case op_rshift: {
625             printBinaryOp(location, it, "rshift");
626             break;
627         }
628         case op_urshift: {
629             printBinaryOp(location, it, "urshift");
630             break;
631         }
632         case op_bitand: {
633             printBinaryOp(location, it, "bitand");
634             ++it;
635             break;
636         }
637         case op_bitxor: {
638             printBinaryOp(location, it, "bitxor");
639             ++it;
640             break;
641         }
642         case op_bitor: {
643             printBinaryOp(location, it, "bitor");
644             ++it;
645             break;
646         }
647         case op_bitnot: {
648             printUnaryOp(location, it, "bitnot");
649             break;
650         }
651         case op_instanceof: {
652             int r0 = (++it)->u.operand;
653             int r1 = (++it)->u.operand;
654             int r2 = (++it)->u.operand;
655             int r3 = (++it)->u.operand;
656             printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str());
657             break;
658         }
659         case op_typeof: {
660             printUnaryOp(location, it, "typeof");
661             break;
662         }
663         case op_is_undefined: {
664             printUnaryOp(location, it, "is_undefined");
665             break;
666         }
667         case op_is_boolean: {
668             printUnaryOp(location, it, "is_boolean");
669             break;
670         }
671         case op_is_number: {
672             printUnaryOp(location, it, "is_number");
673             break;
674         }
675         case op_is_string: {
676             printUnaryOp(location, it, "is_string");
677             break;
678         }
679         case op_is_object: {
680             printUnaryOp(location, it, "is_object");
681             break;
682         }
683         case op_is_function: {
684             printUnaryOp(location, it, "is_function");
685             break;
686         }
687         case op_in: {
688             printBinaryOp(location, it, "in");
689             break;
690         }
691         case op_resolve: {
692             int r0 = (++it)->u.operand;
693             int id0 = (++it)->u.operand;
694             printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
695             break;
696         }
697         case op_resolve_skip: {
698             int r0 = (++it)->u.operand;
699             int id0 = (++it)->u.operand;
700             int skipLevels = (++it)->u.operand;
701             printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);
702             break;
703         }
704         case op_resolve_global: {
705             int r0 = (++it)->u.operand;
706             JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
707             int id0 = (++it)->u.operand;
708             printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());
709             it += 2;
710             break;
711         }
712         case op_get_scoped_var: {
713             int r0 = (++it)->u.operand;
714             int index = (++it)->u.operand;
715             int skipLevels = (++it)->u.operand;
716             printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);
717             break;
718         }
719         case op_put_scoped_var: {
720             int index = (++it)->u.operand;
721             int skipLevels = (++it)->u.operand;
722             int r0 = (++it)->u.operand;
723             printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());
724             break;
725         }
726         case op_get_global_var: {
727             int r0 = (++it)->u.operand;
728             JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
729             int index = (++it)->u.operand;
730             printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);
731             break;
732         }
733         case op_put_global_var: {
734             JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
735             int index = (++it)->u.operand;
736             int r0 = (++it)->u.operand;
737             printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());
738             break;
739         }
740         case op_resolve_base: {
741             int r0 = (++it)->u.operand;
742             int id0 = (++it)->u.operand;
743             printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
744             break;
745         }
746         case op_resolve_with_base: {
747             int r0 = (++it)->u.operand;
748             int r1 = (++it)->u.operand;
749             int id0 = (++it)->u.operand;
750             printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
751             break;
752         }
753         case op_resolve_func: {
754             int r0 = (++it)->u.operand;
755             int r1 = (++it)->u.operand;
756             int id0 = (++it)->u.operand;
757             printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
758             break;
759         }
760         case op_get_by_id: {
761             printGetByIdOp(location, it, m_identifiers, "get_by_id");
762             break;
763         }
764         case op_get_by_id_self: {
765             printGetByIdOp(location, it, m_identifiers, "get_by_id_self");
766             break;
767         }
768         case op_get_by_id_self_list: {
769             printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");
770             break;
771         }
772         case op_get_by_id_proto: {
773             printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");
774             break;
775         }
776         case op_get_by_id_proto_list: {
777             printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");
778             break;
779         }
780         case op_get_by_id_chain: {
781             printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");
782             break;
783         }
784         case op_get_by_id_generic: {
785             printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");
786             break;
787         }
788         case op_get_array_length: {
789             printGetByIdOp(location, it, m_identifiers, "get_array_length");
790             break;
791         }
792         case op_get_string_length: {
793             printGetByIdOp(location, it, m_identifiers, "get_string_length");
794             break;
795         }
796         case op_put_by_id: {
797             printPutByIdOp(location, it, m_identifiers, "put_by_id");
798             break;
799         }
800         case op_put_by_id_replace: {
801             printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");
802             break;
803         }
804         case op_put_by_id_transition: {
805             printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");
806             break;
807         }
808         case op_put_by_id_generic: {
809             printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");
810             break;
811         }
812         case op_put_getter: {
813             int r0 = (++it)->u.operand;
814             int id0 = (++it)->u.operand;
815             int r1 = (++it)->u.operand;
816             printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
817             break;
818         }
819         case op_put_setter: {
820             int r0 = (++it)->u.operand;
821             int id0 = (++it)->u.operand;
822             int r1 = (++it)->u.operand;
823             printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
824             break;
825         }
826         case op_del_by_id: {
827             int r0 = (++it)->u.operand;
828             int r1 = (++it)->u.operand;
829             int id0 = (++it)->u.operand;
830             printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
831             break;
832         }
833         case op_get_by_val: {
834             int r0 = (++it)->u.operand;
835             int r1 = (++it)->u.operand;
836             int r2 = (++it)->u.operand;
837             printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
838             break;
839         }
840         case op_put_by_val: {
841             int r0 = (++it)->u.operand;
842             int r1 = (++it)->u.operand;
843             int r2 = (++it)->u.operand;
844             printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
845             break;
846         }
847         case op_del_by_val: {
848             int r0 = (++it)->u.operand;
849             int r1 = (++it)->u.operand;
850             int r2 = (++it)->u.operand;
851             printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
852             break;
853         }
854         case op_put_by_index: {
855             int r0 = (++it)->u.operand;
856             unsigned n0 = (++it)->u.operand;
857             int r1 = (++it)->u.operand;
858             printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());
859             break;
860         }
861         case op_jmp: {
862             int offset = (++it)->u.operand;
863             printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
864             break;
865         }
866         case op_loop: {
867             int offset = (++it)->u.operand;
868             printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
869             break;
870         }
871         case op_jtrue: {
872             printConditionalJump(begin, it, location, "jtrue");
873             break;
874         }
875         case op_loop_if_true: {
876             printConditionalJump(begin, it, location, "loop_if_true");
877             break;
878         }
879         case op_jfalse: {
880             printConditionalJump(begin, it, location, "jfalse");
881             break;
882         }
883         case op_jeq_null: {
884             printConditionalJump(begin, it, location, "jeq_null");
885             break;
886         }
887         case op_jneq_null: {
888             printConditionalJump(begin, it, location, "jneq_null");
889             break;
890         }
891         case op_jnless: {
892             int r0 = (++it)->u.operand;
893             int r1 = (++it)->u.operand;
894             int offset = (++it)->u.operand;
895             printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
896             break;
897         }
898         case op_loop_if_less: {
899             int r0 = (++it)->u.operand;
900             int r1 = (++it)->u.operand;
901             int offset = (++it)->u.operand;
902             printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
903             break;
904         }
905         case op_loop_if_lesseq: {
906             int r0 = (++it)->u.operand;
907             int r1 = (++it)->u.operand;
908             int offset = (++it)->u.operand;
909             printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
910             break;
911         }
912         case op_switch_imm: {
913             int tableIndex = (++it)->u.operand;
914             int defaultTarget = (++it)->u.operand;
915             int scrutineeRegister = (++it)->u.operand;
916             printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
917             break;
918         }
919         case op_switch_char: {
920             int tableIndex = (++it)->u.operand;
921             int defaultTarget = (++it)->u.operand;
922             int scrutineeRegister = (++it)->u.operand;
923             printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
924             break;
925         }
926         case op_switch_string: {
927             int tableIndex = (++it)->u.operand;
928             int defaultTarget = (++it)->u.operand;
929             int scrutineeRegister = (++it)->u.operand;
930             printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
931             break;
932         }
933         case op_new_func: {
934             int r0 = (++it)->u.operand;
935             int f0 = (++it)->u.operand;
936             printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);
937             break;
938         }
939         case op_new_func_exp: {
940             int r0 = (++it)->u.operand;
941             int f0 = (++it)->u.operand;
942             printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);
943             break;
944         }
945         case op_call: {
946             int dst = (++it)->u.operand;
947             int func = (++it)->u.operand;
948             int argCount = (++it)->u.operand;
949             int registerOffset = (++it)->u.operand;
950             printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
951             break;
952         }
953         case op_call_eval: {
954             int dst = (++it)->u.operand;
955             int func = (++it)->u.operand;
956             int argCount = (++it)->u.operand;
957             int registerOffset = (++it)->u.operand;
958             printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
959             break;
960         }
961         case op_tear_off_activation: {
962             int r0 = (++it)->u.operand;
963             printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());
964             break;
965         }
966         case op_tear_off_arguments: {
967             printf("[%4d] tear_off_arguments\n", location);
968             break;
969         }
970         case op_ret: {
971             int r0 = (++it)->u.operand;
972             printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());
973             break;
974         }
975         case op_construct: {
976             int dst = (++it)->u.operand;
977             int func = (++it)->u.operand;
978             int argCount = (++it)->u.operand;
979             int registerOffset = (++it)->u.operand;
980             int proto = (++it)->u.operand;
981             int thisRegister = (++it)->u.operand;
982             printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());
983             break;
984         }
985         case op_construct_verify: {
986             int r0 = (++it)->u.operand;
987             int r1 = (++it)->u.operand;
988             printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
989             break;
990         }
991         case op_get_pnames: {
992             int r0 = (++it)->u.operand;
993             int r1 = (++it)->u.operand;
994             printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
995             break;
996         }
997         case op_next_pname: {
998             int dest = (++it)->u.operand;
999             int iter = (++it)->u.operand;
1000             int offset = (++it)->u.operand;
1001             printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));
1002             break;
1003         }
1004         case op_push_scope: {
1005             int r0 = (++it)->u.operand;
1006             printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());
1007             break;
1008         }
1009         case op_pop_scope: {
1010             printf("[%4d] pop_scope\n", location);
1011             break;
1012         }
1013         case op_push_new_scope: {
1014             int r0 = (++it)->u.operand;
1015             int id0 = (++it)->u.operand;
1016             int r1 = (++it)->u.operand;
1017             printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
1018             break;
1019         }
1020         case op_jmp_scopes: {
1021             int scopeDelta = (++it)->u.operand;
1022             int offset = (++it)->u.operand;
1023             printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));
1024             break;
1025         }
1026         case op_catch: {
1027             int r0 = (++it)->u.operand;
1028             printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());
1029             break;
1030         }
1031         case op_throw: {
1032             int r0 = (++it)->u.operand;
1033             printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());
1034             break;
1035         }
1036         case op_new_error: {
1037             int r0 = (++it)->u.operand;
1038             int errorType = (++it)->u.operand;
1039             int k0 = (++it)->u.operand;
1040             printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstant(k0)).c_str());
1041             break;
1042         }
1043         case op_jsr: {
1044             int retAddrDst = (++it)->u.operand;
1045             int offset = (++it)->u.operand;
1046             printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));
1047             break;
1048         }
1049         case op_sret: {
1050             int retAddrSrc = (++it)->u.operand;
1051             printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());
1052             break;
1053         }
1054         case op_debug: {
1055             int debugHookID = (++it)->u.operand;
1056             int firstLine = (++it)->u.operand;
1057             int lastLine = (++it)->u.operand;
1058             printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
1059             break;
1060         }
1061         case op_profile_will_call: {
1062             int function = (++it)->u.operand;
1063             printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());
1064             break;
1065         }
1066         case op_profile_did_call: {
1067             int function = (++it)->u.operand;
1068             printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());
1069             break;
1070         }
1071         case op_end: {
1072             int r0 = (++it)->u.operand;
1073             printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());
1074             break;
1075         }
1076     }
1077 }
1078 
1079 #endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
1080 
1081 #if DUMP_CODE_BLOCK_STATISTICS
1082 static HashSet<CodeBlock*> liveCodeBlockSet;
1083 #endif
1084 
1085 #define FOR_EACH_MEMBER_VECTOR(macro) \
1086     macro(instructions) \
1087     macro(globalResolveInfos) \
1088     macro(structureStubInfos) \
1089     macro(callLinkInfos) \
1090     macro(linkedCallerList) \
1091     macro(identifiers) \
1092     macro(functionExpressions) \
1093     macro(constantRegisters)
1094 
1095 #define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
1096     macro(regexps) \
1097     macro(functions) \
1098     macro(unexpectedConstants) \
1099     macro(exceptionHandlers) \
1100     macro(immediateSwitchJumpTables) \
1101     macro(characterSwitchJumpTables) \
1102     macro(stringSwitchJumpTables) \
1103     macro(functionRegisterInfos)
1104 
1105 #define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \
1106     macro(expressionInfo) \
1107     macro(lineInfo) \
1108     macro(getByIdExceptionInfo) \
1109     macro(pcVector)
1110 
1111 template<typename T>
sizeInBytes(const Vector<T> & vector)1112 static size_t sizeInBytes(const Vector<T>& vector)
1113 {
1114     return vector.capacity() * sizeof(T);
1115 }
1116 
dumpStatistics()1117 void CodeBlock::dumpStatistics()
1118 {
1119 #if DUMP_CODE_BLOCK_STATISTICS
1120     #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;
1121         FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)
1122         FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)
1123         FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(DEFINE_VARS)
1124     #undef DEFINE_VARS
1125 
1126     // Non-vector data members
1127     size_t evalCodeCacheIsNotEmpty = 0;
1128 
1129     size_t symbolTableIsNotEmpty = 0;
1130     size_t symbolTableTotalSize = 0;
1131 
1132     size_t hasExceptionInfo = 0;
1133     size_t hasRareData = 0;
1134 
1135     size_t isFunctionCode = 0;
1136     size_t isGlobalCode = 0;
1137     size_t isEvalCode = 0;
1138 
1139     HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end();
1140     for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) {
1141         CodeBlock* codeBlock = *it;
1142 
1143         #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); }
1144             FOR_EACH_MEMBER_VECTOR(GET_STATS)
1145         #undef GET_STATS
1146 
1147         if (!codeBlock->m_symbolTable.isEmpty()) {
1148             symbolTableIsNotEmpty++;
1149             symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
1150         }
1151 
1152         if (codeBlock->m_exceptionInfo) {
1153             hasExceptionInfo++;
1154             #define GET_STATS(name) if (!codeBlock->m_exceptionInfo->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_exceptionInfo->m_##name); }
1155                 FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_STATS)
1156             #undef GET_STATS
1157         }
1158 
1159         if (codeBlock->m_rareData) {
1160             hasRareData++;
1161             #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }
1162                 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS)
1163             #undef GET_STATS
1164 
1165             if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty())
1166                 evalCodeCacheIsNotEmpty++;
1167         }
1168 
1169         switch (codeBlock->codeType()) {
1170             case FunctionCode:
1171                 ++isFunctionCode;
1172                 break;
1173             case GlobalCode:
1174                 ++isGlobalCode;
1175                 break;
1176             case EvalCode:
1177                 ++isEvalCode;
1178                 break;
1179         }
1180     }
1181 
1182     size_t totalSize = 0;
1183 
1184     #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize;
1185         FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE)
1186         FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE)
1187         FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_TOTAL_SIZE)
1188     #undef GET_TOTAL_SIZE
1189 
1190     totalSize += symbolTableTotalSize;
1191     totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
1192 
1193     printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
1194     printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
1195     printf("Size of all CodeBlocks: %zu\n", totalSize);
1196     printf("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
1197 
1198     printf("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size());
1199     printf("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
1200     printf("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
1201 
1202     printf("Number of CodeBlocks with exception info: %zu (%.3f%%)\n", hasExceptionInfo, static_cast<double>(hasExceptionInfo) * 100.0 / liveCodeBlockSet.size());
1203     printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
1204 
1205     #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize);
1206         FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
1207         FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
1208         FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(PRINT_STATS)
1209     #undef PRINT_STATS
1210 
1211     printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
1212     printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
1213 
1214     printf("Size of all symbolTables: %zu\n", symbolTableTotalSize);
1215 
1216 #else
1217     printf("Dumping CodeBlock statistics is not enabled.\n");
1218 #endif
1219 }
1220 
1221 
CodeBlock(ScopeNode * ownerNode,CodeType codeType,PassRefPtr<SourceProvider> sourceProvider,unsigned sourceOffset)1222 CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
1223     : m_numCalleeRegisters(0)
1224     , m_numConstants(0)
1225     , m_numVars(0)
1226     , m_numParameters(0)
1227     , m_ownerNode(ownerNode)
1228     , m_globalData(0)
1229 #ifndef NDEBUG
1230     , m_instructionCount(0)
1231 #endif
1232     , m_needsFullScopeChain(ownerNode->needsActivation())
1233     , m_usesEval(ownerNode->usesEval())
1234     , m_isNumericCompareFunction(false)
1235     , m_codeType(codeType)
1236     , m_source(sourceProvider)
1237     , m_sourceOffset(sourceOffset)
1238     , m_exceptionInfo(new ExceptionInfo)
1239 {
1240     ASSERT(m_source);
1241 
1242 #if DUMP_CODE_BLOCK_STATISTICS
1243     liveCodeBlockSet.add(this);
1244 #endif
1245 }
1246 
~CodeBlock()1247 CodeBlock::~CodeBlock()
1248 {
1249 #if !ENABLE(JIT)
1250     for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
1251         derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
1252 
1253     for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
1254         derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);
1255 #else
1256     for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
1257         if (m_globalResolveInfos[i].structure)
1258             m_globalResolveInfos[i].structure->deref();
1259     }
1260 
1261     for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
1262         m_structureStubInfos[i].deref();
1263 
1264     for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
1265         CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];
1266         if (callLinkInfo->isLinked())
1267             callLinkInfo->callee->removeCaller(callLinkInfo);
1268     }
1269 
1270     unlinkCallers();
1271 #endif
1272 
1273 #if DUMP_CODE_BLOCK_STATISTICS
1274     liveCodeBlockSet.remove(this);
1275 #endif
1276 }
1277 
1278 #if ENABLE(JIT)
unlinkCallers()1279 void CodeBlock::unlinkCallers()
1280 {
1281     size_t size = m_linkedCallerList.size();
1282     for (size_t i = 0; i < size; ++i) {
1283         CallLinkInfo* currentCaller = m_linkedCallerList[i];
1284         JIT::unlinkCall(currentCaller);
1285         currentCaller->setUnlinked();
1286     }
1287     m_linkedCallerList.clear();
1288 }
1289 #endif
1290 
derefStructures(Instruction * vPC) const1291 void CodeBlock::derefStructures(Instruction* vPC) const
1292 {
1293     Interpreter* interpreter = m_globalData->interpreter;
1294 
1295     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
1296         vPC[4].u.structure->deref();
1297         return;
1298     }
1299     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
1300         vPC[4].u.structure->deref();
1301         vPC[5].u.structure->deref();
1302         return;
1303     }
1304     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
1305         vPC[4].u.structure->deref();
1306         vPC[5].u.structureChain->deref();
1307         return;
1308     }
1309     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
1310         vPC[4].u.structure->deref();
1311         vPC[5].u.structure->deref();
1312         vPC[6].u.structureChain->deref();
1313         return;
1314     }
1315     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
1316         vPC[4].u.structure->deref();
1317         return;
1318     }
1319     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
1320         if(vPC[4].u.structure)
1321             vPC[4].u.structure->deref();
1322         return;
1323     }
1324     if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
1325         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {
1326         PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
1327         polymorphicStructures->derefStructures(vPC[5].u.operand);
1328         delete polymorphicStructures;
1329         return;
1330     }
1331 
1332     // These instructions don't ref their Structures.
1333     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));
1334 }
1335 
refStructures(Instruction * vPC) const1336 void CodeBlock::refStructures(Instruction* vPC) const
1337 {
1338     Interpreter* interpreter = m_globalData->interpreter;
1339 
1340     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
1341         vPC[4].u.structure->ref();
1342         return;
1343     }
1344     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
1345         vPC[4].u.structure->ref();
1346         vPC[5].u.structure->ref();
1347         return;
1348     }
1349     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
1350         vPC[4].u.structure->ref();
1351         vPC[5].u.structureChain->ref();
1352         return;
1353     }
1354     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
1355         vPC[4].u.structure->ref();
1356         vPC[5].u.structure->ref();
1357         vPC[6].u.structureChain->ref();
1358         return;
1359     }
1360     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
1361         vPC[4].u.structure->ref();
1362         return;
1363     }
1364 
1365     // These instructions don't ref their Structures.
1366     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));
1367 }
1368 
mark()1369 void CodeBlock::mark()
1370 {
1371     for (size_t i = 0; i < m_constantRegisters.size(); ++i)
1372         if (!m_constantRegisters[i].marked())
1373             m_constantRegisters[i].mark();
1374 
1375     for (size_t i = 0; i < m_functionExpressions.size(); ++i)
1376         m_functionExpressions[i]->body()->mark();
1377 
1378     if (m_rareData) {
1379         for (size_t i = 0; i < m_rareData->m_functions.size(); ++i)
1380             m_rareData->m_functions[i]->body()->mark();
1381 
1382         for (size_t i = 0; i < m_rareData->m_unexpectedConstants.size(); ++i) {
1383             if (!m_rareData->m_unexpectedConstants[i].marked())
1384                 m_rareData->m_unexpectedConstants[i].mark();
1385         }
1386         m_rareData->m_evalCodeCache.mark();
1387     }
1388 }
1389 
reparseForExceptionInfoIfNecessary(CallFrame * callFrame)1390 void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
1391 {
1392     if (m_exceptionInfo)
1393         return;
1394 
1395     ScopeChainNode* scopeChain = callFrame->scopeChain();
1396     if (m_needsFullScopeChain) {
1397         ScopeChain sc(scopeChain);
1398         int scopeDelta = sc.localDepth();
1399         if (m_codeType == EvalCode)
1400             scopeDelta -= static_cast<EvalCodeBlock*>(this)->baseScopeDepth();
1401         else if (m_codeType == FunctionCode)
1402             scopeDelta++; // Compilation of function code assumes activation is not on the scope chain yet.
1403         ASSERT(scopeDelta >= 0);
1404         while (scopeDelta--)
1405             scopeChain = scopeChain->next;
1406     }
1407 
1408     switch (m_codeType) {
1409         case FunctionCode: {
1410             FunctionBodyNode* ownerFunctionBodyNode = static_cast<FunctionBodyNode*>(m_ownerNode);
1411             RefPtr<FunctionBodyNode> newFunctionBody = m_globalData->parser->reparse<FunctionBodyNode>(m_globalData, ownerFunctionBodyNode);
1412             ASSERT(newFunctionBody);
1413             newFunctionBody->finishParsing(ownerFunctionBodyNode->copyParameters(), ownerFunctionBodyNode->parameterCount());
1414 
1415             m_globalData->scopeNodeBeingReparsed = newFunctionBody.get();
1416 
1417             CodeBlock& newCodeBlock = newFunctionBody->bytecodeForExceptionInfoReparse(scopeChain, this);
1418             ASSERT(newCodeBlock.m_exceptionInfo);
1419             ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
1420 
1421 #if ENABLE(JIT)
1422             JIT::compile(m_globalData, &newCodeBlock);
1423             ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
1424 #endif
1425 
1426             m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
1427 
1428             m_globalData->scopeNodeBeingReparsed = 0;
1429 
1430             break;
1431         }
1432         case EvalCode: {
1433             EvalNode* ownerEvalNode = static_cast<EvalNode*>(m_ownerNode);
1434             RefPtr<EvalNode> newEvalBody = m_globalData->parser->reparse<EvalNode>(m_globalData, ownerEvalNode);
1435 
1436             m_globalData->scopeNodeBeingReparsed = newEvalBody.get();
1437 
1438             EvalCodeBlock& newCodeBlock = newEvalBody->bytecodeForExceptionInfoReparse(scopeChain, this);
1439             ASSERT(newCodeBlock.m_exceptionInfo);
1440             ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
1441 
1442 #if ENABLE(JIT)
1443             JIT::compile(m_globalData, &newCodeBlock);
1444             ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
1445 #endif
1446 
1447             m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
1448 
1449             m_globalData->scopeNodeBeingReparsed = 0;
1450 
1451             break;
1452         }
1453         default:
1454             // CodeBlocks for Global code blocks are transient and therefore to not gain from
1455             // from throwing out there exception information.
1456             ASSERT_NOT_REACHED();
1457     }
1458 }
1459 
handlerForBytecodeOffset(unsigned bytecodeOffset)1460 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
1461 {
1462     ASSERT(bytecodeOffset < m_instructionCount);
1463 
1464     if (!m_rareData)
1465         return 0;
1466 
1467     Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
1468     for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
1469         // Handlers are ordered innermost first, so the first handler we encounter
1470         // that contains the source address is the correct handler to use.
1471         if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end >= bytecodeOffset)
1472             return &exceptionHandlers[i];
1473     }
1474 
1475     return 0;
1476 }
1477 
lineNumberForBytecodeOffset(CallFrame * callFrame,unsigned bytecodeOffset)1478 int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
1479 {
1480     ASSERT(bytecodeOffset < m_instructionCount);
1481 
1482     reparseForExceptionInfoIfNecessary(callFrame);
1483     ASSERT(m_exceptionInfo);
1484 
1485     if (!m_exceptionInfo->m_lineInfo.size())
1486         return m_ownerNode->source().firstLine(); // Empty function
1487 
1488     int low = 0;
1489     int high = m_exceptionInfo->m_lineInfo.size();
1490     while (low < high) {
1491         int mid = low + (high - low) / 2;
1492         if (m_exceptionInfo->m_lineInfo[mid].instructionOffset <= bytecodeOffset)
1493             low = mid + 1;
1494         else
1495             high = mid;
1496     }
1497 
1498     if (!low)
1499         return m_ownerNode->source().firstLine();
1500     return m_exceptionInfo->m_lineInfo[low - 1].lineNumber;
1501 }
1502 
expressionRangeForBytecodeOffset(CallFrame * callFrame,unsigned bytecodeOffset,int & divot,int & startOffset,int & endOffset)1503 int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
1504 {
1505     ASSERT(bytecodeOffset < m_instructionCount);
1506 
1507     reparseForExceptionInfoIfNecessary(callFrame);
1508     ASSERT(m_exceptionInfo);
1509 
1510     if (!m_exceptionInfo->m_expressionInfo.size()) {
1511         // We didn't think anything could throw.  Apparently we were wrong.
1512         startOffset = 0;
1513         endOffset = 0;
1514         divot = 0;
1515         return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
1516     }
1517 
1518     int low = 0;
1519     int high = m_exceptionInfo->m_expressionInfo.size();
1520     while (low < high) {
1521         int mid = low + (high - low) / 2;
1522         if (m_exceptionInfo->m_expressionInfo[mid].instructionOffset <= bytecodeOffset)
1523             low = mid + 1;
1524         else
1525             high = mid;
1526     }
1527 
1528     ASSERT(low);
1529     if (!low) {
1530         startOffset = 0;
1531         endOffset = 0;
1532         divot = 0;
1533         return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
1534     }
1535 
1536     startOffset = m_exceptionInfo->m_expressionInfo[low - 1].startOffset;
1537     endOffset = m_exceptionInfo->m_expressionInfo[low - 1].endOffset;
1538     divot = m_exceptionInfo->m_expressionInfo[low - 1].divotPoint + m_sourceOffset;
1539     return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
1540 }
1541 
getByIdExceptionInfoForBytecodeOffset(CallFrame * callFrame,unsigned bytecodeOffset,OpcodeID & opcodeID)1542 bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
1543 {
1544     ASSERT(bytecodeOffset < m_instructionCount);
1545 
1546     reparseForExceptionInfoIfNecessary(callFrame);
1547     ASSERT(m_exceptionInfo);
1548 
1549     if (!m_exceptionInfo->m_getByIdExceptionInfo.size())
1550         return false;
1551 
1552     int low = 0;
1553     int high = m_exceptionInfo->m_getByIdExceptionInfo.size();
1554     while (low < high) {
1555         int mid = low + (high - low) / 2;
1556         if (m_exceptionInfo->m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset)
1557             low = mid + 1;
1558         else
1559             high = mid;
1560     }
1561 
1562     if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset)
1563         return false;
1564 
1565     opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpConstruct ? op_construct : op_instanceof;
1566     return true;
1567 }
1568 
1569 #if ENABLE(JIT)
functionRegisterForBytecodeOffset(unsigned bytecodeOffset,int & functionRegisterIndex)1570 bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
1571 {
1572     ASSERT(bytecodeOffset < m_instructionCount);
1573 
1574     if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
1575         return false;
1576 
1577     int low = 0;
1578     int high = m_rareData->m_functionRegisterInfos.size();
1579     while (low < high) {
1580         int mid = low + (high - low) / 2;
1581         if (m_rareData->m_functionRegisterInfos[mid].bytecodeOffset <= bytecodeOffset)
1582             low = mid + 1;
1583         else
1584             high = mid;
1585     }
1586 
1587     if (!low || m_rareData->m_functionRegisterInfos[low - 1].bytecodeOffset != bytecodeOffset)
1588         return false;
1589 
1590     functionRegisterIndex = m_rareData->m_functionRegisterInfos[low - 1].functionRegisterIndex;
1591     return true;
1592 }
1593 #endif
1594 
1595 #if !ENABLE(JIT)
hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)1596 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
1597 {
1598     if (m_globalResolveInstructions.isEmpty())
1599         return false;
1600 
1601     int low = 0;
1602     int high = m_globalResolveInstructions.size();
1603     while (low < high) {
1604         int mid = low + (high - low) / 2;
1605         if (m_globalResolveInstructions[mid] <= bytecodeOffset)
1606             low = mid + 1;
1607         else
1608             high = mid;
1609     }
1610 
1611     if (!low || m_globalResolveInstructions[low - 1] != bytecodeOffset)
1612         return false;
1613     return true;
1614 }
1615 #else
hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)1616 bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
1617 {
1618     if (m_globalResolveInfos.isEmpty())
1619         return false;
1620 
1621     int low = 0;
1622     int high = m_globalResolveInfos.size();
1623     while (low < high) {
1624         int mid = low + (high - low) / 2;
1625         if (m_globalResolveInfos[mid].bytecodeOffset <= bytecodeOffset)
1626             low = mid + 1;
1627         else
1628             high = mid;
1629     }
1630 
1631     if (!low || m_globalResolveInfos[low - 1].bytecodeOffset != bytecodeOffset)
1632         return false;
1633     return true;
1634 }
1635 #endif
1636 
1637 #if ENABLE(JIT)
setJITCode(JITCodeRef & jitCode)1638 void CodeBlock::setJITCode(JITCodeRef& jitCode)
1639 {
1640     m_jitCode = jitCode;
1641 #if !ENABLE(OPCODE_SAMPLING)
1642     if (!BytecodeGenerator::dumpsGeneratedCode())
1643         m_instructions.clear();
1644 #endif
1645 }
1646 #endif
1647 
shrinkToFit()1648 void CodeBlock::shrinkToFit()
1649 {
1650     m_instructions.shrinkToFit();
1651 
1652 #if !ENABLE(JIT)
1653     m_propertyAccessInstructions.shrinkToFit();
1654     m_globalResolveInstructions.shrinkToFit();
1655 #else
1656     m_structureStubInfos.shrinkToFit();
1657     m_globalResolveInfos.shrinkToFit();
1658     m_callLinkInfos.shrinkToFit();
1659     m_linkedCallerList.shrinkToFit();
1660 #endif
1661 
1662     m_identifiers.shrinkToFit();
1663     m_functionExpressions.shrinkToFit();
1664     m_constantRegisters.shrinkToFit();
1665 
1666     if (m_exceptionInfo) {
1667         m_exceptionInfo->m_expressionInfo.shrinkToFit();
1668         m_exceptionInfo->m_lineInfo.shrinkToFit();
1669         m_exceptionInfo->m_getByIdExceptionInfo.shrinkToFit();
1670     }
1671 
1672     if (m_rareData) {
1673         m_rareData->m_exceptionHandlers.shrinkToFit();
1674         m_rareData->m_functions.shrinkToFit();
1675         m_rareData->m_unexpectedConstants.shrinkToFit();
1676         m_rareData->m_regexps.shrinkToFit();
1677         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
1678         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
1679         m_rareData->m_stringSwitchJumpTables.shrinkToFit();
1680 #if ENABLE(JIT)
1681         m_rareData->m_functionRegisterInfos.shrinkToFit();
1682 #endif
1683     }
1684 }
1685 
1686 } // namespace JSC
1687