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