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