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