]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecode/CodeBlock.cpp
JavaScriptCore-1218.34.tar.gz
[apple/javascriptcore.git] / bytecode / CodeBlock.cpp
CommitLineData
9dae56ea 1/*
93a37866 2 * Copyright (C) 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
9dae56ea
A
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
14957cd0 33#include "BytecodeGenerator.h"
93a37866 34#include "CallLinkStatus.h"
6fe7ccc8 35#include "DFGCapabilities.h"
93a37866 36#include "DFGCommon.h"
6fe7ccc8
A
37#include "DFGNode.h"
38#include "DFGRepatch.h"
14957cd0 39#include "Debugger.h"
9dae56ea 40#include "Interpreter.h"
14957cd0 41#include "JIT.h"
6fe7ccc8 42#include "JITStubs.h"
14957cd0 43#include "JSActivation.h"
93a37866 44#include "JSCJSValue.h"
f9bf01c6 45#include "JSFunction.h"
93a37866 46#include "JSNameScope.h"
6fe7ccc8 47#include "LowLevelInterpreter.h"
93a37866
A
48#include "Operations.h"
49#include "ReduceWhitespace.h"
14957cd0 50#include "RepatchBuffer.h"
93a37866 51#include "SlotVisitorInlines.h"
9dae56ea 52#include <stdio.h>
93a37866 53#include <wtf/CommaPrinter.h>
9dae56ea 54#include <wtf/StringExtras.h>
93a37866 55#include <wtf/StringPrintStream.h>
9dae56ea 56
6fe7ccc8
A
57#if ENABLE(DFG_JIT)
58#include "DFGOperations.h"
59#endif
60
9dae56ea
A
61#define DUMP_CODE_BLOCK_STATISTICS 0
62
63namespace JSC {
64
6fe7ccc8
A
65#if ENABLE(DFG_JIT)
66using namespace DFG;
67#endif
9dae56ea 68
93a37866 69String CodeBlock::inferredName() const
9dae56ea 70{
93a37866
A
71 switch (codeType()) {
72 case GlobalCode:
73 return "<global>";
74 case EvalCode:
75 return "<eval>";
76 case FunctionCode:
77 return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().string();
78 default:
79 CRASH();
80 return String();
81 }
82}
83
84CodeBlockHash CodeBlock::hash() const
85{
86 return CodeBlockHash(ownerExecutable()->source(), specializationKind());
87}
88
89String CodeBlock::sourceCodeForTools() const
90{
91 if (codeType() != FunctionCode)
92 return ownerExecutable()->source().toString();
93
94 SourceProvider* provider = source();
95 FunctionExecutable* executable = jsCast<FunctionExecutable*>(ownerExecutable());
96 UnlinkedFunctionExecutable* unlinked = executable->unlinkedExecutable();
97 unsigned unlinkedStartOffset = unlinked->startOffset();
98 unsigned linkedStartOffset = executable->source().startOffset();
99 int delta = linkedStartOffset - unlinkedStartOffset;
100 StringBuilder builder;
101 builder.append("function ");
102 builder.append(provider->getRange(
103 delta + unlinked->functionStartOffset(),
104 delta + unlinked->startOffset() + unlinked->sourceLength()));
105 return builder.toString();
106}
107
108String CodeBlock::sourceCodeOnOneLine() const
109{
110 return reduceWhitespace(sourceCodeForTools());
111}
112
113void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const
114{
115 out.print(inferredName(), "#", hash(), ":[", RawPointer(this), "->", RawPointer(ownerExecutable()), ", ", jitType, codeType());
116 if (codeType() == FunctionCode)
117 out.print(specializationKind());
118 out.print("]");
119}
120
121void CodeBlock::dump(PrintStream& out) const
122{
123 dumpAssumingJITType(out, getJITType());
124}
125
126static String escapeQuotes(const String& str)
127{
128 String result = str;
14957cd0
A
129 size_t pos = 0;
130 while ((pos = result.find('\"', pos)) != notFound) {
93a37866 131 result = makeString(result.substringSharingImpl(0, pos), "\"\\\"\"", result.substringSharingImpl(pos + 1));
9dae56ea
A
132 pos += 4;
133 }
134 return result;
135}
136
93a37866 137static String valueToSourceString(ExecState* exec, JSValue val)
9dae56ea 138{
ba379fdc 139 if (!val)
93a37866 140 return ASCIILiteral("0");
ba379fdc 141
f9bf01c6 142 if (val.isString())
93a37866 143 return makeString("\"", escapeQuotes(val.toString(exec)->value(exec)), "\"");
9dae56ea 144
93a37866 145 return toString(val);
9dae56ea
A
146}
147
f9bf01c6 148static CString constantName(ExecState* exec, int k, JSValue value)
9dae56ea 149{
93a37866 150 return makeString(valueToSourceString(exec, value), "(@k", String::number(k - FirstConstantRegisterIndex), ")").utf8();
9dae56ea
A
151}
152
f9bf01c6 153static CString idName(int id0, const Identifier& ident)
9dae56ea 154{
93a37866 155 return makeString(ident.string(), "(@id", String::number(id0), ")").utf8();
9dae56ea
A
156}
157
f9bf01c6 158CString CodeBlock::registerName(ExecState* exec, int r) const
9dae56ea 159{
f9bf01c6
A
160 if (r == missingThisObjectMarker())
161 return "<null>";
162
163 if (isConstantRegisterIndex(r))
164 return constantName(exec, r, getConstant(r));
165
93a37866 166 return makeString("r", String::number(r)).utf8();
9dae56ea
A
167}
168
93a37866 169static String regexpToSourceString(RegExp* regExp)
9dae56ea 170{
f9bf01c6
A
171 char postfix[5] = { '/', 0, 0, 0, 0 };
172 int index = 1;
9dae56ea 173 if (regExp->global())
f9bf01c6 174 postfix[index++] = 'g';
9dae56ea 175 if (regExp->ignoreCase())
f9bf01c6 176 postfix[index++] = 'i';
9dae56ea 177 if (regExp->multiline())
f9bf01c6 178 postfix[index] = 'm';
9dae56ea 179
93a37866 180 return makeString("/", regExp->pattern(), postfix);
9dae56ea
A
181}
182
183static CString regexpName(int re, RegExp* regexp)
184{
93a37866 185 return makeString(regexpToSourceString(regexp), "(@re", String::number(re), ")").utf8();
9dae56ea
A
186}
187
93a37866 188static String pointerToSourceString(void* p)
9dae56ea
A
189{
190 char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
191 snprintf(buffer, sizeof(buffer), "%p", p);
192 return buffer;
193}
194
195NEVER_INLINE static const char* debugHookName(int debugHookID)
196{
197 switch (static_cast<DebugHookID>(debugHookID)) {
198 case DidEnterCallFrame:
199 return "didEnterCallFrame";
200 case WillLeaveCallFrame:
201 return "willLeaveCallFrame";
202 case WillExecuteStatement:
203 return "willExecuteStatement";
204 case WillExecuteProgram:
205 return "willExecuteProgram";
206 case DidExecuteProgram:
207 return "didExecuteProgram";
208 case DidReachBreakpoint:
209 return "didReachBreakpoint";
210 }
211
93a37866 212 RELEASE_ASSERT_NOT_REACHED();
9dae56ea
A
213 return "";
214}
215
93a37866 216void CodeBlock::printUnaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
9dae56ea
A
217{
218 int r0 = (++it)->u.operand;
219 int r1 = (++it)->u.operand;
220
93a37866 221 out.printf("[%4d] %s\t\t %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data());
9dae56ea
A
222}
223
93a37866 224void CodeBlock::printBinaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
9dae56ea
A
225{
226 int r0 = (++it)->u.operand;
227 int r1 = (++it)->u.operand;
228 int r2 = (++it)->u.operand;
93a37866 229 out.printf("[%4d] %s\t\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
9dae56ea
A
230}
231
93a37866 232void CodeBlock::printConditionalJump(PrintStream& out, ExecState* exec, const Instruction*, const Instruction*& it, int location, const char* op)
9dae56ea
A
233{
234 int r0 = (++it)->u.operand;
235 int offset = (++it)->u.operand;
93a37866 236 out.printf("[%4d] %s\t\t %s, %d(->%d)", location, op, registerName(exec, r0).data(), offset, location + offset);
9dae56ea
A
237}
238
93a37866 239void CodeBlock::printGetByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it)
9dae56ea 240{
93a37866
A
241 const char* op;
242 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
243 case op_get_by_id:
244 op = "get_by_id";
245 break;
246 case op_get_by_id_out_of_line:
247 op = "get_by_id_out_of_line";
248 break;
249 case op_get_by_id_self:
250 op = "get_by_id_self";
251 break;
252 case op_get_by_id_proto:
253 op = "get_by_id_proto";
254 break;
255 case op_get_by_id_chain:
256 op = "get_by_id_chain";
257 break;
258 case op_get_by_id_getter_self:
259 op = "get_by_id_getter_self";
260 break;
261 case op_get_by_id_getter_proto:
262 op = "get_by_id_getter_proto";
263 break;
264 case op_get_by_id_getter_chain:
265 op = "get_by_id_getter_chain";
266 break;
267 case op_get_by_id_custom_self:
268 op = "get_by_id_custom_self";
269 break;
270 case op_get_by_id_custom_proto:
271 op = "get_by_id_custom_proto";
272 break;
273 case op_get_by_id_custom_chain:
274 op = "get_by_id_custom_chain";
275 break;
276 case op_get_by_id_generic:
277 op = "get_by_id_generic";
278 break;
279 case op_get_array_length:
280 op = "array_length";
281 break;
282 case op_get_string_length:
283 op = "string_length";
284 break;
285 default:
286 RELEASE_ASSERT_NOT_REACHED();
287 op = 0;
288 }
9dae56ea
A
289 int r0 = (++it)->u.operand;
290 int r1 = (++it)->u.operand;
291 int id0 = (++it)->u.operand;
93a37866
A
292 out.printf("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
293 it += 4; // Increment up to the value profiler.
6fe7ccc8
A
294}
295
93a37866
A
296#if ENABLE(JIT) || ENABLE(LLINT) // unused in some configurations
297static void dumpStructure(PrintStream& out, const char* name, ExecState* exec, Structure* structure, Identifier& ident)
6fe7ccc8 298{
93a37866
A
299 if (!structure)
300 return;
301
302 out.printf("%s = %p", name, structure);
303
304 PropertyOffset offset = structure->get(exec->vm(), ident);
305 if (offset != invalidOffset)
306 out.printf(" (offset = %d)", offset);
9dae56ea 307}
93a37866 308#endif
9dae56ea 309
93a37866
A
310#if ENABLE(JIT) // unused when not ENABLE(JIT), leading to silly warnings
311static void dumpChain(PrintStream& out, ExecState* exec, StructureChain* chain, Identifier& ident)
9dae56ea 312{
93a37866
A
313 out.printf("chain = %p: [", chain);
314 bool first = true;
315 for (WriteBarrier<Structure>* currentStructure = chain->head();
316 *currentStructure;
317 ++currentStructure) {
318 if (first)
319 first = false;
320 else
321 out.printf(", ");
322 dumpStructure(out, "struct", exec, currentStructure->get(), ident);
323 }
324 out.printf("]");
9dae56ea 325}
93a37866 326#endif
9dae56ea 327
93a37866 328void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int location)
9dae56ea 329{
93a37866 330 Instruction* instruction = instructions().begin() + location;
9dae56ea 331
93a37866
A
332 Identifier& ident = identifier(instruction[3].u.operand);
333
334 UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
335
336#if ENABLE(LLINT)
337 if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
338 out.printf(" llint(array_length)");
339 else if (Structure* structure = instruction[4].u.structure.get()) {
340 out.printf(" llint(");
341 dumpStructure(out, "struct", exec, structure, ident);
342 out.printf(")");
9dae56ea 343 }
93a37866 344#endif
9dae56ea 345
93a37866
A
346#if ENABLE(JIT)
347 if (numberOfStructureStubInfos()) {
348 StructureStubInfo& stubInfo = getStubInfo(location);
349 if (stubInfo.seen) {
350 out.printf(" jit(");
351
352 Structure* baseStructure = 0;
353 Structure* prototypeStructure = 0;
354 StructureChain* chain = 0;
355 PolymorphicAccessStructureList* structureList = 0;
356 int listSize = 0;
357
358 switch (stubInfo.accessType) {
359 case access_get_by_id_self:
360 out.printf("self");
361 baseStructure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
362 break;
363 case access_get_by_id_proto:
364 out.printf("proto");
365 baseStructure = stubInfo.u.getByIdProto.baseObjectStructure.get();
366 prototypeStructure = stubInfo.u.getByIdProto.prototypeStructure.get();
367 break;
368 case access_get_by_id_chain:
369 out.printf("chain");
370 baseStructure = stubInfo.u.getByIdChain.baseObjectStructure.get();
371 chain = stubInfo.u.getByIdChain.chain.get();
372 break;
373 case access_get_by_id_self_list:
374 out.printf("self_list");
375 structureList = stubInfo.u.getByIdSelfList.structureList;
376 listSize = stubInfo.u.getByIdSelfList.listSize;
377 break;
378 case access_get_by_id_proto_list:
379 out.printf("proto_list");
380 structureList = stubInfo.u.getByIdProtoList.structureList;
381 listSize = stubInfo.u.getByIdProtoList.listSize;
382 break;
383 case access_unset:
384 out.printf("unset");
385 break;
386 case access_get_by_id_generic:
387 out.printf("generic");
388 break;
389 case access_get_array_length:
390 out.printf("array_length");
391 break;
392 case access_get_string_length:
393 out.printf("string_length");
394 break;
395 default:
396 RELEASE_ASSERT_NOT_REACHED();
397 break;
398 }
399
400 if (baseStructure) {
401 out.printf(", ");
402 dumpStructure(out, "struct", exec, baseStructure, ident);
403 }
404
405 if (prototypeStructure) {
406 out.printf(", ");
407 dumpStructure(out, "prototypeStruct", exec, baseStructure, ident);
408 }
409
410 if (chain) {
411 out.printf(", ");
412 dumpChain(out, exec, chain, ident);
413 }
414
415 if (structureList) {
416 out.printf(", list = %p: [", structureList);
417 for (int i = 0; i < listSize; ++i) {
418 if (i)
419 out.printf(", ");
420 out.printf("(");
421 dumpStructure(out, "base", exec, structureList->list[i].base.get(), ident);
422 if (structureList->list[i].isChain) {
423 if (structureList->list[i].u.chain.get()) {
424 out.printf(", ");
425 dumpChain(out, exec, structureList->list[i].u.chain.get(), ident);
426 }
427 } else {
428 if (structureList->list[i].u.proto.get()) {
429 out.printf(", ");
430 dumpStructure(out, "proto", exec, structureList->list[i].u.proto.get(), ident);
431 }
432 }
433 out.printf(")");
434 }
435 out.printf("]");
436 }
437 out.printf(")");
9dae56ea 438 }
9dae56ea 439 }
93a37866 440#endif
9dae56ea
A
441}
442
93a37866 443void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, CacheDumpMode cacheDumpMode)
9dae56ea 444{
93a37866
A
445 int func = (++it)->u.operand;
446 int argCount = (++it)->u.operand;
447 int registerOffset = (++it)->u.operand;
448 out.printf("[%4d] %s\t %s, %d, %d", location, op, registerName(exec, func).data(), argCount, registerOffset);
449 if (cacheDumpMode == DumpCaches) {
450#if ENABLE(LLINT)
451 LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo;
452 if (callLinkInfo->lastSeenCallee) {
453 out.printf(
454 " llint(%p, exec %p)",
455 callLinkInfo->lastSeenCallee.get(),
456 callLinkInfo->lastSeenCallee->executable());
457 }
458#endif
459#if ENABLE(JIT)
460 if (numberOfCallLinkInfos()) {
461 JSFunction* target = getCallLinkInfo(location).lastSeenCallee.get();
462 if (target)
463 out.printf(" jit(%p, exec %p)", target, target->executable());
464 }
465#endif
466 out.print(" status(", CallLinkStatus::computeFor(this, location), ")");
467 }
468 it += 2;
9dae56ea
A
469}
470
93a37866 471void CodeBlock::printPutByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
9dae56ea 472{
93a37866
A
473 int r0 = (++it)->u.operand;
474 int id0 = (++it)->u.operand;
475 int r1 = (++it)->u.operand;
476 out.printf("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
477 it += 5;
9dae56ea 478}
9dae56ea 479
93a37866 480void CodeBlock::printStructure(PrintStream& out, const char* name, const Instruction* vPC, int operand)
9dae56ea 481{
6fe7ccc8 482 unsigned instructionOffset = vPC - instructions().begin();
93a37866 483 out.printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data());
9dae56ea
A
484}
485
93a37866 486void CodeBlock::printStructures(PrintStream& out, const Instruction* vPC)
9dae56ea 487{
93a37866 488 Interpreter* interpreter = m_vm->interpreter;
6fe7ccc8 489 unsigned instructionOffset = vPC - instructions().begin();
9dae56ea
A
490
491 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
93a37866 492 printStructure(out, "get_by_id", vPC, 4);
9dae56ea
A
493 return;
494 }
495 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
93a37866 496 printStructure(out, "get_by_id_self", vPC, 4);
9dae56ea
A
497 return;
498 }
499 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
93a37866 500 out.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());
9dae56ea
A
501 return;
502 }
503 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
93a37866 504 out.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());
9dae56ea
A
505 return;
506 }
507 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
93a37866 508 out.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());
9dae56ea
A
509 return;
510 }
511 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
93a37866 512 printStructure(out, "put_by_id", vPC, 4);
9dae56ea
A
513 return;
514 }
515 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
93a37866 516 printStructure(out, "put_by_id_replace", vPC, 4);
4e4e5a6f
A
517 return;
518 }
9dae56ea
A
519
520 // These m_instructions doesn't ref Structures.
521 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));
522}
523
93a37866 524void CodeBlock::dumpBytecode(PrintStream& out)
9dae56ea 525{
93a37866
A
526 // We only use the ExecState* for things that don't actually lead to JS execution,
527 // like converting a JSString to a String. Hence the globalExec is appropriate.
528 ExecState* exec = m_globalObject->globalExec();
529
9dae56ea
A
530 size_t instructionCount = 0;
531
6fe7ccc8 532 for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
9dae56ea
A
533 ++instructionCount;
534
93a37866
A
535 out.print(*this);
536 out.printf(
537 ": %lu m_instructions; %lu bytes; %d parameter(s); %d callee register(s); %d variable(s)",
6fe7ccc8
A
538 static_cast<unsigned long>(instructions().size()),
539 static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
93a37866
A
540 m_numParameters, m_numCalleeRegisters, m_numVars);
541 if (symbolTable() && symbolTable()->captureCount()) {
542 out.printf(
543 "; %d captured var(s) (from r%d to r%d, inclusive)",
544 symbolTable()->captureCount(), symbolTable()->captureStart(), symbolTable()->captureEnd() - 1);
545 }
546 if (usesArguments()) {
547 out.printf(
548 "; uses arguments, in r%d, r%d",
549 argumentsRegister(),
550 unmodifiedArgumentsRegister(argumentsRegister()));
551 }
552 if (needsFullScopeChain() && codeType() == FunctionCode)
553 out.printf("; activation in r%d", activationRegister());
554 out.print("\n\nSource: ", sourceCodeOnOneLine(), "\n\n");
555
556 const Instruction* begin = instructions().begin();
557 const Instruction* end = instructions().end();
558 for (const Instruction* it = begin; it != end; ++it)
559 dumpBytecode(out, exec, begin, it);
9dae56ea
A
560
561 if (!m_identifiers.isEmpty()) {
93a37866 562 out.printf("\nIdentifiers:\n");
9dae56ea
A
563 size_t i = 0;
564 do {
93a37866 565 out.printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].string().utf8().data());
9dae56ea
A
566 ++i;
567 } while (i != m_identifiers.size());
568 }
569
570 if (!m_constantRegisters.isEmpty()) {
93a37866 571 out.printf("\nConstants:\n");
9dae56ea
A
572 size_t i = 0;
573 do {
93a37866 574 out.printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data());
9dae56ea 575 ++i;
9dae56ea
A
576 } while (i < m_constantRegisters.size());
577 }
578
93a37866
A
579 if (size_t count = m_unlinkedCode->numberOfRegExps()) {
580 out.printf("\nm_regexps:\n");
9dae56ea
A
581 size_t i = 0;
582 do {
93a37866 583 out.printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).utf8().data());
9dae56ea 584 ++i;
93a37866 585 } while (i < count);
9dae56ea
A
586 }
587
588#if ENABLE(JIT)
93a37866
A
589 if (!m_structureStubInfos.isEmpty())
590 out.printf("\nStructures:\n");
9dae56ea
A
591#endif
592
593 if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
93a37866 594 out.printf("\nException Handlers:\n");
9dae56ea
A
595 unsigned i = 0;
596 do {
93a37866 597 out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] depth: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target, m_rareData->m_exceptionHandlers[i].scopeDepth);
9dae56ea
A
598 ++i;
599 } while (i < m_rareData->m_exceptionHandlers.size());
600 }
601
602 if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
93a37866 603 out.printf("Immediate Switch Jump Tables:\n");
9dae56ea
A
604 unsigned i = 0;
605 do {
93a37866 606 out.printf(" %1d = {\n", i);
9dae56ea
A
607 int entry = 0;
608 Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
609 for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
610 if (!*iter)
611 continue;
93a37866 612 out.printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
9dae56ea 613 }
93a37866 614 out.printf(" }\n");
9dae56ea
A
615 ++i;
616 } while (i < m_rareData->m_immediateSwitchJumpTables.size());
617 }
618
619 if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
93a37866 620 out.printf("\nCharacter Switch Jump Tables:\n");
9dae56ea
A
621 unsigned i = 0;
622 do {
93a37866 623 out.printf(" %1d = {\n", i);
9dae56ea
A
624 int entry = 0;
625 Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
626 for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
627 if (!*iter)
628 continue;
629 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
630 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
93a37866
A
631 out.printf("\t\t\"%s\" => %04d\n", String(&ch, 1).utf8().data(), *iter);
632 }
633 out.printf(" }\n");
9dae56ea
A
634 ++i;
635 } while (i < m_rareData->m_characterSwitchJumpTables.size());
636 }
637
638 if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
93a37866 639 out.printf("\nString Switch Jump Tables:\n");
9dae56ea
A
640 unsigned i = 0;
641 do {
93a37866 642 out.printf(" %1d = {\n", i);
9dae56ea
A
643 StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
644 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
93a37866
A
645 out.printf("\t\t\"%s\" => %04d\n", String(iter->key).utf8().data(), iter->value.branchOffset);
646 out.printf(" }\n");
9dae56ea
A
647 ++i;
648 } while (i < m_rareData->m_stringSwitchJumpTables.size());
649 }
650
93a37866
A
651 out.printf("\n");
652}
653
654void CodeBlock::beginDumpProfiling(PrintStream& out, bool& hasPrintedProfiling)
655{
656 if (hasPrintedProfiling) {
657 out.print("; ");
658 return;
659 }
660
661 out.print(" ");
662 hasPrintedProfiling = true;
663}
664
665void CodeBlock::dumpValueProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
666{
667 ++it;
668#if ENABLE(VALUE_PROFILER)
669 CString description = it->u.profile->briefDescription();
670 if (!description.length())
671 return;
672 beginDumpProfiling(out, hasPrintedProfiling);
673 out.print(description);
674#else
675 UNUSED_PARAM(out);
676 UNUSED_PARAM(hasPrintedProfiling);
677#endif
678}
679
680void CodeBlock::dumpArrayProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
681{
682 ++it;
683#if ENABLE(VALUE_PROFILER)
684 CString description = it->u.arrayProfile->briefDescription(this);
685 if (!description.length())
686 return;
687 beginDumpProfiling(out, hasPrintedProfiling);
688 out.print(description);
689#else
690 UNUSED_PARAM(out);
691 UNUSED_PARAM(hasPrintedProfiling);
692#endif
693}
694
695#if ENABLE(VALUE_PROFILER)
696void CodeBlock::dumpRareCaseProfile(PrintStream& out, const char* name, RareCaseProfile* profile, bool& hasPrintedProfiling)
697{
698 if (!profile || !profile->m_counter)
699 return;
700
701 beginDumpProfiling(out, hasPrintedProfiling);
702 out.print(name, profile->m_counter);
9dae56ea 703}
93a37866 704#endif
9dae56ea 705
93a37866 706void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instruction* begin, const Instruction*& it)
9dae56ea
A
707{
708 int location = it - begin;
93a37866 709 bool hasPrintedProfiling = false;
9dae56ea
A
710 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
711 case op_enter: {
93a37866 712 out.printf("[%4d] enter", location);
9dae56ea
A
713 break;
714 }
14957cd0 715 case op_create_activation: {
9dae56ea 716 int r0 = (++it)->u.operand;
93a37866 717 out.printf("[%4d] create_activation %s", location, registerName(exec, r0).data());
9dae56ea
A
718 break;
719 }
720 case op_create_arguments: {
14957cd0 721 int r0 = (++it)->u.operand;
93a37866 722 out.printf("[%4d] create_arguments\t %s", location, registerName(exec, r0).data());
9dae56ea
A
723 break;
724 }
14957cd0
A
725 case op_init_lazy_reg: {
726 int r0 = (++it)->u.operand;
93a37866 727 out.printf("[%4d] init_lazy_reg\t %s", location, registerName(exec, r0).data());
14957cd0
A
728 break;
729 }
730 case op_get_callee: {
731 int r0 = (++it)->u.operand;
93a37866
A
732 out.printf("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data());
733 ++it;
14957cd0
A
734 break;
735 }
736 case op_create_this: {
737 int r0 = (++it)->u.operand;
738 int r1 = (++it)->u.operand;
93a37866
A
739 unsigned inferredInlineCapacity = (++it)->u.operand;
740 out.printf("[%4d] create_this %s, %s, %u", location, registerName(exec, r0).data(), registerName(exec, r1).data(), inferredInlineCapacity);
9dae56ea
A
741 break;
742 }
ba379fdc 743 case op_convert_this: {
9dae56ea 744 int r0 = (++it)->u.operand;
93a37866
A
745 out.printf("[%4d] convert_this\t %s", location, registerName(exec, r0).data());
746 ++it; // Skip value profile.
14957cd0
A
747 break;
748 }
9dae56ea
A
749 case op_new_object: {
750 int r0 = (++it)->u.operand;
93a37866
A
751 unsigned inferredInlineCapacity = (++it)->u.operand;
752 out.printf("[%4d] new_object\t %s, %u", location, registerName(exec, r0).data(), inferredInlineCapacity);
753 ++it; // Skip object allocation profile.
9dae56ea
A
754 break;
755 }
756 case op_new_array: {
757 int dst = (++it)->u.operand;
758 int argv = (++it)->u.operand;
759 int argc = (++it)->u.operand;
93a37866
A
760 out.printf("[%4d] new_array\t %s, %s, %d", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc);
761 ++it; // Skip array allocation profile.
762 break;
763 }
764 case op_new_array_with_size: {
765 int dst = (++it)->u.operand;
766 int length = (++it)->u.operand;
767 out.printf("[%4d] new_array_with_size\t %s, %s", location, registerName(exec, dst).data(), registerName(exec, length).data());
768 ++it; // Skip array allocation profile.
9dae56ea
A
769 break;
770 }
14957cd0
A
771 case op_new_array_buffer: {
772 int dst = (++it)->u.operand;
773 int argv = (++it)->u.operand;
774 int argc = (++it)->u.operand;
93a37866
A
775 out.printf("[%4d] new_array_buffer\t %s, %d, %d", location, registerName(exec, dst).data(), argv, argc);
776 ++it; // Skip array allocation profile.
14957cd0
A
777 break;
778 }
9dae56ea
A
779 case op_new_regexp: {
780 int r0 = (++it)->u.operand;
781 int re0 = (++it)->u.operand;
93a37866
A
782 out.printf("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data());
783 if (r0 >=0 && r0 < (int)m_unlinkedCode->numberOfRegExps())
784 out.printf("%s", regexpName(re0, regexp(re0)).data());
6fe7ccc8 785 else
93a37866 786 out.printf("bad_regexp(%d)", re0);
9dae56ea
A
787 break;
788 }
789 case op_mov: {
790 int r0 = (++it)->u.operand;
791 int r1 = (++it)->u.operand;
93a37866 792 out.printf("[%4d] mov\t\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data());
9dae56ea
A
793 break;
794 }
795 case op_not: {
93a37866 796 printUnaryOp(out, exec, location, it, "not");
9dae56ea
A
797 break;
798 }
799 case op_eq: {
93a37866 800 printBinaryOp(out, exec, location, it, "eq");
9dae56ea
A
801 break;
802 }
803 case op_eq_null: {
93a37866 804 printUnaryOp(out, exec, location, it, "eq_null");
9dae56ea
A
805 break;
806 }
807 case op_neq: {
93a37866 808 printBinaryOp(out, exec, location, it, "neq");
9dae56ea
A
809 break;
810 }
811 case op_neq_null: {
93a37866 812 printUnaryOp(out, exec, location, it, "neq_null");
9dae56ea
A
813 break;
814 }
815 case op_stricteq: {
93a37866 816 printBinaryOp(out, exec, location, it, "stricteq");
9dae56ea
A
817 break;
818 }
819 case op_nstricteq: {
93a37866 820 printBinaryOp(out, exec, location, it, "nstricteq");
9dae56ea
A
821 break;
822 }
823 case op_less: {
93a37866 824 printBinaryOp(out, exec, location, it, "less");
9dae56ea
A
825 break;
826 }
827 case op_lesseq: {
93a37866 828 printBinaryOp(out, exec, location, it, "lesseq");
9dae56ea
A
829 break;
830 }
6fe7ccc8 831 case op_greater: {
93a37866 832 printBinaryOp(out, exec, location, it, "greater");
6fe7ccc8
A
833 break;
834 }
835 case op_greatereq: {
93a37866 836 printBinaryOp(out, exec, location, it, "greatereq");
6fe7ccc8
A
837 break;
838 }
93a37866 839 case op_inc: {
9dae56ea 840 int r0 = (++it)->u.operand;
93a37866 841 out.printf("[%4d] pre_inc\t\t %s", location, registerName(exec, r0).data());
9dae56ea
A
842 break;
843 }
93a37866 844 case op_dec: {
9dae56ea 845 int r0 = (++it)->u.operand;
93a37866 846 out.printf("[%4d] pre_dec\t\t %s", location, registerName(exec, r0).data());
9dae56ea
A
847 break;
848 }
93a37866
A
849 case op_to_number: {
850 printUnaryOp(out, exec, location, it, "to_number");
9dae56ea
A
851 break;
852 }
853 case op_negate: {
93a37866 854 printUnaryOp(out, exec, location, it, "negate");
9dae56ea
A
855 break;
856 }
857 case op_add: {
93a37866 858 printBinaryOp(out, exec, location, it, "add");
9dae56ea
A
859 ++it;
860 break;
861 }
862 case op_mul: {
93a37866 863 printBinaryOp(out, exec, location, it, "mul");
9dae56ea
A
864 ++it;
865 break;
866 }
867 case op_div: {
93a37866 868 printBinaryOp(out, exec, location, it, "div");
ba379fdc 869 ++it;
9dae56ea
A
870 break;
871 }
872 case op_mod: {
93a37866 873 printBinaryOp(out, exec, location, it, "mod");
9dae56ea
A
874 break;
875 }
876 case op_sub: {
93a37866 877 printBinaryOp(out, exec, location, it, "sub");
9dae56ea
A
878 ++it;
879 break;
880 }
881 case op_lshift: {
93a37866 882 printBinaryOp(out, exec, location, it, "lshift");
9dae56ea
A
883 break;
884 }
885 case op_rshift: {
93a37866 886 printBinaryOp(out, exec, location, it, "rshift");
9dae56ea
A
887 break;
888 }
889 case op_urshift: {
93a37866 890 printBinaryOp(out, exec, location, it, "urshift");
9dae56ea
A
891 break;
892 }
893 case op_bitand: {
93a37866 894 printBinaryOp(out, exec, location, it, "bitand");
9dae56ea
A
895 ++it;
896 break;
897 }
898 case op_bitxor: {
93a37866 899 printBinaryOp(out, exec, location, it, "bitxor");
9dae56ea
A
900 ++it;
901 break;
902 }
903 case op_bitor: {
93a37866 904 printBinaryOp(out, exec, location, it, "bitor");
9dae56ea
A
905 ++it;
906 break;
907 }
14957cd0 908 case op_check_has_instance: {
93a37866
A
909 int r0 = (++it)->u.operand;
910 int r1 = (++it)->u.operand;
911 int r2 = (++it)->u.operand;
912 int offset = (++it)->u.operand;
913 out.printf("[%4d] check_has_instance\t\t %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), offset, location + offset);
14957cd0
A
914 break;
915 }
9dae56ea
A
916 case op_instanceof: {
917 int r0 = (++it)->u.operand;
918 int r1 = (++it)->u.operand;
919 int r2 = (++it)->u.operand;
93a37866 920 out.printf("[%4d] instanceof\t\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
9dae56ea
A
921 break;
922 }
923 case op_typeof: {
93a37866 924 printUnaryOp(out, exec, location, it, "typeof");
9dae56ea
A
925 break;
926 }
927 case op_is_undefined: {
93a37866 928 printUnaryOp(out, exec, location, it, "is_undefined");
9dae56ea
A
929 break;
930 }
931 case op_is_boolean: {
93a37866 932 printUnaryOp(out, exec, location, it, "is_boolean");
9dae56ea
A
933 break;
934 }
935 case op_is_number: {
93a37866 936 printUnaryOp(out, exec, location, it, "is_number");
9dae56ea
A
937 break;
938 }
939 case op_is_string: {
93a37866 940 printUnaryOp(out, exec, location, it, "is_string");
9dae56ea
A
941 break;
942 }
943 case op_is_object: {
93a37866 944 printUnaryOp(out, exec, location, it, "is_object");
9dae56ea
A
945 break;
946 }
947 case op_is_function: {
93a37866 948 printUnaryOp(out, exec, location, it, "is_function");
9dae56ea
A
949 break;
950 }
951 case op_in: {
93a37866 952 printBinaryOp(out, exec, location, it, "in");
9dae56ea
A
953 break;
954 }
93a37866
A
955 case op_put_to_base_variable:
956 case op_put_to_base: {
957 int base = (++it)->u.operand;
9dae56ea 958 int id0 = (++it)->u.operand;
93a37866
A
959 int value = (++it)->u.operand;
960 int resolveInfo = (++it)->u.operand;
961 out.printf("[%4d] put_to_base\t %s, %s, %s, %d", location, registerName(exec, base).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, value).data(), resolveInfo);
9dae56ea
A
962 break;
963 }
93a37866
A
964 case op_resolve:
965 case op_resolve_global_property:
966 case op_resolve_global_var:
967 case op_resolve_scoped_var:
968 case op_resolve_scoped_var_on_top_scope:
969 case op_resolve_scoped_var_with_top_scope_check: {
4e4e5a6f 970 int r0 = (++it)->u.operand;
4e4e5a6f 971 int id0 = (++it)->u.operand;
93a37866
A
972 int resolveInfo = (++it)->u.operand;
973 out.printf("[%4d] resolve\t\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo);
974 dumpValueProfiling(out, it, hasPrintedProfiling);
4e4e5a6f
A
975 break;
976 }
9dae56ea
A
977 case op_get_scoped_var: {
978 int r0 = (++it)->u.operand;
979 int index = (++it)->u.operand;
980 int skipLevels = (++it)->u.operand;
93a37866
A
981 out.printf("[%4d] get_scoped_var\t %s, %d, %d", location, registerName(exec, r0).data(), index, skipLevels);
982 dumpValueProfiling(out, it, hasPrintedProfiling);
9dae56ea
A
983 break;
984 }
985 case op_put_scoped_var: {
986 int index = (++it)->u.operand;
987 int skipLevels = (++it)->u.operand;
988 int r0 = (++it)->u.operand;
93a37866 989 out.printf("[%4d] put_scoped_var\t %d, %d, %s", location, index, skipLevels, registerName(exec, r0).data());
9dae56ea
A
990 break;
991 }
93a37866
A
992 case op_init_global_const_nop: {
993 out.printf("[%4d] init_global_const_nop\t", location);
994 it++;
995 it++;
996 it++;
6fe7ccc8 997 it++;
9dae56ea
A
998 break;
999 }
93a37866
A
1000 case op_init_global_const: {
1001 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
9dae56ea 1002 int r0 = (++it)->u.operand;
93a37866
A
1003 out.printf("[%4d] init_global_const\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data());
1004 it++;
1005 it++;
9dae56ea
A
1006 break;
1007 }
93a37866
A
1008 case op_init_global_const_check: {
1009 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer;
9dae56ea 1010 int r0 = (++it)->u.operand;
93a37866
A
1011 out.printf("[%4d] init_global_const_check\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data());
1012 it++;
6fe7ccc8 1013 it++;
14957cd0
A
1014 break;
1015 }
93a37866
A
1016 case op_resolve_base_to_global:
1017 case op_resolve_base_to_global_dynamic:
1018 case op_resolve_base_to_scope:
1019 case op_resolve_base_to_scope_with_top_scope_check:
1020 case op_resolve_base: {
14957cd0
A
1021 int r0 = (++it)->u.operand;
1022 int id0 = (++it)->u.operand;
93a37866
A
1023 int isStrict = (++it)->u.operand;
1024 int resolveInfo = (++it)->u.operand;
1025 int putToBaseInfo = (++it)->u.operand;
1026 out.printf("[%4d] resolve_base%s\t %s, %s, %d, %d", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo);
1027 dumpValueProfiling(out, it, hasPrintedProfiling);
9dae56ea
A
1028 break;
1029 }
1030 case op_resolve_with_base: {
1031 int r0 = (++it)->u.operand;
1032 int r1 = (++it)->u.operand;
1033 int id0 = (++it)->u.operand;
93a37866
A
1034 int resolveInfo = (++it)->u.operand;
1035 int putToBaseInfo = (++it)->u.operand;
1036 out.printf("[%4d] resolve_with_base %s, %s, %s, %d, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo);
1037 dumpValueProfiling(out, it, hasPrintedProfiling);
6fe7ccc8
A
1038 break;
1039 }
1040 case op_resolve_with_this: {
1041 int r0 = (++it)->u.operand;
1042 int r1 = (++it)->u.operand;
1043 int id0 = (++it)->u.operand;
93a37866
A
1044 int resolveInfo = (++it)->u.operand;
1045 out.printf("[%4d] resolve_with_this %s, %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo);
1046 dumpValueProfiling(out, it, hasPrintedProfiling);
9dae56ea
A
1047 break;
1048 }
93a37866
A
1049 case op_get_by_id:
1050 case op_get_by_id_out_of_line:
1051 case op_get_by_id_self:
1052 case op_get_by_id_proto:
1053 case op_get_by_id_chain:
1054 case op_get_by_id_getter_self:
1055 case op_get_by_id_getter_proto:
1056 case op_get_by_id_getter_chain:
1057 case op_get_by_id_custom_self:
1058 case op_get_by_id_custom_proto:
1059 case op_get_by_id_custom_chain:
1060 case op_get_by_id_generic:
1061 case op_get_array_length:
9dae56ea 1062 case op_get_string_length: {
93a37866
A
1063 printGetByIdOp(out, exec, location, it);
1064 printGetByIdCacheStatus(out, exec, location);
1065 dumpValueProfiling(out, it, hasPrintedProfiling);
9dae56ea
A
1066 break;
1067 }
14957cd0 1068 case op_get_arguments_length: {
93a37866 1069 printUnaryOp(out, exec, location, it, "get_arguments_length");
14957cd0
A
1070 it++;
1071 break;
1072 }
9dae56ea 1073 case op_put_by_id: {
93a37866
A
1074 printPutByIdOp(out, exec, location, it, "put_by_id");
1075 break;
1076 }
1077 case op_put_by_id_out_of_line: {
1078 printPutByIdOp(out, exec, location, it, "put_by_id_out_of_line");
9dae56ea
A
1079 break;
1080 }
1081 case op_put_by_id_replace: {
93a37866 1082 printPutByIdOp(out, exec, location, it, "put_by_id_replace");
9dae56ea
A
1083 break;
1084 }
1085 case op_put_by_id_transition: {
93a37866 1086 printPutByIdOp(out, exec, location, it, "put_by_id_transition");
9dae56ea
A
1087 break;
1088 }
6fe7ccc8 1089 case op_put_by_id_transition_direct: {
93a37866
A
1090 printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct");
1091 break;
1092 }
1093 case op_put_by_id_transition_direct_out_of_line: {
1094 printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct_out_of_line");
9dae56ea
A
1095 break;
1096 }
6fe7ccc8 1097 case op_put_by_id_transition_normal: {
93a37866
A
1098 printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal");
1099 break;
1100 }
1101 case op_put_by_id_transition_normal_out_of_line: {
1102 printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal_out_of_line");
6fe7ccc8
A
1103 break;
1104 }
1105 case op_put_by_id_generic: {
93a37866 1106 printPutByIdOp(out, exec, location, it, "put_by_id_generic");
9dae56ea
A
1107 break;
1108 }
6fe7ccc8 1109 case op_put_getter_setter: {
9dae56ea
A
1110 int r0 = (++it)->u.operand;
1111 int id0 = (++it)->u.operand;
1112 int r1 = (++it)->u.operand;
6fe7ccc8 1113 int r2 = (++it)->u.operand;
93a37866 1114 out.printf("[%4d] put_getter_setter\t %s, %s, %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
ba379fdc
A
1115 break;
1116 }
9dae56ea
A
1117 case op_del_by_id: {
1118 int r0 = (++it)->u.operand;
1119 int r1 = (++it)->u.operand;
1120 int id0 = (++it)->u.operand;
93a37866 1121 out.printf("[%4d] del_by_id\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
9dae56ea
A
1122 break;
1123 }
1124 case op_get_by_val: {
1125 int r0 = (++it)->u.operand;
1126 int r1 = (++it)->u.operand;
1127 int r2 = (++it)->u.operand;
93a37866
A
1128 out.printf("[%4d] get_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
1129 dumpArrayProfiling(out, it, hasPrintedProfiling);
1130 dumpValueProfiling(out, it, hasPrintedProfiling);
f9bf01c6
A
1131 break;
1132 }
14957cd0
A
1133 case op_get_argument_by_val: {
1134 int r0 = (++it)->u.operand;
1135 int r1 = (++it)->u.operand;
1136 int r2 = (++it)->u.operand;
93a37866 1137 out.printf("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
6fe7ccc8 1138 ++it;
93a37866 1139 dumpValueProfiling(out, it, hasPrintedProfiling);
14957cd0
A
1140 break;
1141 }
f9bf01c6
A
1142 case op_get_by_pname: {
1143 int r0 = (++it)->u.operand;
1144 int r1 = (++it)->u.operand;
1145 int r2 = (++it)->u.operand;
1146 int r3 = (++it)->u.operand;
1147 int r4 = (++it)->u.operand;
1148 int r5 = (++it)->u.operand;
93a37866 1149 out.printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s", 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());
9dae56ea
A
1150 break;
1151 }
1152 case op_put_by_val: {
1153 int r0 = (++it)->u.operand;
1154 int r1 = (++it)->u.operand;
1155 int r2 = (++it)->u.operand;
93a37866
A
1156 out.printf("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
1157 dumpArrayProfiling(out, it, hasPrintedProfiling);
9dae56ea
A
1158 break;
1159 }
1160 case op_del_by_val: {
1161 int r0 = (++it)->u.operand;
1162 int r1 = (++it)->u.operand;
1163 int r2 = (++it)->u.operand;
93a37866 1164 out.printf("[%4d] del_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
9dae56ea
A
1165 break;
1166 }
1167 case op_put_by_index: {
1168 int r0 = (++it)->u.operand;
1169 unsigned n0 = (++it)->u.operand;
1170 int r1 = (++it)->u.operand;
93a37866 1171 out.printf("[%4d] put_by_index\t %s, %u, %s", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data());
9dae56ea
A
1172 break;
1173 }
1174 case op_jmp: {
1175 int offset = (++it)->u.operand;
93a37866 1176 out.printf("[%4d] jmp\t\t %d(->%d)", location, offset, location + offset);
9dae56ea
A
1177 break;
1178 }
1179 case op_jtrue: {
93a37866 1180 printConditionalJump(out, exec, begin, it, location, "jtrue");
9dae56ea
A
1181 break;
1182 }
93a37866
A
1183 case op_jfalse: {
1184 printConditionalJump(out, exec, begin, it, location, "jfalse");
f9bf01c6
A
1185 break;
1186 }
93a37866
A
1187 case op_jeq_null: {
1188 printConditionalJump(out, exec, begin, it, location, "jeq_null");
9dae56ea
A
1189 break;
1190 }
1191 case op_jneq_null: {
93a37866 1192 printConditionalJump(out, exec, begin, it, location, "jneq_null");
9dae56ea
A
1193 break;
1194 }
ba379fdc
A
1195 case op_jneq_ptr: {
1196 int r0 = (++it)->u.operand;
93a37866 1197 Special::Pointer pointer = (++it)->u.specialPointer;
ba379fdc 1198 int offset = (++it)->u.operand;
93a37866 1199 out.printf("[%4d] jneq_ptr\t\t %s, %d (%p), %d(->%d)", location, registerName(exec, r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset);
6fe7ccc8
A
1200 break;
1201 }
1202 case op_jless: {
1203 int r0 = (++it)->u.operand;
1204 int r1 = (++it)->u.operand;
1205 int offset = (++it)->u.operand;
93a37866 1206 out.printf("[%4d] jless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
6fe7ccc8
A
1207 break;
1208 }
1209 case op_jlesseq: {
1210 int r0 = (++it)->u.operand;
1211 int r1 = (++it)->u.operand;
1212 int offset = (++it)->u.operand;
93a37866 1213 out.printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
6fe7ccc8
A
1214 break;
1215 }
1216 case op_jgreater: {
1217 int r0 = (++it)->u.operand;
1218 int r1 = (++it)->u.operand;
1219 int offset = (++it)->u.operand;
93a37866 1220 out.printf("[%4d] jgreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
6fe7ccc8
A
1221 break;
1222 }
1223 case op_jgreatereq: {
1224 int r0 = (++it)->u.operand;
1225 int r1 = (++it)->u.operand;
1226 int offset = (++it)->u.operand;
93a37866 1227 out.printf("[%4d] jgreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
ba379fdc
A
1228 break;
1229 }
9dae56ea
A
1230 case op_jnless: {
1231 int r0 = (++it)->u.operand;
1232 int r1 = (++it)->u.operand;
1233 int offset = (++it)->u.operand;
93a37866 1234 out.printf("[%4d] jnless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
9dae56ea
A
1235 break;
1236 }
ba379fdc
A
1237 case op_jnlesseq: {
1238 int r0 = (++it)->u.operand;
1239 int r1 = (++it)->u.operand;
1240 int offset = (++it)->u.operand;
93a37866 1241 out.printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
ba379fdc
A
1242 break;
1243 }
6fe7ccc8 1244 case op_jngreater: {
9dae56ea
A
1245 int r0 = (++it)->u.operand;
1246 int r1 = (++it)->u.operand;
1247 int offset = (++it)->u.operand;
93a37866 1248 out.printf("[%4d] jngreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
f9bf01c6
A
1249 break;
1250 }
6fe7ccc8 1251 case op_jngreatereq: {
f9bf01c6
A
1252 int r0 = (++it)->u.operand;
1253 int r1 = (++it)->u.operand;
1254 int offset = (++it)->u.operand;
93a37866 1255 out.printf("[%4d] jngreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
6fe7ccc8
A
1256 break;
1257 }
1258 case op_loop_hint: {
93a37866 1259 out.printf("[%4d] loop_hint", location);
9dae56ea
A
1260 break;
1261 }
1262 case op_switch_imm: {
1263 int tableIndex = (++it)->u.operand;
1264 int defaultTarget = (++it)->u.operand;
1265 int scrutineeRegister = (++it)->u.operand;
93a37866 1266 out.printf("[%4d] switch_imm\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
9dae56ea
A
1267 break;
1268 }
1269 case op_switch_char: {
1270 int tableIndex = (++it)->u.operand;
1271 int defaultTarget = (++it)->u.operand;
1272 int scrutineeRegister = (++it)->u.operand;
93a37866 1273 out.printf("[%4d] switch_char\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
9dae56ea
A
1274 break;
1275 }
1276 case op_switch_string: {
1277 int tableIndex = (++it)->u.operand;
1278 int defaultTarget = (++it)->u.operand;
1279 int scrutineeRegister = (++it)->u.operand;
93a37866 1280 out.printf("[%4d] switch_string\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data());
9dae56ea
A
1281 break;
1282 }
1283 case op_new_func: {
1284 int r0 = (++it)->u.operand;
1285 int f0 = (++it)->u.operand;
14957cd0 1286 int shouldCheck = (++it)->u.operand;
93a37866 1287 out.printf("[%4d] new_func\t\t %s, f%d, %s", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>");
9dae56ea
A
1288 break;
1289 }
1290 case op_new_func_exp: {
1291 int r0 = (++it)->u.operand;
1292 int f0 = (++it)->u.operand;
93a37866 1293 out.printf("[%4d] new_func_exp\t %s, f%d", location, registerName(exec, r0).data(), f0);
9dae56ea
A
1294 break;
1295 }
1296 case op_call: {
93a37866 1297 printCallOp(out, exec, location, it, "call", DumpCaches);
9dae56ea
A
1298 break;
1299 }
1300 case op_call_eval: {
93a37866 1301 printCallOp(out, exec, location, it, "call_eval", DontDumpCaches);
9dae56ea
A
1302 break;
1303 }
ba379fdc 1304 case op_call_varargs: {
6fe7ccc8
A
1305 int callee = (++it)->u.operand;
1306 int thisValue = (++it)->u.operand;
1307 int arguments = (++it)->u.operand;
1308 int firstFreeRegister = (++it)->u.operand;
93a37866 1309 out.printf("[%4d] call_varargs\t %s, %s, %s, %d", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister);
ba379fdc
A
1310 break;
1311 }
9dae56ea
A
1312 case op_tear_off_activation: {
1313 int r0 = (++it)->u.operand;
93a37866 1314 out.printf("[%4d] tear_off_activation\t %s", location, registerName(exec, r0).data());
9dae56ea
A
1315 break;
1316 }
1317 case op_tear_off_arguments: {
14957cd0 1318 int r0 = (++it)->u.operand;
93a37866
A
1319 int r1 = (++it)->u.operand;
1320 out.printf("[%4d] tear_off_arguments %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data());
9dae56ea
A
1321 break;
1322 }
1323 case op_ret: {
1324 int r0 = (++it)->u.operand;
93a37866 1325 out.printf("[%4d] ret\t\t %s", location, registerName(exec, r0).data());
9dae56ea
A
1326 break;
1327 }
14957cd0
A
1328 case op_call_put_result: {
1329 int r0 = (++it)->u.operand;
93a37866
A
1330 out.printf("[%4d] call_put_result\t\t %s", location, registerName(exec, r0).data());
1331 dumpValueProfiling(out, it, hasPrintedProfiling);
9dae56ea
A
1332 break;
1333 }
14957cd0 1334 case op_ret_object_or_this: {
9dae56ea
A
1335 int r0 = (++it)->u.operand;
1336 int r1 = (++it)->u.operand;
93a37866 1337 out.printf("[%4d] constructor_ret\t\t %s %s", location, registerName(exec, r0).data(), registerName(exec, r1).data());
14957cd0
A
1338 break;
1339 }
1340 case op_construct: {
93a37866 1341 printCallOp(out, exec, location, it, "construct", DumpCaches);
9dae56ea
A
1342 break;
1343 }
ba379fdc
A
1344 case op_strcat: {
1345 int r0 = (++it)->u.operand;
1346 int r1 = (++it)->u.operand;
1347 int count = (++it)->u.operand;
93a37866 1348 out.printf("[%4d] strcat\t\t %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count);
ba379fdc
A
1349 break;
1350 }
1351 case op_to_primitive: {
1352 int r0 = (++it)->u.operand;
1353 int r1 = (++it)->u.operand;
93a37866 1354 out.printf("[%4d] to_primitive\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data());
ba379fdc
A
1355 break;
1356 }
9dae56ea 1357 case op_get_pnames: {
f9bf01c6
A
1358 int r0 = it[1].u.operand;
1359 int r1 = it[2].u.operand;
1360 int r2 = it[3].u.operand;
1361 int r3 = it[4].u.operand;
1362 int offset = it[5].u.operand;
93a37866 1363 out.printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset);
f9bf01c6 1364 it += OPCODE_LENGTH(op_get_pnames) - 1;
9dae56ea
A
1365 break;
1366 }
1367 case op_next_pname: {
f9bf01c6 1368 int dest = it[1].u.operand;
14957cd0
A
1369 int base = it[2].u.operand;
1370 int i = it[3].u.operand;
1371 int size = it[4].u.operand;
1372 int iter = it[5].u.operand;
1373 int offset = it[6].u.operand;
93a37866 1374 out.printf("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset);
f9bf01c6 1375 it += OPCODE_LENGTH(op_next_pname) - 1;
9dae56ea
A
1376 break;
1377 }
93a37866 1378 case op_push_with_scope: {
9dae56ea 1379 int r0 = (++it)->u.operand;
93a37866 1380 out.printf("[%4d] push_with_scope\t %s", location, registerName(exec, r0).data());
9dae56ea
A
1381 break;
1382 }
1383 case op_pop_scope: {
93a37866 1384 out.printf("[%4d] pop_scope", location);
9dae56ea
A
1385 break;
1386 }
93a37866 1387 case op_push_name_scope: {
9dae56ea
A
1388 int id0 = (++it)->u.operand;
1389 int r1 = (++it)->u.operand;
93a37866
A
1390 unsigned attributes = (++it)->u.operand;
1391 out.printf("[%4d] push_name_scope \t%s, %s, %u", location, idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), attributes);
9dae56ea
A
1392 break;
1393 }
1394 case op_catch: {
1395 int r0 = (++it)->u.operand;
93a37866 1396 out.printf("[%4d] catch\t\t %s", location, registerName(exec, r0).data());
9dae56ea
A
1397 break;
1398 }
1399 case op_throw: {
1400 int r0 = (++it)->u.operand;
93a37866 1401 out.printf("[%4d] throw\t\t %s", location, registerName(exec, r0).data());
9dae56ea
A
1402 break;
1403 }
93a37866 1404 case op_throw_static_error: {
9dae56ea 1405 int k0 = (++it)->u.operand;
93a37866
A
1406 int k1 = (++it)->u.operand;
1407 out.printf("[%4d] throw_static_error\t %s, %s", location, constantName(exec, k0, getConstant(k0)).data(), k1 ? "true" : "false");
9dae56ea
A
1408 break;
1409 }
1410 case op_debug: {
1411 int debugHookID = (++it)->u.operand;
1412 int firstLine = (++it)->u.operand;
1413 int lastLine = (++it)->u.operand;
93a37866
A
1414 int column = (++it)->u.operand;
1415 out.printf("[%4d] debug\t\t %s, %d, %d, %d", location, debugHookName(debugHookID), firstLine, lastLine, column);
9dae56ea
A
1416 break;
1417 }
1418 case op_profile_will_call: {
1419 int function = (++it)->u.operand;
93a37866 1420 out.printf("[%4d] profile_will_call %s", location, registerName(exec, function).data());
9dae56ea
A
1421 break;
1422 }
1423 case op_profile_did_call: {
1424 int function = (++it)->u.operand;
93a37866 1425 out.printf("[%4d] profile_did_call\t %s", location, registerName(exec, function).data());
9dae56ea
A
1426 break;
1427 }
1428 case op_end: {
1429 int r0 = (++it)->u.operand;
93a37866 1430 out.printf("[%4d] end\t\t %s", location, registerName(exec, r0).data());
9dae56ea
A
1431 break;
1432 }
93a37866
A
1433#if ENABLE(LLINT_C_LOOP)
1434 default:
1435 RELEASE_ASSERT_NOT_REACHED();
1436#endif
1437 }
1438
1439#if ENABLE(VALUE_PROFILER)
1440 dumpRareCaseProfile(out, "rare case: ", rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
1441 dumpRareCaseProfile(out, "special fast case: ", specialFastCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
1442#endif
1443
1444#if ENABLE(DFG_JIT)
1445 Vector<FrequentExitSite> exitSites = exitProfile().exitSitesFor(location);
1446 if (!exitSites.isEmpty()) {
1447 out.print(" !! frequent exits: ");
1448 CommaPrinter comma;
1449 for (unsigned i = 0; i < exitSites.size(); ++i)
1450 out.print(comma, exitSites[i].kind());
9dae56ea 1451 }
93a37866
A
1452#else // ENABLE(DFG_JIT)
1453 UNUSED_PARAM(location);
1454#endif // ENABLE(DFG_JIT)
1455 out.print("\n");
1456}
1457
1458void CodeBlock::dumpBytecode(PrintStream& out, unsigned bytecodeOffset)
1459{
1460 ExecState* exec = m_globalObject->globalExec();
1461 const Instruction* it = instructions().begin() + bytecodeOffset;
1462 dumpBytecode(out, exec, instructions().begin(), it);
9dae56ea
A
1463}
1464
9dae56ea
A
1465#if DUMP_CODE_BLOCK_STATISTICS
1466static HashSet<CodeBlock*> liveCodeBlockSet;
1467#endif
1468
1469#define FOR_EACH_MEMBER_VECTOR(macro) \
1470 macro(instructions) \
1471 macro(globalResolveInfos) \
1472 macro(structureStubInfos) \
1473 macro(callLinkInfos) \
1474 macro(linkedCallerList) \
1475 macro(identifiers) \
1476 macro(functionExpressions) \
1477 macro(constantRegisters)
1478
1479#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
1480 macro(regexps) \
1481 macro(functions) \
9dae56ea
A
1482 macro(exceptionHandlers) \
1483 macro(immediateSwitchJumpTables) \
1484 macro(characterSwitchJumpTables) \
1485 macro(stringSwitchJumpTables) \
14957cd0 1486 macro(evalCodeCache) \
9dae56ea
A
1487 macro(expressionInfo) \
1488 macro(lineInfo) \
14957cd0 1489 macro(callReturnIndexVector)
9dae56ea
A
1490
1491template<typename T>
1492static size_t sizeInBytes(const Vector<T>& vector)
1493{
1494 return vector.capacity() * sizeof(T);
1495}
1496
1497void CodeBlock::dumpStatistics()
1498{
1499#if DUMP_CODE_BLOCK_STATISTICS
1500 #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;
1501 FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)
1502 FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)
9dae56ea
A
1503 #undef DEFINE_VARS
1504
1505 // Non-vector data members
1506 size_t evalCodeCacheIsNotEmpty = 0;
1507
1508 size_t symbolTableIsNotEmpty = 0;
1509 size_t symbolTableTotalSize = 0;
1510
9dae56ea
A
1511 size_t hasRareData = 0;
1512
1513 size_t isFunctionCode = 0;
1514 size_t isGlobalCode = 0;
1515 size_t isEvalCode = 0;
1516
1517 HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end();
1518 for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) {
1519 CodeBlock* codeBlock = *it;
1520
1521 #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); }
1522 FOR_EACH_MEMBER_VECTOR(GET_STATS)
1523 #undef GET_STATS
1524
93a37866 1525 if (codeBlock->symbolTable() && !codeBlock->symbolTable()->isEmpty()) {
9dae56ea 1526 symbolTableIsNotEmpty++;
93a37866 1527 symbolTableTotalSize += (codeBlock->symbolTable()->capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
9dae56ea
A
1528 }
1529
9dae56ea
A
1530 if (codeBlock->m_rareData) {
1531 hasRareData++;
1532 #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }
1533 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS)
1534 #undef GET_STATS
1535
1536 if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty())
1537 evalCodeCacheIsNotEmpty++;
1538 }
1539
1540 switch (codeBlock->codeType()) {
1541 case FunctionCode:
1542 ++isFunctionCode;
1543 break;
1544 case GlobalCode:
1545 ++isGlobalCode;
1546 break;
1547 case EvalCode:
1548 ++isEvalCode;
1549 break;
1550 }
1551 }
1552
1553 size_t totalSize = 0;
1554
1555 #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize;
1556 FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE)
1557 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE)
9dae56ea
A
1558 #undef GET_TOTAL_SIZE
1559
1560 totalSize += symbolTableTotalSize;
1561 totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
1562
93a37866
A
1563 dataLogF("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
1564 dataLogF("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
1565 dataLogF("Size of all CodeBlocks: %zu\n", totalSize);
1566 dataLogF("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
9dae56ea 1567
93a37866
A
1568 dataLogF("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size());
1569 dataLogF("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
1570 dataLogF("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
9dae56ea 1571
93a37866 1572 dataLogF("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
9dae56ea 1573
93a37866 1574 #define PRINT_STATS(name) dataLogF("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); dataLogF("Size of all " #name ": %zu\n", name##TotalSize);
9dae56ea
A
1575 FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
1576 FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
9dae56ea
A
1577 #undef PRINT_STATS
1578
93a37866
A
1579 dataLogF("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
1580 dataLogF("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
9dae56ea 1581
93a37866 1582 dataLogF("Size of all symbolTables: %zu\n", symbolTableTotalSize);
9dae56ea
A
1583
1584#else
93a37866 1585 dataLogF("Dumping CodeBlock statistics is not enabled.\n");
9dae56ea
A
1586#endif
1587}
1588
93a37866 1589CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
6fe7ccc8
A
1590 : m_globalObject(other.m_globalObject)
1591 , m_heap(other.m_heap)
1592 , m_numCalleeRegisters(other.m_numCalleeRegisters)
1593 , m_numVars(other.m_numVars)
6fe7ccc8 1594 , m_isConstructor(other.m_isConstructor)
93a37866
A
1595 , m_unlinkedCode(*other.m_vm, other.m_ownerExecutable.get(), other.m_unlinkedCode.get())
1596 , m_ownerExecutable(*other.m_vm, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
1597 , m_vm(other.m_vm)
6fe7ccc8
A
1598 , m_instructions(other.m_instructions)
1599 , m_thisRegister(other.m_thisRegister)
1600 , m_argumentsRegister(other.m_argumentsRegister)
1601 , m_activationRegister(other.m_activationRegister)
6fe7ccc8 1602 , m_isStrictMode(other.m_isStrictMode)
93a37866 1603 , m_needsActivation(other.m_needsActivation)
6fe7ccc8
A
1604 , m_source(other.m_source)
1605 , m_sourceOffset(other.m_sourceOffset)
93a37866
A
1606 , m_firstLineColumnOffset(other.m_firstLineColumnOffset)
1607 , m_codeType(other.m_codeType)
6fe7ccc8
A
1608 , m_identifiers(other.m_identifiers)
1609 , m_constantRegisters(other.m_constantRegisters)
1610 , m_functionDecls(other.m_functionDecls)
1611 , m_functionExprs(other.m_functionExprs)
93a37866 1612 , m_osrExitCounter(0)
6fe7ccc8
A
1613 , m_optimizationDelayCounter(0)
1614 , m_reoptimizationRetryCounter(0)
93a37866
A
1615 , m_resolveOperations(other.m_resolveOperations)
1616 , m_putToBaseOperations(other.m_putToBaseOperations)
6fe7ccc8 1617#if ENABLE(JIT)
93a37866 1618 , m_canCompileWithDFGState(DFG::CapabilityLevelNotSet)
6fe7ccc8
A
1619#endif
1620{
1621 setNumParameters(other.numParameters());
1622 optimizeAfterWarmUp();
1623 jitAfterWarmUp();
93a37866 1624
6fe7ccc8
A
1625 if (other.m_rareData) {
1626 createRareDataIfNecessary();
1627
1628 m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
6fe7ccc8
A
1629 m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
1630 m_rareData->m_immediateSwitchJumpTables = other.m_rareData->m_immediateSwitchJumpTables;
1631 m_rareData->m_characterSwitchJumpTables = other.m_rareData->m_characterSwitchJumpTables;
1632 m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
93a37866
A
1633 }
1634}
1635
1636CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset, PassOwnPtr<CodeBlock> alternative)
1637 : m_globalObject(globalObject->vm(), ownerExecutable, globalObject)
1638 , m_heap(&m_globalObject->vm().heap)
1639 , m_numCalleeRegisters(unlinkedCodeBlock->m_numCalleeRegisters)
1640 , m_numVars(unlinkedCodeBlock->m_numVars)
1641 , m_isConstructor(unlinkedCodeBlock->isConstructor())
1642 , m_unlinkedCode(globalObject->vm(), ownerExecutable, unlinkedCodeBlock)
1643 , m_ownerExecutable(globalObject->vm(), ownerExecutable, ownerExecutable)
1644 , m_vm(unlinkedCodeBlock->vm())
1645 , m_thisRegister(unlinkedCodeBlock->thisRegister())
1646 , m_argumentsRegister(unlinkedCodeBlock->argumentsRegister())
1647 , m_activationRegister(unlinkedCodeBlock->activationRegister())
1648 , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
1649 , m_needsActivation(unlinkedCodeBlock->needsFullScopeChain())
9dae56ea
A
1650 , m_source(sourceProvider)
1651 , m_sourceOffset(sourceOffset)
93a37866
A
1652 , m_firstLineColumnOffset(firstLineColumnOffset)
1653 , m_codeType(unlinkedCodeBlock->codeType())
6fe7ccc8 1654 , m_alternative(alternative)
93a37866 1655 , m_osrExitCounter(0)
6fe7ccc8
A
1656 , m_optimizationDelayCounter(0)
1657 , m_reoptimizationRetryCounter(0)
9dae56ea 1658{
93a37866
A
1659 m_vm->startedCompiling(this);
1660
9dae56ea 1661 ASSERT(m_source);
93a37866 1662 setNumParameters(unlinkedCodeBlock->numParameters());
9dae56ea
A
1663
1664#if DUMP_CODE_BLOCK_STATISTICS
1665 liveCodeBlockSet.add(this);
1666#endif
93a37866
A
1667 setIdentifiers(unlinkedCodeBlock->identifiers());
1668 setConstantRegisters(unlinkedCodeBlock->constantRegisters());
1669 if (unlinkedCodeBlock->usesGlobalObject())
1670 m_constantRegisters[unlinkedCodeBlock->globalObjectRegister()].set(*m_vm, ownerExecutable, globalObject);
1671 m_functionDecls.grow(unlinkedCodeBlock->numberOfFunctionDecls());
1672 for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
1673 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
1674 unsigned lineCount = unlinkedExecutable->lineCount();
1675 unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
1676 unsigned startColumn = unlinkedExecutable->functionStartColumn();
1677 startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn());
1678 unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
1679 unsigned sourceLength = unlinkedExecutable->sourceLength();
1680 SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn);
1681 FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn);
1682 m_functionDecls[i].set(*m_vm, ownerExecutable, executable);
1683 }
1684
1685 m_functionExprs.grow(unlinkedCodeBlock->numberOfFunctionExprs());
1686 for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
1687 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
1688 unsigned lineCount = unlinkedExecutable->lineCount();
1689 unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
1690 unsigned startColumn = unlinkedExecutable->functionStartColumn();
1691 startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn());
1692 unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
1693 unsigned sourceLength = unlinkedExecutable->sourceLength();
1694 SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn);
1695 FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn);
1696 m_functionExprs[i].set(*m_vm, ownerExecutable, executable);
1697 }
1698
1699 if (unlinkedCodeBlock->hasRareData()) {
1700 createRareDataIfNecessary();
1701 if (size_t count = unlinkedCodeBlock->constantBufferCount()) {
1702 m_rareData->m_constantBuffers.grow(count);
1703 for (size_t i = 0; i < count; i++) {
1704 const UnlinkedCodeBlock::ConstantBuffer& buffer = unlinkedCodeBlock->constantBuffer(i);
1705 m_rareData->m_constantBuffers[i] = buffer;
1706 }
1707 }
1708 if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) {
1709 m_rareData->m_exceptionHandlers.grow(count);
1710 for (size_t i = 0; i < count; i++) {
1711 const UnlinkedHandlerInfo& handler = unlinkedCodeBlock->exceptionHandler(i);
1712 m_rareData->m_exceptionHandlers[i].start = handler.start;
1713 m_rareData->m_exceptionHandlers[i].end = handler.end;
1714 m_rareData->m_exceptionHandlers[i].target = handler.target;
1715 m_rareData->m_exceptionHandlers[i].scopeDepth = handler.scopeDepth + baseScopeDepth;
1716#if ENABLE(JIT) && ENABLE(LLINT)
1717 m_rareData->m_exceptionHandlers[i].nativeCode = CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(llint_op_catch)));
1718#endif
1719 }
1720 }
1721
1722 if (size_t count = unlinkedCodeBlock->numberOfStringSwitchJumpTables()) {
1723 m_rareData->m_stringSwitchJumpTables.grow(count);
1724 for (size_t i = 0; i < count; i++) {
1725 UnlinkedStringJumpTable::StringOffsetTable::iterator ptr = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.begin();
1726 UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end();
1727 for (; ptr != end; ++ptr) {
1728 OffsetLocation offset;
1729 offset.branchOffset = ptr->value;
1730 m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset);
1731 }
1732 }
1733 }
1734
1735 if (size_t count = unlinkedCodeBlock->numberOfImmediateSwitchJumpTables()) {
1736 m_rareData->m_immediateSwitchJumpTables.grow(count);
1737 for (size_t i = 0; i < count; i++) {
1738 UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->immediateSwitchJumpTable(i);
1739 SimpleJumpTable& destTable = m_rareData->m_immediateSwitchJumpTables[i];
1740 destTable.branchOffsets = sourceTable.branchOffsets;
1741 destTable.min = sourceTable.min;
1742 }
1743 }
1744
1745 if (size_t count = unlinkedCodeBlock->numberOfCharacterSwitchJumpTables()) {
1746 m_rareData->m_characterSwitchJumpTables.grow(count);
1747 for (size_t i = 0; i < count; i++) {
1748 UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->characterSwitchJumpTable(i);
1749 SimpleJumpTable& destTable = m_rareData->m_characterSwitchJumpTables[i];
1750 destTable.branchOffsets = sourceTable.branchOffsets;
1751 destTable.min = sourceTable.min;
1752 }
1753 }
1754 }
1755
1756 // Allocate metadata buffers for the bytecode
1757#if ENABLE(LLINT)
1758 if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos())
1759 m_llintCallLinkInfos.grow(size);
1760#endif
1761#if ENABLE(DFG_JIT)
1762 if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
1763 m_arrayProfiles.grow(size);
1764 if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles())
1765 m_arrayAllocationProfiles.grow(size);
1766 if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
1767 m_valueProfiles.grow(size);
1768#endif
1769 if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
1770 m_objectAllocationProfiles.grow(size);
1771 if (size_t size = unlinkedCodeBlock->numberOfResolveOperations())
1772 m_resolveOperations.grow(size);
1773 if (size_t putToBaseCount = unlinkedCodeBlock->numberOfPutToBaseOperations()) {
1774 m_putToBaseOperations.reserveInitialCapacity(putToBaseCount);
1775 for (size_t i = 0; i < putToBaseCount; ++i)
1776 m_putToBaseOperations.uncheckedAppend(PutToBaseOperation(isStrictMode()));
1777 }
1778
1779 // Copy and translate the UnlinkedInstructions
1780 size_t instructionCount = unlinkedCodeBlock->instructions().size();
1781 UnlinkedInstruction* pc = unlinkedCodeBlock->instructions().data();
1782 Vector<Instruction, 0, UnsafeVectorOverflow> instructions(instructionCount);
1783 for (size_t i = 0; i < unlinkedCodeBlock->instructions().size(); ) {
1784 unsigned opLength = opcodeLength(pc[i].u.opcode);
1785 instructions[i] = vm()->interpreter->getOpcode(pc[i].u.opcode);
1786 for (size_t j = 1; j < opLength; ++j) {
1787 if (sizeof(int32_t) != sizeof(intptr_t))
1788 instructions[i + j].u.pointer = 0;
1789 instructions[i + j].u.operand = pc[i + j].u.operand;
1790 }
1791 switch (pc[i].u.opcode) {
1792#if ENABLE(DFG_JIT)
1793 case op_get_by_val:
1794 case op_get_argument_by_val: {
1795 int arrayProfileIndex = pc[i + opLength - 2].u.operand;
1796 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
1797
1798 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
1799 // fallthrough
1800 }
1801 case op_convert_this:
1802 case op_get_by_id:
1803 case op_call_put_result:
1804 case op_get_callee: {
1805 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
1806 ASSERT(profile->m_bytecodeOffset == -1);
1807 profile->m_bytecodeOffset = i;
1808 instructions[i + opLength - 1] = profile;
1809 break;
1810 }
1811 case op_put_by_val: {
1812 int arrayProfileIndex = pc[i + opLength - 1].u.operand;
1813 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
1814 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
1815 break;
1816 }
1817
1818 case op_new_array:
1819 case op_new_array_buffer:
1820 case op_new_array_with_size: {
1821 int arrayAllocationProfileIndex = pc[i + opLength - 1].u.operand;
1822 instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
1823 break;
1824 }
1825#endif
1826 case op_resolve_base:
1827 case op_resolve_base_to_global:
1828 case op_resolve_base_to_global_dynamic:
1829 case op_resolve_base_to_scope:
1830 case op_resolve_base_to_scope_with_top_scope_check: {
1831 instructions[i + 4].u.resolveOperations = &m_resolveOperations[pc[i + 4].u.operand];
1832 instructions[i + 5].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 5].u.operand];
1833#if ENABLE(DFG_JIT)
1834 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
1835 ASSERT(profile->m_bytecodeOffset == -1);
1836 profile->m_bytecodeOffset = i;
1837 ASSERT((opLength - 1) > 5);
1838 instructions[i + opLength - 1] = profile;
1839#endif
1840 break;
1841 }
1842 case op_resolve_global_property:
1843 case op_resolve_global_var:
1844 case op_resolve_scoped_var:
1845 case op_resolve_scoped_var_on_top_scope:
1846 case op_resolve_scoped_var_with_top_scope_check: {
1847 instructions[i + 3].u.resolveOperations = &m_resolveOperations[pc[i + 3].u.operand];
1848 break;
1849 }
1850 case op_put_to_base:
1851 case op_put_to_base_variable: {
1852 instructions[i + 4].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 4].u.operand];
1853 break;
1854 }
1855 case op_resolve: {
1856#if ENABLE(DFG_JIT)
1857 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
1858 ASSERT(profile->m_bytecodeOffset == -1);
1859 profile->m_bytecodeOffset = i;
1860 ASSERT((opLength - 1) > 3);
1861 instructions[i + opLength - 1] = profile;
1862#endif
1863 instructions[i + 3].u.resolveOperations = &m_resolveOperations[pc[i + 3].u.operand];
1864 break;
1865 }
1866 case op_resolve_with_base:
1867 case op_resolve_with_this: {
1868 instructions[i + 4].u.resolveOperations = &m_resolveOperations[pc[i + 4].u.operand];
1869 if (pc[i].u.opcode != op_resolve_with_this)
1870 instructions[i + 5].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 5].u.operand];
1871#if ENABLE(DFG_JIT)
1872 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
1873 ASSERT(profile->m_bytecodeOffset == -1);
1874 profile->m_bytecodeOffset = i;
1875 instructions[i + opLength - 1] = profile;
1876#endif
1877 break;
1878 }
1879 case op_new_object: {
1880 int objectAllocationProfileIndex = pc[i + opLength - 1].u.operand;
1881 ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex];
1882 int inferredInlineCapacity = pc[i + opLength - 2].u.operand;
1883
1884 instructions[i + opLength - 1] = objectAllocationProfile;
1885 objectAllocationProfile->initialize(*vm(),
1886 m_ownerExecutable.get(), m_globalObject->objectPrototype(), inferredInlineCapacity);
1887 break;
1888 }
1889
1890 case op_get_scoped_var: {
1891#if ENABLE(DFG_JIT)
1892 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
1893 ASSERT(profile->m_bytecodeOffset == -1);
1894 profile->m_bytecodeOffset = i;
1895 instructions[i + opLength - 1] = profile;
1896#endif
1897 break;
1898 }
1899
1900 case op_call:
1901 case op_call_eval: {
1902#if ENABLE(DFG_JIT)
1903 int arrayProfileIndex = pc[i + opLength - 1].u.operand;
1904 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
1905 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
1906#endif
1907#if ENABLE(LLINT)
1908 instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand];
1909#endif
1910 break;
1911 }
1912 case op_construct:
1913#if ENABLE(LLINT)
1914 instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand];
1915#endif
1916 break;
1917 case op_get_by_id_out_of_line:
1918 case op_get_by_id_self:
1919 case op_get_by_id_proto:
1920 case op_get_by_id_chain:
1921 case op_get_by_id_getter_self:
1922 case op_get_by_id_getter_proto:
1923 case op_get_by_id_getter_chain:
1924 case op_get_by_id_custom_self:
1925 case op_get_by_id_custom_proto:
1926 case op_get_by_id_custom_chain:
1927 case op_get_by_id_generic:
1928 case op_get_array_length:
1929 case op_get_string_length:
1930 CRASH();
1931
1932 case op_init_global_const_nop: {
1933 ASSERT(codeType() == GlobalCode);
1934 Identifier ident = identifier(pc[i + 4].u.operand);
1935 SymbolTableEntry entry = globalObject->symbolTable()->get(ident.impl());
1936 if (entry.isNull())
1937 break;
1938
1939 if (entry.couldBeWatched()) {
1940 instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const_check);
1941 instructions[i + 1] = &globalObject->registerAt(entry.getIndex());
1942 instructions[i + 3] = entry.addressOfIsWatched();
1943 break;
1944 }
1945
1946 instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const);
1947 instructions[i + 1] = &globalObject->registerAt(entry.getIndex());
1948 break;
1949 }
1950
1951 case op_debug: {
1952 instructions[i + 4] = columnNumberForBytecodeOffset(i);
1953 break;
1954 }
1955
1956 default:
1957 break;
1958 }
1959 i += opLength;
1960 }
1961 m_instructions = WTF::RefCountedArray<Instruction>(instructions);
1962
1963 // Set optimization thresholds only after m_instructions is initialized, since these
1964 // rely on the instruction count (and are in theory permitted to also inspect the
1965 // instruction stream to more accurate assess the cost of tier-up).
1966 optimizeAfterWarmUp();
1967 jitAfterWarmUp();
1968
1969 if (Options::dumpGeneratedBytecodes())
1970 dumpBytecode();
1971 m_vm->finishedCompiling(this);
9dae56ea
A
1972}
1973
1974CodeBlock::~CodeBlock()
1975{
93a37866
A
1976 if (m_vm->m_perBytecodeProfiler)
1977 m_vm->m_perBytecodeProfiler->notifyDestruction(this);
1978
6fe7ccc8
A
1979#if ENABLE(DFG_JIT)
1980 // Remove myself from the set of DFG code blocks. Note that I may not be in this set
1981 // (because I'm not a DFG code block), in which case this is a no-op anyway.
93a37866 1982 m_vm->heap.m_dfgCodeBlocks.m_set.remove(this);
6fe7ccc8
A
1983#endif
1984
1985#if ENABLE(VERBOSE_VALUE_PROFILE)
1986 dumpValueProfiles();
1987#endif
1988
1989#if ENABLE(LLINT)
1990 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
1991 m_incomingLLIntCalls.begin()->remove();
1992#endif // ENABLE(LLINT)
4e4e5a6f 1993#if ENABLE(JIT)
6fe7ccc8
A
1994 // We may be destroyed before any CodeBlocks that refer to us are destroyed.
1995 // Consider that two CodeBlocks become unreachable at the same time. There
1996 // is no guarantee about the order in which the CodeBlocks are destroyed.
1997 // So, if we don't remove incoming calls, and get destroyed before the
1998 // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's
1999 // destructor will try to remove nodes from our (no longer valid) linked list.
2000 while (m_incomingCalls.begin() != m_incomingCalls.end())
2001 m_incomingCalls.begin()->remove();
2002
2003 // Note that our outgoing calls will be removed from other CodeBlocks'
2004 // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
2005 // destructors.
2006
9dae56ea
A
2007 for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
2008 m_structureStubInfos[i].deref();
4e4e5a6f 2009#endif // ENABLE(JIT)
ba379fdc 2010
9dae56ea
A
2011#if DUMP_CODE_BLOCK_STATISTICS
2012 liveCodeBlockSet.remove(this);
2013#endif
2014}
2015
6fe7ccc8
A
2016void CodeBlock::setNumParameters(int newValue)
2017{
2018 m_numParameters = newValue;
2019
2020#if ENABLE(VALUE_PROFILER)
93a37866 2021 m_argumentValueProfiles.resizeToFit(newValue);
6fe7ccc8
A
2022#endif
2023}
2024
93a37866 2025void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC)
6fe7ccc8 2026{
93a37866 2027 Interpreter* interpreter = m_vm->interpreter;
9dae56ea 2028
14957cd0
A
2029 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) && vPC[4].u.structure) {
2030 visitor.append(&vPC[4].u.structure);
2031 return;
2032 }
2033
4e4e5a6f 2034 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)) {
14957cd0 2035 visitor.append(&vPC[4].u.structure);
9dae56ea
A
2036 return;
2037 }
4e4e5a6f 2038 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)) {
14957cd0
A
2039 visitor.append(&vPC[4].u.structure);
2040 visitor.append(&vPC[5].u.structure);
9dae56ea
A
2041 return;
2042 }
4e4e5a6f 2043 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)) {
14957cd0 2044 visitor.append(&vPC[4].u.structure);
6fe7ccc8
A
2045 if (vPC[5].u.structureChain)
2046 visitor.append(&vPC[5].u.structureChain);
9dae56ea
A
2047 return;
2048 }
2049 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
14957cd0
A
2050 visitor.append(&vPC[4].u.structure);
2051 visitor.append(&vPC[5].u.structure);
6fe7ccc8
A
2052 if (vPC[6].u.structureChain)
2053 visitor.append(&vPC[6].u.structureChain);
14957cd0
A
2054 return;
2055 }
2056 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) && vPC[4].u.structure) {
2057 visitor.append(&vPC[4].u.structure);
9dae56ea
A
2058 return;
2059 }
2060 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
14957cd0 2061 visitor.append(&vPC[4].u.structure);
9dae56ea
A
2062 return;
2063 }
9dae56ea
A
2064
2065 // These instructions don't ref their Structures.
2066 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));
2067}
2068
14957cd0 2069void EvalCodeCache::visitAggregate(SlotVisitor& visitor)
9dae56ea 2070{
14957cd0
A
2071 EvalCacheMap::iterator end = m_cacheMap.end();
2072 for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
93a37866 2073 visitor.append(&ptr->value);
9dae56ea
A
2074}
2075
14957cd0 2076void CodeBlock::visitAggregate(SlotVisitor& visitor)
6fe7ccc8
A
2077{
2078#if ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT)
2079 if (!!m_dfgData) {
2080 // I may be asked to scan myself more than once, and it may even happen concurrently.
2081 // To this end, use a CAS loop to check if I've been called already. Only one thread
2082 // may proceed past this point - whichever one wins the CAS race.
2083 unsigned oldValue;
2084 do {
2085 oldValue = m_dfgData->visitAggregateHasBeenCalled;
2086 if (oldValue) {
2087 // Looks like someone else won! Return immediately to ensure that we don't
2088 // trace the same CodeBlock concurrently. Doing so is hazardous since we will
2089 // be mutating the state of ValueProfiles, which contain JSValues, which can
2090 // have word-tearing on 32-bit, leading to awesome timing-dependent crashes
2091 // that are nearly impossible to track down.
2092
2093 // Also note that it must be safe to return early as soon as we see the
2094 // value true (well, (unsigned)1), since once a GC thread is in this method
2095 // and has won the CAS race (i.e. was responsible for setting the value true)
2096 // it will definitely complete the rest of this method before declaring
2097 // termination.
2098 return;
2099 }
2100 } while (!WTF::weakCompareAndSwap(&m_dfgData->visitAggregateHasBeenCalled, 0, 1));
2101 }
2102#endif // ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT)
2103
2104 if (!!m_alternative)
2105 m_alternative->visitAggregate(visitor);
2106
93a37866
A
2107 visitor.append(&m_unlinkedCode);
2108
6fe7ccc8
A
2109 // There are three things that may use unconditional finalizers: lazy bytecode freeing,
2110 // inline cache clearing, and jettisoning. The probability of us wanting to do at
2111 // least one of those things is probably quite close to 1. So we add one no matter what
2112 // and when it runs, it figures out whether it has any work to do.
2113 visitor.addUnconditionalFinalizer(this);
2114
2115 if (shouldImmediatelyAssumeLivenessDuringScan()) {
2116 // This code block is live, so scan all references strongly and return.
2117 stronglyVisitStrongReferences(visitor);
2118 stronglyVisitWeakReferences(visitor);
2119 return;
2120 }
2121
2122#if ENABLE(DFG_JIT)
2123 // We get here if we're live in the sense that our owner executable is live,
2124 // but we're not yet live for sure in another sense: we may yet decide that this
2125 // code block should be jettisoned based on its outgoing weak references being
2126 // stale. Set a flag to indicate that we're still assuming that we're dead, and
2127 // perform one round of determining if we're live. The GC may determine, based on
2128 // either us marking additional objects, or by other objects being marked for
2129 // other reasons, that this iteration should run again; it will notify us of this
2130 // decision by calling harvestWeakReferences().
2131
2132 m_dfgData->livenessHasBeenProved = false;
2133 m_dfgData->allTransitionsHaveBeenMarked = false;
2134
2135 performTracingFixpointIteration(visitor);
2136
2137 // GC doesn't have enough information yet for us to decide whether to keep our DFG
2138 // data, so we need to register a handler to run again at the end of GC, when more
2139 // information is available.
2140 if (!(m_dfgData->livenessHasBeenProved && m_dfgData->allTransitionsHaveBeenMarked))
2141 visitor.addWeakReferenceHarvester(this);
2142
2143#else // ENABLE(DFG_JIT)
93a37866 2144 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
2145#endif // ENABLE(DFG_JIT)
2146}
2147
2148void CodeBlock::performTracingFixpointIteration(SlotVisitor& visitor)
2149{
2150 UNUSED_PARAM(visitor);
2151
2152#if ENABLE(DFG_JIT)
2153 // Evaluate our weak reference transitions, if there are still some to evaluate.
2154 if (!m_dfgData->allTransitionsHaveBeenMarked) {
2155 bool allAreMarkedSoFar = true;
2156 for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) {
2157 if ((!m_dfgData->transitions[i].m_codeOrigin
2158 || Heap::isMarked(m_dfgData->transitions[i].m_codeOrigin.get()))
2159 && Heap::isMarked(m_dfgData->transitions[i].m_from.get())) {
2160 // If the following three things are live, then the target of the
2161 // transition is also live:
2162 // - This code block. We know it's live already because otherwise
2163 // we wouldn't be scanning ourselves.
2164 // - The code origin of the transition. Transitions may arise from
2165 // code that was inlined. They are not relevant if the user's
2166 // object that is required for the inlinee to run is no longer
2167 // live.
2168 // - The source of the transition. The transition checks if some
2169 // heap location holds the source, and if so, stores the target.
2170 // Hence the source must be live for the transition to be live.
2171 visitor.append(&m_dfgData->transitions[i].m_to);
2172 } else
2173 allAreMarkedSoFar = false;
2174 }
2175
2176 if (allAreMarkedSoFar)
2177 m_dfgData->allTransitionsHaveBeenMarked = true;
2178 }
2179
2180 // Check if we have any remaining work to do.
2181 if (m_dfgData->livenessHasBeenProved)
2182 return;
2183
2184 // Now check all of our weak references. If all of them are live, then we
2185 // have proved liveness and so we scan our strong references. If at end of
2186 // GC we still have not proved liveness, then this code block is toast.
2187 bool allAreLiveSoFar = true;
2188 for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) {
2189 if (!Heap::isMarked(m_dfgData->weakReferences[i].get())) {
2190 allAreLiveSoFar = false;
2191 break;
2192 }
2193 }
2194
2195 // If some weak references are dead, then this fixpoint iteration was
2196 // unsuccessful.
2197 if (!allAreLiveSoFar)
2198 return;
2199
2200 // All weak references are live. Record this information so we don't
2201 // come back here again, and scan the strong references.
2202 m_dfgData->livenessHasBeenProved = true;
2203 stronglyVisitStrongReferences(visitor);
2204#endif // ENABLE(DFG_JIT)
2205}
2206
2207void CodeBlock::visitWeakReferences(SlotVisitor& visitor)
2208{
2209 performTracingFixpointIteration(visitor);
2210}
2211
6fe7ccc8 2212#if ENABLE(JIT_VERBOSE_OSR)
93a37866 2213static const bool verboseUnlinking = true;
6fe7ccc8 2214#else
93a37866 2215static const bool verboseUnlinking = false;
6fe7ccc8 2216#endif
93a37866
A
2217
2218void CodeBlock::finalizeUnconditionally()
2219{
6fe7ccc8 2220#if ENABLE(LLINT)
93a37866
A
2221 Interpreter* interpreter = m_vm->interpreter;
2222 if (!!numberOfInstructions()) {
2223 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
2224 for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
2225 Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
6fe7ccc8
A
2226 switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
2227 case op_get_by_id:
93a37866 2228 case op_get_by_id_out_of_line:
6fe7ccc8 2229 case op_put_by_id:
93a37866 2230 case op_put_by_id_out_of_line:
6fe7ccc8
A
2231 if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
2232 break;
2233 if (verboseUnlinking)
93a37866 2234 dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
6fe7ccc8
A
2235 curInstruction[4].u.structure.clear();
2236 curInstruction[5].u.operand = 0;
2237 break;
2238 case op_put_by_id_transition_direct:
2239 case op_put_by_id_transition_normal:
93a37866
A
2240 case op_put_by_id_transition_direct_out_of_line:
2241 case op_put_by_id_transition_normal_out_of_line:
6fe7ccc8
A
2242 if (Heap::isMarked(curInstruction[4].u.structure.get())
2243 && Heap::isMarked(curInstruction[6].u.structure.get())
2244 && Heap::isMarked(curInstruction[7].u.structureChain.get()))
2245 break;
2246 if (verboseUnlinking) {
93a37866 2247 dataLogF("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
6fe7ccc8
A
2248 curInstruction[4].u.structure.get(),
2249 curInstruction[6].u.structure.get(),
2250 curInstruction[7].u.structureChain.get());
2251 }
2252 curInstruction[4].u.structure.clear();
2253 curInstruction[6].u.structure.clear();
2254 curInstruction[7].u.structureChain.clear();
2255 curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id);
2256 break;
93a37866
A
2257 case op_get_array_length:
2258 break;
6fe7ccc8 2259 default:
93a37866 2260 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
2261 }
2262 }
93a37866 2263
6fe7ccc8
A
2264 for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
2265 if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
2266 if (verboseUnlinking)
93a37866 2267 dataLog("Clearing LLInt call from ", *this, "\n");
6fe7ccc8
A
2268 m_llintCallLinkInfos[i].unlink();
2269 }
2270 if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
2271 m_llintCallLinkInfos[i].lastSeenCallee.clear();
2272 }
2273 }
2274#endif // ENABLE(LLINT)
2275
2276#if ENABLE(DFG_JIT)
2277 // Check if we're not live. If we are, then jettison.
2278 if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) {
2279 if (verboseUnlinking)
93a37866
A
2280 dataLog(*this, " has dead weak references, jettisoning during GC.\n");
2281
2282 if (DFG::shouldShowDisassembly()) {
2283 dataLog(*this, " will be jettisoned because of the following dead references:\n");
2284 for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) {
2285 WeakReferenceTransition& transition = m_dfgData->transitions[i];
2286 JSCell* origin = transition.m_codeOrigin.get();
2287 JSCell* from = transition.m_from.get();
2288 JSCell* to = transition.m_to.get();
2289 if ((!origin || Heap::isMarked(origin)) && Heap::isMarked(from))
2290 continue;
2291 dataLog(" Transition under ", JSValue(origin), ", ", JSValue(from), " -> ", JSValue(to), ".\n");
2292 }
2293 for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) {
2294 JSCell* weak = m_dfgData->weakReferences[i].get();
2295 if (Heap::isMarked(weak))
2296 continue;
2297 dataLog(" Weak reference ", JSValue(weak), ".\n");
2298 }
2299 }
6fe7ccc8
A
2300
2301 jettison();
2302 return;
2303 }
2304#endif // ENABLE(DFG_JIT)
93a37866
A
2305
2306 for (size_t size = m_putToBaseOperations.size(), i = 0; i < size; ++i) {
2307 if (m_putToBaseOperations[i].m_structure && !Heap::isMarked(m_putToBaseOperations[i].m_structure.get())) {
2308 if (verboseUnlinking)
2309 dataLog("Clearing putToBase info in ", *this, "\n");
2310 m_putToBaseOperations[i].m_structure.clear();
2311 }
2312 }
2313 for (size_t size = m_resolveOperations.size(), i = 0; i < size; ++i) {
2314 if (m_resolveOperations[i].isEmpty())
2315 continue;
2316#ifndef NDEBUG
2317 for (size_t insnSize = m_resolveOperations[i].size() - 1, k = 0; k < insnSize; ++k)
2318 ASSERT(!m_resolveOperations[i][k].m_structure);
2319#endif
2320 m_resolveOperations[i].last().m_structure.clear();
2321 if (m_resolveOperations[i].last().m_structure && !Heap::isMarked(m_resolveOperations[i].last().m_structure.get())) {
2322 if (verboseUnlinking)
2323 dataLog("Clearing resolve info in ", *this, "\n");
2324 m_resolveOperations[i].last().m_structure.clear();
2325 }
2326 }
2327
6fe7ccc8
A
2328#if ENABLE(JIT)
2329 // Handle inline caches.
2330 if (!!getJITCode()) {
2331 RepatchBuffer repatchBuffer(this);
2332 for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) {
93a37866
A
2333 if (callLinkInfo(i).isLinked()) {
2334 if (ClosureCallStubRoutine* stub = callLinkInfo(i).stub.get()) {
2335 if (!Heap::isMarked(stub->structure())
2336 || !Heap::isMarked(stub->executable())) {
2337 if (verboseUnlinking) {
2338 dataLog(
2339 "Clearing closure call from ", *this, " to ",
2340 stub->executable()->hashFor(callLinkInfo(i).specializationKind()),
2341 ", stub routine ", RawPointer(stub), ".\n");
2342 }
2343 callLinkInfo(i).unlink(*m_vm, repatchBuffer);
2344 }
2345 } else if (!Heap::isMarked(callLinkInfo(i).callee.get())) {
2346 if (verboseUnlinking) {
2347 dataLog(
2348 "Clearing call from ", *this, " to ",
2349 RawPointer(callLinkInfo(i).callee.get()), " (",
2350 callLinkInfo(i).callee.get()->executable()->hashFor(
2351 callLinkInfo(i).specializationKind()),
2352 ").\n");
2353 }
2354 callLinkInfo(i).unlink(*m_vm, repatchBuffer);
2355 }
6fe7ccc8
A
2356 }
2357 if (!!callLinkInfo(i).lastSeenCallee
2358 && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get()))
2359 callLinkInfo(i).lastSeenCallee.clear();
2360 }
6fe7ccc8
A
2361 for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) {
2362 StructureStubInfo& stubInfo = m_structureStubInfos[i];
2363
6fe7ccc8
A
2364 if (stubInfo.visitWeakReferences())
2365 continue;
2366
93a37866 2367 resetStubDuringGCInternal(repatchBuffer, stubInfo);
6fe7ccc8 2368 }
93a37866
A
2369 }
2370#endif
2371}
6fe7ccc8 2372
93a37866
A
2373#if ENABLE(JIT)
2374void CodeBlock::resetStub(StructureStubInfo& stubInfo)
2375{
2376 if (stubInfo.accessType == access_unset)
2377 return;
2378
2379 RepatchBuffer repatchBuffer(this);
2380 resetStubInternal(repatchBuffer, stubInfo);
2381}
6fe7ccc8 2382
93a37866
A
2383void CodeBlock::resetStubInternal(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
2384{
2385 AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
2386
2387 if (verboseUnlinking)
2388 dataLog("Clearing structure cache (kind ", static_cast<int>(stubInfo.accessType), ") in ", *this, ".\n");
2389
2390 if (isGetByIdAccess(accessType)) {
2391 if (getJITCode().jitType() == JITCode::DFGJIT)
2392 DFG::dfgResetGetByID(repatchBuffer, stubInfo);
2393 else
2394 JIT::resetPatchGetById(repatchBuffer, &stubInfo);
2395 } else {
2396 ASSERT(isPutByIdAccess(accessType));
2397 if (getJITCode().jitType() == JITCode::DFGJIT)
2398 DFG::dfgResetPutByID(repatchBuffer, stubInfo);
2399 else
2400 JIT::resetPatchPutById(repatchBuffer, &stubInfo);
6fe7ccc8 2401 }
93a37866
A
2402
2403 stubInfo.reset();
2404}
2405
2406void CodeBlock::resetStubDuringGCInternal(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
2407{
2408 resetStubInternal(repatchBuffer, stubInfo);
2409 stubInfo.resetByGC = true;
6fe7ccc8 2410}
93a37866 2411#endif
6fe7ccc8
A
2412
2413void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
9dae56ea 2414{
14957cd0
A
2415 visitor.append(&m_globalObject);
2416 visitor.append(&m_ownerExecutable);
93a37866
A
2417 visitor.append(&m_unlinkedCode);
2418 if (m_rareData)
14957cd0 2419 m_rareData->m_evalCodeCache.visitAggregate(visitor);
14957cd0 2420 visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
f9bf01c6 2421 for (size_t i = 0; i < m_functionExprs.size(); ++i)
14957cd0 2422 visitor.append(&m_functionExprs[i]);
f9bf01c6 2423 for (size_t i = 0; i < m_functionDecls.size(); ++i)
14957cd0 2424 visitor.append(&m_functionDecls[i]);
93a37866
A
2425 for (unsigned i = 0; i < m_objectAllocationProfiles.size(); ++i)
2426 m_objectAllocationProfiles[i].visitAggregate(visitor);
6fe7ccc8 2427
93a37866 2428 updateAllPredictions(Collection);
9dae56ea
A
2429}
2430
6fe7ccc8
A
2431void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor)
2432{
2433 UNUSED_PARAM(visitor);
2434
2435#if ENABLE(DFG_JIT)
2436 if (!m_dfgData)
2437 return;
2438
2439 for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) {
2440 if (!!m_dfgData->transitions[i].m_codeOrigin)
2441 visitor.append(&m_dfgData->transitions[i].m_codeOrigin); // Almost certainly not necessary, since the code origin should also be a weak reference. Better to be safe, though.
2442 visitor.append(&m_dfgData->transitions[i].m_from);
2443 visitor.append(&m_dfgData->transitions[i].m_to);
2444 }
2445
2446 for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i)
2447 visitor.append(&m_dfgData->weakReferences[i]);
2448#endif
2449}
2450
9dae56ea
A
2451HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
2452{
93a37866 2453 RELEASE_ASSERT(bytecodeOffset < instructions().size());
9dae56ea
A
2454
2455 if (!m_rareData)
2456 return 0;
2457
2458 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
2459 for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
2460 // Handlers are ordered innermost first, so the first handler we encounter
2461 // that contains the source address is the correct handler to use.
93a37866 2462 if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end > bytecodeOffset)
9dae56ea
A
2463 return &exceptionHandlers[i];
2464 }
2465
2466 return 0;
2467}
2468
93a37866 2469unsigned CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
9dae56ea 2470{
93a37866
A
2471 RELEASE_ASSERT(bytecodeOffset < instructions().size());
2472 return m_ownerExecutable->lineNo() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset);
9dae56ea
A
2473}
2474
93a37866 2475unsigned CodeBlock::columnNumberForBytecodeOffset(unsigned bytecodeOffset)
9dae56ea 2476{
93a37866
A
2477 int divot;
2478 int startOffset;
2479 int endOffset;
2480 unsigned line;
2481 unsigned column;
2482 expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
2483 return column;
9dae56ea 2484}
9dae56ea 2485
93a37866 2486void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
9dae56ea 2487{
93a37866
A
2488 m_unlinkedCode->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
2489 divot += m_sourceOffset;
2490 column += line ? 1 : firstLineColumnOffset();
2491 line += m_ownerExecutable->lineNo();
9dae56ea 2492}
9dae56ea 2493
93a37866 2494void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
9dae56ea 2495{
93a37866
A
2496#if ENABLE(LLINT)
2497 m_llintCallLinkInfos.shrinkToFit();
4e4e5a6f
A
2498#endif
2499#if ENABLE(JIT)
9dae56ea 2500 m_structureStubInfos.shrinkToFit();
9dae56ea 2501 m_callLinkInfos.shrinkToFit();
9dae56ea 2502#endif
93a37866
A
2503#if ENABLE(VALUE_PROFILER)
2504 m_rareCaseProfiles.shrinkToFit();
2505 m_specialFastCaseProfiles.shrinkToFit();
2506#endif
2507
2508 if (shrinkMode == EarlyShrink) {
2509 m_identifiers.shrinkToFit();
2510 m_functionDecls.shrinkToFit();
2511 m_functionExprs.shrinkToFit();
2512 m_constantRegisters.shrinkToFit();
2513 } // else don't shrink these, because we would have already pointed pointers into these tables.
9dae56ea 2514
9dae56ea
A
2515 if (m_rareData) {
2516 m_rareData->m_exceptionHandlers.shrinkToFit();
9dae56ea
A
2517 m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
2518 m_rareData->m_characterSwitchJumpTables.shrinkToFit();
2519 m_rareData->m_stringSwitchJumpTables.shrinkToFit();
93a37866
A
2520#if ENABLE(JIT)
2521 m_rareData->m_callReturnIndexVector.shrinkToFit();
2522#endif
2523#if ENABLE(DFG_JIT)
2524 m_rareData->m_inlineCallFrames.shrinkToFit();
2525 m_rareData->m_codeOrigins.shrinkToFit();
2526#endif
2527 }
2528
2529#if ENABLE(DFG_JIT)
2530 if (m_dfgData) {
2531 m_dfgData->osrEntry.shrinkToFit();
2532 m_dfgData->osrExit.shrinkToFit();
2533 m_dfgData->speculationRecovery.shrinkToFit();
2534 m_dfgData->weakReferences.shrinkToFit();
2535 m_dfgData->transitions.shrinkToFit();
2536 m_dfgData->minifiedDFG.prepareAndShrink();
2537 m_dfgData->variableEventStream.shrinkToFit();
14957cd0 2538 }
93a37866 2539#endif
14957cd0
A
2540}
2541
2542void CodeBlock::createActivation(CallFrame* callFrame)
2543{
2544 ASSERT(codeType() == FunctionCode);
2545 ASSERT(needsFullScopeChain());
2546 ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue());
93a37866 2547 JSActivation* activation = JSActivation::create(callFrame->vm(), callFrame, this);
14957cd0 2548 callFrame->uncheckedR(activationRegister()) = JSValue(activation);
93a37866 2549 callFrame->setScope(activation);
14957cd0 2550}
6fe7ccc8
A
2551
2552unsigned CodeBlock::addOrFindConstant(JSValue v)
2553{
2554 unsigned numberOfConstants = numberOfConstantRegisters();
2555 for (unsigned i = 0; i < numberOfConstants; ++i) {
2556 if (getConstant(FirstConstantRegisterIndex + i) == v)
2557 return i;
2558 }
2559 return addConstant(v);
2560}
2561
9dae56ea 2562#if ENABLE(JIT)
14957cd0
A
2563void CodeBlock::unlinkCalls()
2564{
6fe7ccc8
A
2565 if (!!m_alternative)
2566 m_alternative->unlinkCalls();
2567#if ENABLE(LLINT)
2568 for (size_t i = 0; i < m_llintCallLinkInfos.size(); ++i) {
2569 if (m_llintCallLinkInfos[i].isLinked())
2570 m_llintCallLinkInfos[i].unlink();
2571 }
2572#endif
93a37866 2573 if (!m_callLinkInfos.size())
14957cd0 2574 return;
93a37866 2575 if (!m_vm->canUseJIT())
14957cd0
A
2576 return;
2577 RepatchBuffer repatchBuffer(this);
2578 for (size_t i = 0; i < m_callLinkInfos.size(); i++) {
2579 if (!m_callLinkInfos[i].isLinked())
2580 continue;
93a37866 2581 m_callLinkInfos[i].unlink(*m_vm, repatchBuffer);
9dae56ea
A
2582 }
2583}
6fe7ccc8
A
2584
2585void CodeBlock::unlinkIncomingCalls()
2586{
2587#if ENABLE(LLINT)
2588 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
2589 m_incomingLLIntCalls.begin()->unlink();
2590#endif
2591 if (m_incomingCalls.isEmpty())
2592 return;
2593 RepatchBuffer repatchBuffer(this);
2594 while (m_incomingCalls.begin() != m_incomingCalls.end())
93a37866
A
2595 m_incomingCalls.begin()->unlink(*m_vm, repatchBuffer);
2596}
2597#endif // ENABLE(JIT)
2598
2599#if ENABLE(LLINT)
2600Instruction* CodeBlock::adjustPCIfAtCallSite(Instruction* potentialReturnPC)
2601{
2602 ASSERT(potentialReturnPC);
2603
2604 unsigned returnPCOffset = potentialReturnPC - instructions().begin();
2605 Instruction* adjustedPC;
2606 unsigned opcodeLength;
2607
2608 // If we are at a callsite, the LLInt stores the PC after the call
2609 // instruction rather than the PC of the call instruction. This requires
2610 // some correcting. If so, we can rely on the fact that the preceding
2611 // instruction must be one of the call instructions, so either it's a
2612 // call_varargs or it's a call, construct, or eval.
2613 //
2614 // If we are not at a call site, then we need to guard against the
2615 // possibility of peeking past the start of the bytecode range for this
2616 // codeBlock. Hence, we do a bounds check before we peek at the
2617 // potential "preceding" instruction.
2618 // The bounds check is done by comparing the offset of the potential
2619 // returnPC with the length of the opcode. If there is room for a call
2620 // instruction before the returnPC, then the offset of the returnPC must
2621 // be greater than the size of the call opcode we're looking for.
2622
2623 // The determination of the call instruction present (if we are at a
2624 // callsite) depends on the following assumptions. So, assert that
2625 // they are still true:
2626 ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
2627 ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
2628 ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
2629
2630 // Check for the case of a preceeding op_call_varargs:
2631 opcodeLength = OPCODE_LENGTH(op_call_varargs);
2632 adjustedPC = potentialReturnPC - opcodeLength;
2633 if ((returnPCOffset >= opcodeLength)
2634 && (adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_call_varargs))) {
2635 return adjustedPC;
2636 }
2637
2638 // Check for the case of the other 3 call instructions:
2639 opcodeLength = OPCODE_LENGTH(op_call);
2640 adjustedPC = potentialReturnPC - opcodeLength;
2641 if ((returnPCOffset >= opcodeLength)
2642 && (adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_call)
2643 || adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_construct)
2644 || adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_call_eval))) {
2645 return adjustedPC;
2646 }
2647
2648 // Not a call site. No need to adjust PC. Just return the original.
2649 return potentialReturnPC;
6fe7ccc8 2650}
93a37866
A
2651#endif // ENABLE(LLINT)
2652
2653#if ENABLE(JIT)
2654ClosureCallStubRoutine* CodeBlock::findClosureCallForReturnPC(ReturnAddressPtr returnAddress)
2655{
2656 for (unsigned i = m_callLinkInfos.size(); i--;) {
2657 CallLinkInfo& info = m_callLinkInfos[i];
2658 if (!info.stub)
2659 continue;
2660 if (!info.stub->code().executableMemory()->contains(returnAddress.value()))
2661 continue;
2662
2663 RELEASE_ASSERT(info.stub->codeOrigin().bytecodeIndex < CodeOrigin::maximumBytecodeIndex);
2664 return info.stub.get();
2665 }
2666
2667 // The stub routine may have been jettisoned. This is rare, but we have to handle it.
2668 const JITStubRoutineSet& set = m_vm->heap.jitStubRoutines();
2669 for (unsigned i = set.size(); i--;) {
2670 GCAwareJITStubRoutine* genericStub = set.at(i);
2671 if (!genericStub->isClosureCall())
2672 continue;
2673 ClosureCallStubRoutine* stub = static_cast<ClosureCallStubRoutine*>(genericStub);
2674 if (!stub->code().executableMemory()->contains(returnAddress.value()))
2675 continue;
2676 RELEASE_ASSERT(stub->codeOrigin().bytecodeIndex < CodeOrigin::maximumBytecodeIndex);
2677 return stub;
2678 }
2679
2680 return 0;
2681}
2682#endif
6fe7ccc8
A
2683
2684unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress)
2685{
93a37866
A
2686 UNUSED_PARAM(exec);
2687 UNUSED_PARAM(returnAddress);
6fe7ccc8 2688#if ENABLE(LLINT)
93a37866
A
2689#if !ENABLE(LLINT_C_LOOP)
2690 // When using the JIT, we could have addresses that are not bytecode
2691 // addresses. We check if the return address is in the LLint glue and
2692 // opcode handlers range here to ensure that we are looking at bytecode
2693 // before attempting to convert the return address into a bytecode offset.
2694 //
2695 // In the case of the C Loop LLInt, the JIT is disabled, and the only
2696 // valid return addresses should be bytecode PCs. So, we can and need to
2697 // forego this check because when we do not ENABLE(COMPUTED_GOTO_OPCODES),
2698 // then the bytecode "PC"s are actually the opcodeIDs and are not bounded
2699 // by llint_begin and llint_end.
2700 if (returnAddress.value() >= LLInt::getCodePtr(llint_begin)
2701 && returnAddress.value() <= LLInt::getCodePtr(llint_end))
2702#endif
2703 {
2704 RELEASE_ASSERT(exec->codeBlock());
2705 RELEASE_ASSERT(exec->codeBlock() == this);
2706 RELEASE_ASSERT(JITCode::isBaselineCode(getJITType()));
6fe7ccc8 2707 Instruction* instruction = exec->currentVPC();
93a37866
A
2708 RELEASE_ASSERT(instruction);
2709
2710 instruction = adjustPCIfAtCallSite(instruction);
6fe7ccc8
A
2711 return bytecodeOffset(instruction);
2712 }
93a37866
A
2713#endif // !ENABLE(LLINT)
2714
2715#if ENABLE(JIT)
6fe7ccc8
A
2716 if (!m_rareData)
2717 return 1;
93a37866 2718 Vector<CallReturnOffsetToBytecodeOffset, 0, UnsafeVectorOverflow>& callIndices = m_rareData->m_callReturnIndexVector;
6fe7ccc8
A
2719 if (!callIndices.size())
2720 return 1;
93a37866
A
2721
2722 if (getJITCode().getExecutableMemory()->contains(returnAddress.value())) {
2723 unsigned callReturnOffset = getJITCode().offsetOf(returnAddress.value());
2724 CallReturnOffsetToBytecodeOffset* result =
2725 binarySearch<CallReturnOffsetToBytecodeOffset, unsigned>(
2726 callIndices, callIndices.size(), callReturnOffset, getCallReturnOffset);
2727 RELEASE_ASSERT(result->callReturnOffset == callReturnOffset);
2728 RELEASE_ASSERT(result->bytecodeOffset < instructionCount());
2729 return result->bytecodeOffset;
2730 }
2731 ClosureCallStubRoutine* closureInfo = findClosureCallForReturnPC(returnAddress);
2732 CodeOrigin origin = closureInfo->codeOrigin();
2733 while (InlineCallFrame* inlineCallFrame = origin.inlineCallFrame) {
2734 if (inlineCallFrame->baselineCodeBlock() == this)
2735 break;
2736 origin = inlineCallFrame->caller;
2737 RELEASE_ASSERT(origin.bytecodeIndex < CodeOrigin::maximumBytecodeIndex);
2738 }
2739 RELEASE_ASSERT(origin.bytecodeIndex < CodeOrigin::maximumBytecodeIndex);
2740 unsigned bytecodeIndex = origin.bytecodeIndex;
2741 RELEASE_ASSERT(bytecodeIndex < instructionCount());
2742 return bytecodeIndex;
2743#endif // ENABLE(JIT)
2744
2745#if !ENABLE(LLINT) && !ENABLE(JIT)
2746 return 1;
14957cd0 2747#endif
93a37866
A
2748}
2749
2750#if ENABLE(DFG_JIT)
2751bool CodeBlock::codeOriginForReturn(ReturnAddressPtr returnAddress, CodeOrigin& codeOrigin)
2752{
2753 if (!hasCodeOrigins())
2754 return false;
2755
2756 if (!getJITCode().getExecutableMemory()->contains(returnAddress.value())) {
2757 ClosureCallStubRoutine* stub = findClosureCallForReturnPC(returnAddress);
2758 ASSERT(stub);
2759 if (!stub)
2760 return false;
2761 codeOrigin = stub->codeOrigin();
2762 return true;
2763 }
2764
2765 unsigned offset = getJITCode().offsetOf(returnAddress.value());
2766 CodeOriginAtCallReturnOffset* entry =
2767 tryBinarySearch<CodeOriginAtCallReturnOffset, unsigned>(
2768 codeOrigins(), codeOrigins().size(), offset,
2769 getCallReturnOffsetForCodeOrigin);
2770 if (!entry)
2771 return false;
2772 codeOrigin = entry->codeOrigin;
2773 return true;
2774}
2775#endif // ENABLE(DFG_JIT)
14957cd0
A
2776
2777void CodeBlock::clearEvalCache()
2778{
6fe7ccc8
A
2779 if (!!m_alternative)
2780 m_alternative->clearEvalCache();
14957cd0
A
2781 if (!m_rareData)
2782 return;
2783 m_rareData->m_evalCodeCache.clear();
2784}
9dae56ea 2785
93a37866
A
2786template<typename T, size_t inlineCapacity, typename U, typename V>
2787inline void replaceExistingEntries(Vector<T, inlineCapacity, U>& target, Vector<T, inlineCapacity, V>& source)
6fe7ccc8
A
2788{
2789 ASSERT(target.size() <= source.size());
2790 for (size_t i = 0; i < target.size(); ++i)
2791 target[i] = source[i];
2792}
2793
2794void CodeBlock::copyPostParseDataFrom(CodeBlock* alternative)
2795{
2796 if (!alternative)
2797 return;
2798
2799 replaceExistingEntries(m_constantRegisters, alternative->m_constantRegisters);
2800 replaceExistingEntries(m_functionDecls, alternative->m_functionDecls);
2801 replaceExistingEntries(m_functionExprs, alternative->m_functionExprs);
2802 if (!!m_rareData && !!alternative->m_rareData)
2803 replaceExistingEntries(m_rareData->m_constantBuffers, alternative->m_rareData->m_constantBuffers);
2804}
2805
2806void CodeBlock::copyPostParseDataFromAlternative()
2807{
2808 copyPostParseDataFrom(m_alternative.get());
2809}
2810
2811#if ENABLE(JIT)
93a37866
A
2812void CodeBlock::reoptimize()
2813{
2814 ASSERT(replacement() != this);
2815 ASSERT(replacement()->alternative() == this);
2816 if (DFG::shouldShowDisassembly())
2817 dataLog(*replacement(), " will be jettisoned due to reoptimization of ", *this, ".\n");
2818 replacement()->jettison();
2819 countReoptimization();
2820}
2821
6fe7ccc8
A
2822CodeBlock* ProgramCodeBlock::replacement()
2823{
2824 return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode();
2825}
2826
2827CodeBlock* EvalCodeBlock::replacement()
2828{
2829 return &static_cast<EvalExecutable*>(ownerExecutable())->generatedBytecode();
2830}
2831
2832CodeBlock* FunctionCodeBlock::replacement()
2833{
2834 return &static_cast<FunctionExecutable*>(ownerExecutable())->generatedBytecodeFor(m_isConstructor ? CodeForConstruct : CodeForCall);
2835}
2836
93a37866 2837JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
6fe7ccc8
A
2838{
2839 if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
2840 return 0;
93a37866 2841 JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scope, bytecodeIndex);
6fe7ccc8
A
2842 return error;
2843}
2844
93a37866 2845JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
6fe7ccc8
A
2846{
2847 if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
2848 return 0;
93a37866 2849 JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scope, bytecodeIndex);
6fe7ccc8
A
2850 return error;
2851}
2852
93a37866 2853JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
6fe7ccc8
A
2854{
2855 if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType()))
2856 return 0;
93a37866 2857 JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scope, bytecodeIndex, m_isConstructor ? CodeForConstruct : CodeForCall);
6fe7ccc8
A
2858 return error;
2859}
2860
93a37866 2861DFG::CapabilityLevel ProgramCodeBlock::canCompileWithDFGInternal()
6fe7ccc8
A
2862{
2863 return DFG::canCompileProgram(this);
2864}
2865
93a37866 2866DFG::CapabilityLevel EvalCodeBlock::canCompileWithDFGInternal()
6fe7ccc8
A
2867{
2868 return DFG::canCompileEval(this);
2869}
2870
93a37866 2871DFG::CapabilityLevel FunctionCodeBlock::canCompileWithDFGInternal()
6fe7ccc8
A
2872{
2873 if (m_isConstructor)
2874 return DFG::canCompileFunctionForConstruct(this);
2875 return DFG::canCompileFunctionForCall(this);
2876}
2877
93a37866 2878void CodeBlock::jettison()
6fe7ccc8
A
2879{
2880 ASSERT(JITCode::isOptimizingJIT(getJITType()));
2881 ASSERT(this == replacement());
93a37866
A
2882 alternative()->optimizeAfterWarmUp();
2883 tallyFrequentExitSites();
2884 if (DFG::shouldShowDisassembly())
2885 dataLog("Jettisoning ", *this, ".\n");
2886 jettisonImpl();
6fe7ccc8
A
2887}
2888
93a37866 2889void ProgramCodeBlock::jettisonImpl()
6fe7ccc8 2890{
93a37866 2891 static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*vm());
6fe7ccc8
A
2892}
2893
93a37866 2894void EvalCodeBlock::jettisonImpl()
6fe7ccc8 2895{
93a37866
A
2896 static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*vm());
2897}
2898
2899void FunctionCodeBlock::jettisonImpl()
2900{
2901 static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*vm(), m_isConstructor ? CodeForConstruct : CodeForCall);
6fe7ccc8
A
2902}
2903
93a37866 2904bool ProgramCodeBlock::jitCompileImpl(ExecState* exec)
6fe7ccc8
A
2905{
2906 ASSERT(getJITType() == JITCode::InterpreterThunk);
2907 ASSERT(this == replacement());
93a37866 2908 return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(exec);
6fe7ccc8
A
2909}
2910
93a37866 2911bool EvalCodeBlock::jitCompileImpl(ExecState* exec)
6fe7ccc8
A
2912{
2913 ASSERT(getJITType() == JITCode::InterpreterThunk);
2914 ASSERT(this == replacement());
93a37866 2915 return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(exec);
6fe7ccc8
A
2916}
2917
93a37866 2918bool FunctionCodeBlock::jitCompileImpl(ExecState* exec)
6fe7ccc8
A
2919{
2920 ASSERT(getJITType() == JITCode::InterpreterThunk);
2921 ASSERT(this == replacement());
93a37866 2922 return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(exec, m_isConstructor ? CodeForConstruct : CodeForCall);
6fe7ccc8
A
2923}
2924#endif
2925
93a37866
A
2926JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin)
2927{
2928 if (!codeOrigin.inlineCallFrame)
2929 return globalObject();
2930 return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->generatedBytecode().globalObject();
2931}
2932
2933unsigned CodeBlock::reoptimizationRetryCounter() const
2934{
2935 ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax());
2936 return m_reoptimizationRetryCounter;
2937}
2938
2939void CodeBlock::countReoptimization()
2940{
2941 m_reoptimizationRetryCounter++;
2942 if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax())
2943 m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax();
2944}
2945
2946int32_t CodeBlock::codeTypeThresholdMultiplier() const
6fe7ccc8 2947{
93a37866
A
2948 if (codeType() == EvalCode)
2949 return Options::evalThresholdMultiplier();
2950
2951 return 1;
2952}
2953
2954double CodeBlock::optimizationThresholdScalingFactor()
2955{
2956 // This expression arises from doing a least-squares fit of
2957 //
2958 // F[x_] =: a * Sqrt[x + b] + Abs[c * x] + d
2959 //
2960 // against the data points:
2961 //
2962 // x F[x_]
2963 // 10 0.9 (smallest reasonable code block)
2964 // 200 1.0 (typical small-ish code block)
2965 // 320 1.2 (something I saw in 3d-cube that I wanted to optimize)
2966 // 1268 5.0 (something I saw in 3d-cube that I didn't want to optimize)
2967 // 4000 5.5 (random large size, used to cause the function to converge to a shallow curve of some sort)
2968 // 10000 6.0 (similar to above)
2969 //
2970 // I achieve the minimization using the following Mathematica code:
2971 //
2972 // MyFunctionTemplate[x_, a_, b_, c_, d_] := a*Sqrt[x + b] + Abs[c*x] + d
2973 //
2974 // samples = {{10, 0.9}, {200, 1}, {320, 1.2}, {1268, 5}, {4000, 5.5}, {10000, 6}}
2975 //
2976 // solution =
2977 // Minimize[Plus @@ ((MyFunctionTemplate[#[[1]], a, b, c, d] - #[[2]])^2 & /@ samples),
2978 // {a, b, c, d}][[2]]
2979 //
2980 // And the code below (to initialize a, b, c, d) is generated by:
2981 //
2982 // Print["const double " <> ToString[#[[1]]] <> " = " <>
2983 // If[#[[2]] < 0.00001, "0.0", ToString[#[[2]]]] <> ";"] & /@ solution
2984 //
2985 // We've long known the following to be true:
2986 // - Small code blocks are cheap to optimize and so we should do it sooner rather
2987 // than later.
2988 // - Large code blocks are expensive to optimize and so we should postpone doing so,
2989 // and sometimes have a large enough threshold that we never optimize them.
2990 // - The difference in cost is not totally linear because (a) just invoking the
2991 // DFG incurs some base cost and (b) for large code blocks there is enough slop
2992 // in the correlation between instruction count and the actual compilation cost
2993 // that for those large blocks, the instruction count should not have a strong
2994 // influence on our threshold.
2995 //
2996 // I knew the goals but I didn't know how to achieve them; so I picked an interesting
2997 // example where the heuristics were right (code block in 3d-cube with instruction
2998 // count 320, which got compiled early as it should have been) and one where they were
2999 // totally wrong (code block in 3d-cube with instruction count 1268, which was expensive
3000 // to compile and didn't run often enough to warrant compilation in my opinion), and
3001 // then threw in additional data points that represented my own guess of what our
3002 // heuristics should do for some round-numbered examples.
3003 //
3004 // The expression to which I decided to fit the data arose because I started with an
3005 // affine function, and then did two things: put the linear part in an Abs to ensure
3006 // that the fit didn't end up choosing a negative value of c (which would result in
3007 // the function turning over and going negative for large x) and I threw in a Sqrt
3008 // term because Sqrt represents my intution that the function should be more sensitive
3009 // to small changes in small values of x, but less sensitive when x gets large.
3010
3011 // Note that the current fit essentially eliminates the linear portion of the
3012 // expression (c == 0.0).
3013 const double a = 0.061504;
3014 const double b = 1.02406;
3015 const double c = 0.0;
3016 const double d = 0.825914;
3017
3018 double instructionCount = this->instructionCount();
3019
3020 ASSERT(instructionCount); // Make sure this is called only after we have an instruction stream; otherwise it'll just return the value of d, which makes no sense.
3021
3022 double result = d + a * sqrt(instructionCount + b) + c * instructionCount;
6fe7ccc8 3023#if ENABLE(JIT_VERBOSE_OSR)
93a37866 3024 dataLog(*this, ": instruction count is ", instructionCount, ", scaling execution counter by ", result, " * ", codeTypeThresholdMultiplier(), "\n");
6fe7ccc8 3025#endif
93a37866
A
3026 return result * codeTypeThresholdMultiplier();
3027}
6fe7ccc8 3028
93a37866
A
3029static int32_t clipThreshold(double threshold)
3030{
3031 if (threshold < 1.0)
3032 return 1;
3033
3034 if (threshold > static_cast<double>(std::numeric_limits<int32_t>::max()))
3035 return std::numeric_limits<int32_t>::max();
3036
3037 return static_cast<int32_t>(threshold);
3038}
3039
3040int32_t CodeBlock::counterValueForOptimizeAfterWarmUp()
3041{
3042 return clipThreshold(
3043 Options::thresholdForOptimizeAfterWarmUp() *
3044 optimizationThresholdScalingFactor() *
3045 (1 << reoptimizationRetryCounter()));
3046}
3047
3048int32_t CodeBlock::counterValueForOptimizeAfterLongWarmUp()
3049{
3050 return clipThreshold(
3051 Options::thresholdForOptimizeAfterLongWarmUp() *
3052 optimizationThresholdScalingFactor() *
3053 (1 << reoptimizationRetryCounter()));
3054}
3055
3056int32_t CodeBlock::counterValueForOptimizeSoon()
3057{
3058 return clipThreshold(
3059 Options::thresholdForOptimizeSoon() *
3060 optimizationThresholdScalingFactor() *
3061 (1 << reoptimizationRetryCounter()));
3062}
3063
3064bool CodeBlock::checkIfOptimizationThresholdReached()
3065{
3066 return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
3067}
3068
3069void CodeBlock::optimizeNextInvocation()
3070{
3071 m_jitExecuteCounter.setNewThreshold(0, this);
3072}
3073
3074void CodeBlock::dontOptimizeAnytimeSoon()
3075{
3076 m_jitExecuteCounter.deferIndefinitely();
3077}
3078
3079void CodeBlock::optimizeAfterWarmUp()
3080{
3081 m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterWarmUp(), this);
3082}
3083
3084void CodeBlock::optimizeAfterLongWarmUp()
3085{
3086 m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterLongWarmUp(), this);
3087}
3088
3089void CodeBlock::optimizeSoon()
3090{
3091 m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeSoon(), this);
3092}
3093
3094#if ENABLE(JIT)
3095uint32_t CodeBlock::adjustedExitCountThreshold(uint32_t desiredThreshold)
3096{
3097 ASSERT(getJITType() == JITCode::DFGJIT);
3098 // Compute this the lame way so we don't saturate. This is called infrequently
3099 // enough that this loop won't hurt us.
3100 unsigned result = desiredThreshold;
3101 for (unsigned n = baselineVersion()->reoptimizationRetryCounter(); n--;) {
3102 unsigned newResult = result << 1;
3103 if (newResult < result)
3104 return std::numeric_limits<uint32_t>::max();
3105 result = newResult;
3106 }
3107 return result;
3108}
3109
3110uint32_t CodeBlock::exitCountThresholdForReoptimization()
3111{
3112 return adjustedExitCountThreshold(Options::osrExitCountForReoptimization() * codeTypeThresholdMultiplier());
3113}
3114
3115uint32_t CodeBlock::exitCountThresholdForReoptimizationFromLoop()
3116{
3117 return adjustedExitCountThreshold(Options::osrExitCountForReoptimizationFromLoop() * codeTypeThresholdMultiplier());
3118}
3119
3120bool CodeBlock::shouldReoptimizeNow()
3121{
3122 return osrExitCounter() >= exitCountThresholdForReoptimization();
3123}
3124
3125bool CodeBlock::shouldReoptimizeFromLoopNow()
3126{
3127 return osrExitCounter() >= exitCountThresholdForReoptimizationFromLoop();
3128}
6fe7ccc8
A
3129#endif
3130
93a37866
A
3131#if ENABLE(VALUE_PROFILER)
3132ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset)
3133{
3134 for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) {
3135 if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset)
3136 return &m_arrayProfiles[i];
3137 }
3138 return 0;
3139}
3140
3141ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset)
3142{
3143 ArrayProfile* result = getArrayProfile(bytecodeOffset);
3144 if (result)
3145 return result;
3146 return addArrayProfile(bytecodeOffset);
3147}
3148
3149void CodeBlock::updateAllPredictionsAndCountLiveness(
3150 OperationInProgress operation, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
3151{
3152 numberOfLiveNonArgumentValueProfiles = 0;
3153 numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
6fe7ccc8
A
3154 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
3155 ValueProfile* profile = getFromAllValueProfiles(i);
3156 unsigned numSamples = profile->totalNumberOfSamples();
3157 if (numSamples > ValueProfile::numberOfBuckets)
3158 numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
3159 numberOfSamplesInProfiles += numSamples;
3160 if (profile->m_bytecodeOffset < 0) {
93a37866 3161 profile->computeUpdatedPrediction(operation);
6fe7ccc8
A
3162 continue;
3163 }
93a37866 3164 if (profile->numberOfSamples() || profile->m_prediction != SpecNone)
6fe7ccc8 3165 numberOfLiveNonArgumentValueProfiles++;
93a37866 3166 profile->computeUpdatedPrediction(operation);
6fe7ccc8 3167 }
93a37866
A
3168
3169#if ENABLE(DFG_JIT)
3170 m_lazyOperandValueProfiles.computeUpdatedPredictions(operation);
3171#endif
3172}
3173
3174void CodeBlock::updateAllValueProfilePredictions(OperationInProgress operation)
3175{
3176 unsigned ignoredValue1, ignoredValue2;
3177 updateAllPredictionsAndCountLiveness(operation, ignoredValue1, ignoredValue2);
3178}
3179
3180void CodeBlock::updateAllArrayPredictions(OperationInProgress operation)
3181{
3182 for (unsigned i = m_arrayProfiles.size(); i--;)
3183 m_arrayProfiles[i].computeUpdatedPrediction(this, operation);
3184
3185 // Don't count these either, for similar reasons.
3186 for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
3187 m_arrayAllocationProfiles[i].updateIndexingType();
3188}
3189
3190void CodeBlock::updateAllPredictions(OperationInProgress operation)
3191{
3192 updateAllValueProfilePredictions(operation);
3193 updateAllArrayPredictions(operation);
3194}
3195
3196bool CodeBlock::shouldOptimizeNow()
3197{
3198#if ENABLE(JIT_VERBOSE_OSR)
3199 dataLog("Considering optimizing ", *this, "...\n");
3200#endif
3201
3202#if ENABLE(VERBOSE_VALUE_PROFILE)
3203 dumpValueProfiles();
3204#endif
3205
3206 if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay())
3207 return true;
3208
3209 updateAllArrayPredictions();
3210
3211 unsigned numberOfLiveNonArgumentValueProfiles;
3212 unsigned numberOfSamplesInProfiles;
3213 updateAllPredictionsAndCountLiveness(NoOperation, numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles);
6fe7ccc8
A
3214
3215#if ENABLE(JIT_VERBOSE_OSR)
93a37866 3216 dataLogF("Profile hotness: %lf (%u / %u), %lf (%u / %u)\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(), numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles());
6fe7ccc8
A
3217#endif
3218
93a37866
A
3219 if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate())
3220 && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate())
3221 && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay())
6fe7ccc8
A
3222 return true;
3223
3224 ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max());
3225 m_optimizationDelayCounter++;
3226 optimizeAfterWarmUp();
3227 return false;
3228}
3229#endif
3230
3231#if ENABLE(DFG_JIT)
3232void CodeBlock::tallyFrequentExitSites()
3233{
3234 ASSERT(getJITType() == JITCode::DFGJIT);
3235 ASSERT(alternative()->getJITType() == JITCode::BaselineJIT);
3236 ASSERT(!!m_dfgData);
3237
3238 CodeBlock* profiledBlock = alternative();
3239
3240 for (unsigned i = 0; i < m_dfgData->osrExit.size(); ++i) {
3241 DFG::OSRExit& exit = m_dfgData->osrExit[i];
3242
93a37866 3243 if (!exit.considerAddingAsFrequentExitSite(profiledBlock))
6fe7ccc8
A
3244 continue;
3245
3246#if DFG_ENABLE(DEBUG_VERBOSE)
93a37866 3247 dataLog("OSR exit #", i, " (bc#", exit.m_codeOrigin.bytecodeIndex, ", ", exit.m_kind, ") for ", *this, " occurred frequently: counting as frequent exit site.\n");
6fe7ccc8
A
3248#endif
3249 }
3250}
3251#endif // ENABLE(DFG_JIT)
3252
3253#if ENABLE(VERBOSE_VALUE_PROFILE)
3254void CodeBlock::dumpValueProfiles()
3255{
93a37866 3256 dataLog("ValueProfile for ", *this, ":\n");
6fe7ccc8
A
3257 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
3258 ValueProfile* profile = getFromAllValueProfiles(i);
3259 if (profile->m_bytecodeOffset < 0) {
3260 ASSERT(profile->m_bytecodeOffset == -1);
93a37866 3261 dataLogF(" arg = %u: ", i);
6fe7ccc8 3262 } else
93a37866
A
3263 dataLogF(" bc = %d: ", profile->m_bytecodeOffset);
3264 if (!profile->numberOfSamples() && profile->m_prediction == SpecNone) {
3265 dataLogF("<empty>\n");
6fe7ccc8
A
3266 continue;
3267 }
3268 profile->dump(WTF::dataFile());
93a37866 3269 dataLogF("\n");
6fe7ccc8 3270 }
93a37866 3271 dataLog("RareCaseProfile for ", *this, ":\n");
6fe7ccc8
A
3272 for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) {
3273 RareCaseProfile* profile = rareCaseProfile(i);
93a37866 3274 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
6fe7ccc8 3275 }
93a37866 3276 dataLog("SpecialFastCaseProfile for ", *this, ":\n");
6fe7ccc8
A
3277 for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) {
3278 RareCaseProfile* profile = specialFastCaseProfile(i);
93a37866 3279 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
6fe7ccc8
A
3280 }
3281}
93a37866 3282#endif // ENABLE(VERBOSE_VALUE_PROFILE)
6fe7ccc8
A
3283
3284size_t CodeBlock::predictedMachineCodeSize()
3285{
93a37866 3286 // This will be called from CodeBlock::CodeBlock before either m_vm or the
6fe7ccc8
A
3287 // instructions have been initialized. It's OK to return 0 because what will really
3288 // matter is the recomputation of this value when the slow path is triggered.
93a37866 3289 if (!m_vm)
6fe7ccc8
A
3290 return 0;
3291
93a37866 3292 if (!m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT)
6fe7ccc8
A
3293 return 0; // It's as good of a prediction as we'll get.
3294
3295 // Be conservative: return a size that will be an overestimation 84% of the time.
93a37866
A
3296 double multiplier = m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.mean() +
3297 m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.standardDeviation();
6fe7ccc8
A
3298
3299 // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing
3300 // here is OK, since this whole method is just a heuristic.
3301 if (multiplier < 0 || multiplier > 1000)
3302 return 0;
3303
3304 double doubleResult = multiplier * m_instructions.size();
3305
3306 // Be even more paranoid: silently reject values that won't fit into a size_t. If
3307 // the function is so huge that we can't even fit it into virtual memory then we
3308 // should probably have some other guards in place to prevent us from even getting
3309 // to this point.
3310 if (doubleResult > std::numeric_limits<size_t>::max())
3311 return 0;
3312
3313 return static_cast<size_t>(doubleResult);
3314}
3315
3316bool CodeBlock::usesOpcode(OpcodeID opcodeID)
3317{
93a37866 3318 Interpreter* interpreter = vm()->interpreter;
6fe7ccc8
A
3319 Instruction* instructionsBegin = instructions().begin();
3320 unsigned instructionCount = instructions().size();
3321
3322 for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
3323 switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
3324#define DEFINE_OP(curOpcode, length) \
3325 case curOpcode: \
3326 if (curOpcode == opcodeID) \
3327 return true; \
3328 bytecodeOffset += length; \
3329 break;
3330 FOR_EACH_OPCODE_ID(DEFINE_OP)
3331#undef DEFINE_OP
3332 default:
93a37866 3333 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
3334 break;
3335 }
3336 }
3337
3338 return false;
3339}
3340
93a37866
A
3341String CodeBlock::nameForRegister(int registerNumber)
3342{
3343 SymbolTable::iterator end = symbolTable()->end();
3344 for (SymbolTable::iterator ptr = symbolTable()->begin(); ptr != end; ++ptr) {
3345 if (ptr->value.getIndex() == registerNumber)
3346 return String(ptr->key);
3347 }
3348 if (needsActivation() && registerNumber == activationRegister())
3349 return ASCIILiteral("activation");
3350 if (registerNumber == thisRegister())
3351 return ASCIILiteral("this");
3352 if (usesArguments()) {
3353 if (registerNumber == argumentsRegister())
3354 return ASCIILiteral("arguments");
3355 if (unmodifiedArgumentsRegister(argumentsRegister()) == registerNumber)
3356 return ASCIILiteral("real arguments");
3357 }
3358 if (registerNumber < 0) {
3359 int argumentPosition = -registerNumber;
3360 argumentPosition -= JSStack::CallFrameHeaderSize + 1;
3361 return String::format("arguments[%3d]", argumentPosition - 1).impl();
3362 }
3363 return "";
3364}
3365
9dae56ea 3366} // namespace JSC