blob: bf6d19de86ec6a8f82cd8fe5f68a2ad072edc8fc [file] [log] [blame]
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001/*
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002 * Copyright (C) 2008-2010, 2012-2015 Apple Inc. All rights reserved.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00003 * 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.
mjs@apple.com92047332014-03-15 04:08:27 +000014 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000015 * 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
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +000033#include "BasicBlockLocation.h"
barraclough@apple.comc2527d62010-08-11 19:52:41 +000034#include "BytecodeGenerator.h"
fpizlo@apple.com0309686b2013-12-02 19:49:43 +000035#include "BytecodeUseDef.h"
fpizlo@apple.com806b5822013-01-08 01:23:38 +000036#include "CallLinkStatus.h"
fpizlo@apple.com452cb412011-09-08 21:38:04 +000037#include "DFGCapabilities.h"
fpizlo@apple.com1e89af32012-11-19 02:55:14 +000038#include "DFGCommon.h"
fpizlo@apple.com62b6af82013-08-29 18:25:36 +000039#include "DFGDriver.h"
fpizlo@apple.comb426f862014-02-10 02:51:13 +000040#include "DFGJITCode.h"
oliver@apple.com284cc3d2013-07-25 04:00:33 +000041#include "DFGWorklist.h"
barraclough@apple.comc2527d62010-08-11 19:52:41 +000042#include "Debugger.h"
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +000043#include "FunctionExecutableDump.h"
saambarati1@gmail.com060e7512015-09-03 19:45:44 +000044#include "GetPutInfo.h"
ggaren@apple.com0dc469d2015-08-18 19:28:37 +000045#include "InlineCallFrame.h"
ggaren@apple.com901a8a22008-11-17 20:57:18 +000046#include "Interpreter.h"
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +000047#include "JIT.h"
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +000048#include "JITStubs.h"
oliver@apple.comd04e0a02014-02-01 01:37:59 +000049#include "JSCJSValue.h"
barraclough@apple.com3dc12332009-08-12 05:22:33 +000050#include "JSFunction.h"
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +000051#include "JSLexicalEnvironment.h"
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +000052#include "JSModuleEnvironment.h"
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +000053#include "LLIntEntrypoint.h"
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000054#include "LowLevelInterpreter.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000055#include "JSCInlines.h"
fpizlo@apple.comb26b5242015-09-10 19:49:36 +000056#include "PolymorphicAccess.h"
akling@apple.com5a0a87e2014-03-22 20:57:04 +000057#include "ProfilerDatabase.h"
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +000058#include "ReduceWhitespace.h"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +000059#include "Repatch.h"
mark.lam@apple.coma4fe7ab2012-11-09 03:03:44 +000060#include "SlotVisitorInlines.h"
msaboff@apple.com4d563e42014-08-16 01:45:40 +000061#include "StackVisitor.h"
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +000062#include "TypeLocationCache.h"
63#include "TypeProfiler.h"
akling@apple.com8427aaf2014-01-27 05:45:30 +000064#include "UnlinkedInstructionStream.h"
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000065#include <wtf/BagToHashMap.h>
fpizlo@apple.com806b5822013-01-08 01:23:38 +000066#include <wtf/CommaPrinter.h>
aroben@apple.coma2fd5702008-09-02 15:15:21 +000067#include <wtf/StringExtras.h>
fpizlo@apple.com9fe49132012-12-04 19:29:13 +000068#include <wtf/StringPrintStream.h>
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +000069#include <wtf/text/UniquedStringImpl.h>
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000070
msaboff@apple.com02085462015-09-10 17:47:16 +000071#if ENABLE(JIT)
72#include "RegisterAtOffsetList.h"
73#endif
74
commit-queue@webkit.org4ea48922011-07-06 00:56:49 +000075#if ENABLE(DFG_JIT)
76#include "DFGOperations.h"
77#endif
78
carlosgc@webkit.org13f6daf22013-07-30 06:42:00 +000079#if ENABLE(FTL_JIT)
80#include "FTLJITCode.h"
81#endif
82
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000083namespace JSC {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000084
oliver@apple.com02039462013-07-25 03:59:29 +000085CString CodeBlock::inferredName() const
fpizlo@apple.com1a6da212012-12-10 18:38:15 +000086{
87 switch (codeType()) {
88 case GlobalCode:
89 return "<global>";
90 case EvalCode:
91 return "<eval>";
92 case FunctionCode:
oliver@apple.com02039462013-07-25 03:59:29 +000093 return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().utf8();
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +000094 case ModuleCode:
95 return "<module>";
fpizlo@apple.com1a6da212012-12-10 18:38:15 +000096 default:
97 CRASH();
oliver@apple.com02039462013-07-25 03:59:29 +000098 return CString("", 0);
fpizlo@apple.com1a6da212012-12-10 18:38:15 +000099 }
100}
101
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000102bool CodeBlock::hasHash() const
103{
104 return !!m_hash;
105}
106
107bool CodeBlock::isSafeToComputeHash() const
108{
109 return !isCompilationThread();
110}
111
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000112CodeBlockHash CodeBlock::hash() const
113{
oliver@apple.comacdde492013-07-25 04:02:57 +0000114 if (!m_hash) {
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000115 RELEASE_ASSERT(isSafeToComputeHash());
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000116 m_hash = CodeBlockHash(ownerScriptExecutable()->source(), specializationKind());
oliver@apple.comacdde492013-07-25 04:02:57 +0000117 }
118 return m_hash;
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000119}
120
oliver@apple.com02039462013-07-25 03:59:29 +0000121CString CodeBlock::sourceCodeForTools() const
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000122{
123 if (codeType() != FunctionCode)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000124 return ownerScriptExecutable()->source().toUTF8();
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000125
126 SourceProvider* provider = source();
127 FunctionExecutable* executable = jsCast<FunctionExecutable*>(ownerExecutable());
128 UnlinkedFunctionExecutable* unlinked = executable->unlinkedExecutable();
129 unsigned unlinkedStartOffset = unlinked->startOffset();
130 unsigned linkedStartOffset = executable->source().startOffset();
131 int delta = linkedStartOffset - unlinkedStartOffset;
mark.lam@apple.comfa35e782013-11-19 21:55:16 +0000132 unsigned rangeStart = delta + unlinked->unlinkedFunctionNameStart();
oliver@apple.com02039462013-07-25 03:59:29 +0000133 unsigned rangeEnd = delta + unlinked->startOffset() + unlinked->sourceLength();
134 return toCString(
135 "function ",
136 provider->source().impl()->utf8ForRange(rangeStart, rangeEnd - rangeStart));
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000137}
138
oliver@apple.com02039462013-07-25 03:59:29 +0000139CString CodeBlock::sourceCodeOnOneLine() const
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000140{
141 return reduceWhitespace(sourceCodeForTools());
142}
143
fpizlo@apple.comf285f712014-03-13 01:50:41 +0000144CString CodeBlock::hashAsStringIfPossible() const
145{
146 if (hasHash() || isSafeToComputeHash())
147 return toCString(hash());
148 return "<no-hash>";
149}
150
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000151void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const
152{
fpizlo@apple.comf285f712014-03-13 01:50:41 +0000153 out.print(inferredName(), "#", hashAsStringIfPossible());
msaboff@apple.com95894332014-01-29 19:18:54 +0000154 out.print(":[", RawPointer(this), "->");
155 if (!!m_alternative)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +0000156 out.print(RawPointer(m_alternative.get()), "->");
msaboff@apple.com95894332014-01-29 19:18:54 +0000157 out.print(RawPointer(ownerExecutable()), ", ", jitType, codeType());
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000158
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000159 if (codeType() == FunctionCode)
160 out.print(specializationKind());
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000161 out.print(", ", instructionCount());
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000162 if (this->jitType() == JITCode::BaselineJIT && m_shouldAlwaysBeInlined)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000163 out.print(" (ShouldAlwaysBeInlined)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000164 if (ownerScriptExecutable()->neverInline())
oliver@apple.com4e67ae52013-07-25 04:01:24 +0000165 out.print(" (NeverInline)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000166 if (ownerScriptExecutable()->neverOptimize())
mark.lam@apple.com49e71b92015-08-28 05:59:44 +0000167 out.print(" (NeverOptimize)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000168 if (ownerScriptExecutable()->didTryToEnterInLoop())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000169 out.print(" (DidTryToEnterInLoop)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000170 if (ownerScriptExecutable()->isStrictMode())
fpizlo@apple.com018818d2013-09-13 23:18:19 +0000171 out.print(" (StrictMode)");
msaboff@apple.com95894332014-01-29 19:18:54 +0000172 if (this->jitType() == JITCode::BaselineJIT && m_didFailFTLCompilation)
173 out.print(" (FTLFail)");
174 if (this->jitType() == JITCode::BaselineJIT && m_hasBeenCompiledWithFTL)
175 out.print(" (HadFTLReplacement)");
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000176 out.print("]");
177}
178
179void CodeBlock::dump(PrintStream& out) const
180{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +0000181 dumpAssumingJITType(out, jitType());
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000182}
183
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000184static CString idName(int id0, const Identifier& ident)
185{
oliver@apple.com02039462013-07-25 03:59:29 +0000186 return toCString(ident.impl(), "(@id", id0, ")");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000187}
188
oliver@apple.com02039462013-07-25 03:59:29 +0000189CString CodeBlock::registerName(int r) const
mrowe@apple.comd5316092009-11-05 02:22:08 +0000190{
mrowe@apple.comd5316092009-11-05 02:22:08 +0000191 if (isConstantRegisterIndex(r))
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000192 return constantName(r);
mrowe@apple.comd5316092009-11-05 02:22:08 +0000193
fpizlo@apple.com240c7a52015-02-02 23:32:00 +0000194 return toCString(VirtualRegister(r));
mrowe@apple.comd5316092009-11-05 02:22:08 +0000195}
196
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000197CString CodeBlock::constantName(int index) const
198{
199 JSValue value = getConstant(index);
200 return toCString(value, "(", VirtualRegister(index), ")");
201}
202
oliver@apple.com02039462013-07-25 03:59:29 +0000203static CString regexpToSourceString(RegExp* regExp)
oliver@apple.com22d55c32010-05-10 01:41:07 +0000204{
205 char postfix[5] = { '/', 0, 0, 0, 0 };
206 int index = 1;
207 if (regExp->global())
208 postfix[index++] = 'g';
209 if (regExp->ignoreCase())
210 postfix[index++] = 'i';
211 if (regExp->multiline())
212 postfix[index] = 'm';
213
oliver@apple.com02039462013-07-25 03:59:29 +0000214 return toCString("/", regExp->pattern().impl(), postfix);
oliver@apple.com22d55c32010-05-10 01:41:07 +0000215}
216
217static CString regexpName(int re, RegExp* regexp)
218{
oliver@apple.com02039462013-07-25 03:59:29 +0000219 return toCString(regexpToSourceString(regexp), "(@re", re, ")");
oliver@apple.com22d55c32010-05-10 01:41:07 +0000220}
221
ggaren@apple.comd0740c82008-05-28 20:47:13 +0000222NEVER_INLINE static const char* debugHookName(int debugHookID)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000223{
weinig@apple.coma963b962008-06-05 05:36:55 +0000224 switch (static_cast<DebugHookID>(debugHookID)) {
225 case DidEnterCallFrame:
226 return "didEnterCallFrame";
227 case WillLeaveCallFrame:
228 return "willLeaveCallFrame";
229 case WillExecuteStatement:
230 return "willExecuteStatement";
231 case WillExecuteProgram:
232 return "willExecuteProgram";
233 case DidExecuteProgram:
234 return "didExecuteProgram";
235 case DidReachBreakpoint:
236 return "didReachBreakpoint";
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000237 }
weinig@apple.coma963b962008-06-05 05:36:55 +0000238
oliver@apple.com5598c182013-01-23 22:25:07 +0000239 RELEASE_ASSERT_NOT_REACHED();
ggaren@apple.comd0740c82008-05-28 20:47:13 +0000240 return "";
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000241}
242
msaboff@apple.comc5808642013-09-05 23:27:41 +0000243void CodeBlock::printUnaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000244{
245 int r0 = (++it)->u.operand;
246 int r1 = (++it)->u.operand;
247
msaboff@apple.comc5808642013-09-05 23:27:41 +0000248 printLocationAndOp(out, exec, location, it, op);
249 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000250}
251
msaboff@apple.comc5808642013-09-05 23:27:41 +0000252void CodeBlock::printBinaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000253{
254 int r0 = (++it)->u.operand;
255 int r1 = (++it)->u.operand;
256 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000257 printLocationAndOp(out, exec, location, it, op);
258 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000259}
260
msaboff@apple.comc5808642013-09-05 23:27:41 +0000261void CodeBlock::printConditionalJump(PrintStream& out, ExecState* exec, const Instruction*, const Instruction*& it, int location, const char* op)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000262{
263 int r0 = (++it)->u.operand;
264 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000265 printLocationAndOp(out, exec, location, it, op);
266 out.printf("%s, %d(->%d)", registerName(r0).data(), offset, location + offset);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000267}
268
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000269void CodeBlock::printGetByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it)
weinig@apple.com3412bb42008-09-01 21:22:54 +0000270{
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000271 const char* op;
272 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
273 case op_get_by_id:
274 op = "get_by_id";
275 break;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000276 case op_get_array_length:
277 op = "array_length";
278 break;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000279 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000280 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.com0a661162014-09-08 02:16:47 +0000281#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000282 op = 0;
mjs@apple.com0a661162014-09-08 02:16:47 +0000283#endif
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000284 }
weinig@apple.com3412bb42008-09-01 21:22:54 +0000285 int r0 = (++it)->u.operand;
286 int r1 = (++it)->u.operand;
287 int id0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000288 printLocationAndOp(out, exec, location, it, op);
289 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000290 it += 4; // Increment up to the value profiler.
weinig@apple.com3412bb42008-09-01 21:22:54 +0000291}
292
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000293static void dumpStructure(PrintStream& out, const char* name, Structure* structure, const Identifier& ident)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000294{
295 if (!structure)
296 return;
297
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000298 out.printf("%s = %p", name, structure);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000299
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000300 PropertyOffset offset = structure->getConcurrently(ident.impl());
fpizlo@apple.com961a9562012-07-24 02:13:19 +0000301 if (offset != invalidOffset)
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000302 out.printf(" (offset = %d)", offset);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000303}
304
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000305static void dumpChain(PrintStream& out, StructureChain* chain, const Identifier& ident)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000306{
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000307 out.printf("chain = %p: [", chain);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000308 bool first = true;
309 for (WriteBarrier<Structure>* currentStructure = chain->head();
310 *currentStructure;
311 ++currentStructure) {
312 if (first)
313 first = false;
314 else
fpizlo@apple.com304fbca2012-12-17 21:38:51 +0000315 out.printf(", ");
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000316 dumpStructure(out, "struct", currentStructure->get(), ident);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000317 }
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000318 out.printf("]");
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000319}
320
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000321void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000322{
323 Instruction* instruction = instructions().begin() + location;
324
oliver@apple.com9b652762013-08-12 22:39:13 +0000325 const Identifier& ident = identifier(instruction[3].u.operand);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000326
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000327 UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
328
fpizlo@apple.com4cafdbd2012-09-11 20:00:31 +0000329 if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000330 out.printf(" llint(array_length)");
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000331 else if (StructureID structureID = instruction[4].u.structureID) {
332 Structure* structure = m_vm->heap.structureIDTable().get(structureID);
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000333 out.printf(" llint(");
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000334 dumpStructure(out, "struct", structure, ident);
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000335 out.printf(")");
fpizlo@apple.com4cafdbd2012-09-11 20:00:31 +0000336 }
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000337
338#if ENABLE(JIT)
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000339 if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
340 StructureStubInfo& stubInfo = *stubPtr;
fpizlo@apple.com12803e22014-02-02 06:38:51 +0000341 if (stubInfo.resetByGC)
342 out.print(" (Reset By GC)");
343
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000344 if (stubInfo.seen) {
345 out.printf(" jit(");
346
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000347 Structure* baseStructure = nullptr;
348 PolymorphicAccess* stub = nullptr;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000349
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000350 switch (stubInfo.cacheType) {
351 case CacheType::GetByIdSelf:
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000352 out.printf("self");
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000353 baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get();
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000354 break;
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000355 case CacheType::Stub:
356 out.printf("stub");
357 stub = stubInfo.u.stub;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000358 break;
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000359 case CacheType::Unset:
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000360 out.printf("unset");
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000361 break;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000362 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000363 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000364 break;
365 }
366
367 if (baseStructure) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000368 out.printf(", ");
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000369 dumpStructure(out, "struct", baseStructure, ident);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000370 }
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000371
372 if (stub)
373 out.print(", ", *stub);
374
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000375 out.printf(")");
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000376 }
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000377 }
mark.lam@apple.comb1ea3ea2013-10-24 16:10:59 +0000378#else
379 UNUSED_PARAM(map);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000380#endif
381}
382
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000383void CodeBlock::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000384{
385 Instruction* instruction = instructions().begin() + location;
386
387 const Identifier& ident = identifier(instruction[2].u.operand);
388
389 UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000390
391 out.print(", ", instruction[8].u.putByIdFlags);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000392
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000393 if (StructureID structureID = instruction[4].u.structureID) {
394 Structure* structure = m_vm->heap.structureIDTable().get(structureID);
395 out.print(" llint(");
396 if (StructureID newStructureID = instruction[6].u.structureID) {
397 Structure* newStructure = m_vm->heap.structureIDTable().get(newStructureID);
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000398 dumpStructure(out, "prev", structure, ident);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000399 out.print(", ");
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000400 dumpStructure(out, "next", newStructure, ident);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000401 if (StructureChain* chain = instruction[7].u.structureChain.get()) {
402 out.print(", ");
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000403 dumpChain(out, chain, ident);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000404 }
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000405 } else
406 dumpStructure(out, "struct", structure, ident);
407 out.print(")");
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000408 }
409
410#if ENABLE(JIT)
411 if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
412 StructureStubInfo& stubInfo = *stubPtr;
413 if (stubInfo.resetByGC)
414 out.print(" (Reset By GC)");
415
416 if (stubInfo.seen) {
417 out.printf(" jit(");
418
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000419 switch (stubInfo.cacheType) {
420 case CacheType::PutByIdReplace:
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000421 out.print("replace, ");
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000422 dumpStructure(out, "struct", stubInfo.u.byIdSelf.baseObjectStructure.get(), ident);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000423 break;
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000424 case CacheType::Stub: {
425 out.print("stub, ", *stubInfo.u.stub);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000426 break;
427 }
fpizlo@apple.comb26b5242015-09-10 19:49:36 +0000428 case CacheType::Unset:
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000429 out.printf("unset");
430 break;
431 default:
432 RELEASE_ASSERT_NOT_REACHED();
433 break;
434 }
435 out.printf(")");
436 }
437 }
438#else
439 UNUSED_PARAM(map);
440#endif
441}
442
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000443void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, CacheDumpMode cacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap& map)
ggaren@apple.com6f82ad52012-01-12 01:00:58 +0000444{
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000445 int dst = (++it)->u.operand;
ggaren@apple.com6f82ad52012-01-12 01:00:58 +0000446 int func = (++it)->u.operand;
447 int argCount = (++it)->u.operand;
448 int registerOffset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000449 printLocationAndOp(out, exec, location, it, op);
450 out.printf("%s, %s, %d, %d", registerName(dst).data(), registerName(func).data(), argCount, registerOffset);
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000451 if (cacheDumpMode == DumpCaches) {
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000452 LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo;
453 if (callLinkInfo->lastSeenCallee) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000454 out.printf(
455 " llint(%p, exec %p)",
456 callLinkInfo->lastSeenCallee.get(),
457 callLinkInfo->lastSeenCallee->executable());
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000458 }
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000459#if ENABLE(JIT)
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000460 if (CallLinkInfo* info = map.get(CodeOrigin(location))) {
msaboff@apple.com203a56e2015-06-24 22:37:30 +0000461 JSFunction* target = info->lastSeenCallee();
fpizlo@apple.com5e3852d2012-05-24 00:05:21 +0000462 if (target)
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000463 out.printf(" jit(%p, exec %p)", target, target->executable());
fpizlo@apple.com5e3852d2012-05-24 00:05:21 +0000464 }
mark.lam@apple.com507b94e2015-04-17 00:25:14 +0000465
466 if (jitType() != JITCode::FTLJIT)
467 out.print(" status(", CallLinkStatus::computeFor(this, location, map), ")");
fpizlo@apple.comf7100b62014-03-24 17:29:51 +0000468#else
469 UNUSED_PARAM(map);
msaboff@apple.com95894332014-01-29 19:18:54 +0000470#endif
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000471 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000472 ++it;
oliver@apple.com7ff89b12014-02-21 22:37:29 +0000473 ++it;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000474 dumpArrayProfiling(out, it, hasPrintedProfiling);
475 dumpValueProfiling(out, it, hasPrintedProfiling);
ggaren@apple.com6f82ad52012-01-12 01:00:58 +0000476}
477
msaboff@apple.comc5808642013-09-05 23:27:41 +0000478void CodeBlock::printPutByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
weinig@apple.com3412bb42008-09-01 21:22:54 +0000479{
480 int r0 = (++it)->u.operand;
481 int id0 = (++it)->u.operand;
482 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000483 printLocationAndOp(out, exec, location, it, op);
484 out.printf("%s, %s, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), registerName(r1).data());
oliver@apple.comef690aa2010-07-15 20:00:31 +0000485 it += 5;
weinig@apple.com3412bb42008-09-01 21:22:54 +0000486}
487
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000488void CodeBlock::dumpSource()
489{
490 dumpSource(WTF::dataFile());
491}
492
493void CodeBlock::dumpSource(PrintStream& out)
494{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000495 ScriptExecutable* executable = ownerScriptExecutable();
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000496 if (executable->isFunctionExecutable()) {
497 FunctionExecutable* functionExecutable = reinterpret_cast<FunctionExecutable*>(executable);
498 String source = functionExecutable->source().provider()->getRange(
499 functionExecutable->parametersStartOffset(),
500 functionExecutable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
501
502 out.print("function ", inferredName(), source);
503 return;
504 }
505 out.print(executable->source().toString());
506}
507
508void CodeBlock::dumpBytecode()
509{
510 dumpBytecode(WTF::dataFile());
511}
512
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000513void CodeBlock::dumpBytecode(PrintStream& out)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000514{
fpizlo@apple.com1949f322012-11-22 00:46:57 +0000515 // We only use the ExecState* for things that don't actually lead to JS execution,
516 // like converting a JSString to a String. Hence the globalExec is appropriate.
517 ExecState* exec = m_globalObject->globalExec();
518
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000519 size_t instructionCount = 0;
weinig@apple.com0aaf82a2008-12-12 08:02:09 +0000520
fpizlo@apple.com9ac73f12011-11-10 04:37:32 +0000521 for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
weinig@apple.com0aaf82a2008-12-12 08:02:09 +0000522 ++instructionCount;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000523
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000524 out.print(*this);
525 out.printf(
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000526 ": %lu m_instructions; %lu bytes; %d parameter(s); %d callee register(s); %d variable(s)",
fpizlo@apple.comebe232e2012-02-27 02:07:34 +0000527 static_cast<unsigned long>(instructions().size()),
fpizlo@apple.com9ac73f12011-11-10 04:37:32 +0000528 static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000529 m_numParameters, m_numCalleeRegisters, m_numVars);
mark.lam@apple.com65a636f2014-02-01 01:24:39 +0000530 if (needsActivation() && codeType() == FunctionCode)
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +0000531 out.printf("; lexical environment in r%d", activationRegister().offset());
msaboff@apple.comc5808642013-09-05 23:27:41 +0000532 out.printf("\n");
533
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000534 StubInfoMap stubInfos;
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000535 CallLinkInfoMap callLinkInfos;
msaboff@apple.com95894332014-01-29 19:18:54 +0000536 getStubInfoMap(stubInfos);
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000537 getCallLinkInfoMap(callLinkInfos);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000538
fpizlo@apple.com1949f322012-11-22 00:46:57 +0000539 const Instruction* begin = instructions().begin();
540 const Instruction* end = instructions().end();
541 for (const Instruction* it = begin; it != end; ++it)
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000542 dumpBytecode(out, exec, begin, it, stubInfos, callLinkInfos);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000543
oliver@apple.com9b652762013-08-12 22:39:13 +0000544 if (numberOfIdentifiers()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000545 out.printf("\nIdentifiers:\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000546 size_t i = 0;
547 do {
oliver@apple.com9b652762013-08-12 22:39:13 +0000548 out.printf(" id%u = %s\n", static_cast<unsigned>(i), identifier(i).string().utf8().data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000549 ++i;
oliver@apple.com9b652762013-08-12 22:39:13 +0000550 } while (i != numberOfIdentifiers());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000551 }
552
weinig@apple.comcb26d812008-12-06 22:01:05 +0000553 if (!m_constantRegisters.isEmpty()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000554 out.printf("\nConstants:\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000555 size_t i = 0;
556 do {
mark.lam@apple.com61ba1f32015-03-10 19:29:13 +0000557 const char* sourceCodeRepresentationDescription = nullptr;
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000558 switch (m_constantsSourceCodeRepresentation[i]) {
559 case SourceCodeRepresentation::Double:
560 sourceCodeRepresentationDescription = ": in source as double";
561 break;
562 case SourceCodeRepresentation::Integer:
563 sourceCodeRepresentationDescription = ": in source as integer";
564 break;
565 case SourceCodeRepresentation::Other:
566 sourceCodeRepresentationDescription = "";
567 break;
568 }
569 out.printf(" k%u = %s%s\n", static_cast<unsigned>(i), toCString(m_constantRegisters[i].get()).data(), sourceCodeRepresentationDescription);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000570 ++i;
weinig@apple.comcb26d812008-12-06 22:01:05 +0000571 } while (i < m_constantRegisters.size());
cwzwarich@webkit.org300bb752008-08-06 10:37:34 +0000572 }
573
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000574 if (size_t count = m_unlinkedCode->numberOfRegExps()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000575 out.printf("\nm_regexps:\n");
oliver@apple.com22d55c32010-05-10 01:41:07 +0000576 size_t i = 0;
577 do {
oliver@apple.com02039462013-07-25 03:59:29 +0000578 out.printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).data());
oliver@apple.com22d55c32010-05-10 01:41:07 +0000579 ++i;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000580 } while (i < count);
oliver@apple.com22d55c32010-05-10 01:41:07 +0000581 }
582
weinig@apple.com4557e842008-12-09 01:06:14 +0000583 if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000584 out.printf("\nException Handlers:\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000585 unsigned i = 0;
586 do {
mark.lam@apple.com4585ce92015-05-30 00:19:01 +0000587 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
saambarati1@gmail.come85426c2015-08-07 17:41:22 +0000588 out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] } %s\n",
589 i + 1, handler.start, handler.end, handler.target, handler.typeName());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000590 ++i;
weinig@apple.com4557e842008-12-09 01:06:14 +0000591 } while (i < m_rareData->m_exceptionHandlers.size());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000592 }
oliver@apple.com8007f462008-07-24 00:49:46 +0000593
oliver@apple.coma14cea52013-07-25 04:03:23 +0000594 if (m_rareData && !m_rareData->m_switchJumpTables.isEmpty()) {
595 out.printf("Switch Jump Tables:\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000596 unsigned i = 0;
597 do {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000598 out.printf(" %1d = {\n", i);
oliver@apple.com8007f462008-07-24 00:49:46 +0000599 int entry = 0;
oliver@apple.coma14cea52013-07-25 04:03:23 +0000600 Vector<int32_t>::const_iterator end = m_rareData->m_switchJumpTables[i].branchOffsets.end();
601 for (Vector<int32_t>::const_iterator iter = m_rareData->m_switchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
weinig@apple.com3412bb42008-09-01 21:22:54 +0000602 if (!*iter)
603 continue;
oliver@apple.coma14cea52013-07-25 04:03:23 +0000604 out.printf("\t\t%4d => %04d\n", entry + m_rareData->m_switchJumpTables[i].min, *iter);
weinig@apple.com3412bb42008-09-01 21:22:54 +0000605 }
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000606 out.printf(" }\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000607 ++i;
oliver@apple.coma14cea52013-07-25 04:03:23 +0000608 } while (i < m_rareData->m_switchJumpTables.size());
oliver@apple.com8007f462008-07-24 00:49:46 +0000609 }
610
weinig@apple.com4557e842008-12-09 01:06:14 +0000611 if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000612 out.printf("\nString Switch Jump Tables:\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000613 unsigned i = 0;
614 do {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000615 out.printf(" %1d = {\n", i);
weinig@apple.com4557e842008-12-09 01:06:14 +0000616 StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
617 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
msaboff@apple.comc2d94712014-04-29 01:36:14 +0000618 out.printf("\t\t\"%s\" => %04d\n", iter->key->utf8().data(), iter->value.branchOffset);
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000619 out.printf(" }\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000620 ++i;
weinig@apple.com4557e842008-12-09 01:06:14 +0000621 } while (i < m_rareData->m_stringSwitchJumpTables.size());
oliver@apple.com8007f462008-07-24 00:49:46 +0000622 }
623
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000624 out.printf("\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000625}
626
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000627void CodeBlock::beginDumpProfiling(PrintStream& out, bool& hasPrintedProfiling)
628{
629 if (hasPrintedProfiling) {
630 out.print("; ");
631 return;
632 }
633
634 out.print(" ");
635 hasPrintedProfiling = true;
636}
637
638void CodeBlock::dumpValueProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000639{
oliver@apple.comd2056662013-07-25 04:00:37 +0000640 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000641
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000642 ++it;
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000643 CString description = it->u.profile->briefDescription(locker);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000644 if (!description.length())
645 return;
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000646 beginDumpProfiling(out, hasPrintedProfiling);
647 out.print(description);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000648}
649
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000650void CodeBlock::dumpArrayProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000651{
oliver@apple.comd2056662013-07-25 04:00:37 +0000652 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000653
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000654 ++it;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000655 if (!it->u.arrayProfile)
656 return;
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000657 CString description = it->u.arrayProfile->briefDescription(locker, this);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000658 if (!description.length())
659 return;
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000660 beginDumpProfiling(out, hasPrintedProfiling);
661 out.print(description);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000662}
663
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000664void CodeBlock::dumpRareCaseProfile(PrintStream& out, const char* name, RareCaseProfile* profile, bool& hasPrintedProfiling)
665{
666 if (!profile || !profile->m_counter)
667 return;
668
669 beginDumpProfiling(out, hasPrintedProfiling);
670 out.print(name, profile->m_counter);
671}
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000672
fpizlo@apple.com12803e22014-02-02 06:38:51 +0000673void CodeBlock::printLocationAndOp(PrintStream& out, ExecState*, int location, const Instruction*&, const char* op)
674{
675 out.printf("[%4d] %-17s ", location, op);
676}
677
678void CodeBlock::printLocationOpAndRegisterOperand(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, int operand)
679{
680 printLocationAndOp(out, exec, location, it, op);
681 out.printf("%s", registerName(operand).data());
682}
683
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000684void CodeBlock::dumpBytecode(
685 PrintStream& out, ExecState* exec, const Instruction* begin, const Instruction*& it,
686 const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000687{
688 int location = it - begin;
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000689 bool hasPrintedProfiling = false;
oliver@apple.com177c2b92014-03-28 01:10:25 +0000690 OpcodeID opcode = exec->interpreter()->getOpcodeID(it->u.opcode);
691 switch (opcode) {
mjs@apple.com8b246d62008-10-04 07:15:33 +0000692 case op_enter: {
msaboff@apple.comc5808642013-09-05 23:27:41 +0000693 printLocationAndOp(out, exec, location, it, "enter");
oliver@apple.comecfd2242008-09-20 03:00:43 +0000694 break;
695 }
msaboff@apple.com8b6b3412014-11-04 03:36:28 +0000696 case op_get_scope: {
697 int r0 = (++it)->u.operand;
698 printLocationOpAndRegisterOperand(out, exec, location, it, "get_scope", r0);
699 break;
700 }
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +0000701 case op_load_arrowfunction_this: {
702 int r0 = (++it)->u.operand;
703 printLocationOpAndRegisterOperand(out, exec, location, it, "load_arrowfunction_this", r0);
704 break;
705 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000706 case op_create_direct_arguments: {
ggaren@apple.com83ce11c2010-05-19 05:10:11 +0000707 int r0 = (++it)->u.operand;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000708 printLocationAndOp(out, exec, location, it, "create_direct_arguments");
709 out.printf("%s", registerName(r0).data());
cwzwarich@webkit.org9e464ca2008-09-29 03:04:08 +0000710 break;
711 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000712 case op_create_scoped_arguments: {
ggaren@apple.com83ce11c2010-05-19 05:10:11 +0000713 int r0 = (++it)->u.operand;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000714 int r1 = (++it)->u.operand;
715 printLocationAndOp(out, exec, location, it, "create_scoped_arguments");
716 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
717 break;
718 }
719 case op_create_out_of_band_arguments: {
720 int r0 = (++it)->u.operand;
721 printLocationAndOp(out, exec, location, it, "create_out_of_band_arguments");
722 out.printf("%s", registerName(r0).data());
oliver@apple.combe38ac42009-05-12 08:58:56 +0000723 break;
724 }
barraclough@apple.comfd8c28a2010-05-25 03:04:43 +0000725 case op_create_this: {
726 int r0 = (++it)->u.operand;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000727 int r1 = (++it)->u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000728 unsigned inferredInlineCapacity = (++it)->u.operand;
rniwa@webkit.org1b971d72015-05-14 04:19:18 +0000729 unsigned cachedFunction = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000730 printLocationAndOp(out, exec, location, it, "create_this");
rniwa@webkit.org1b971d72015-05-14 04:19:18 +0000731 out.printf("%s, %s, %u, %u", registerName(r0).data(), registerName(r1).data(), inferredInlineCapacity, cachedFunction);
barraclough@apple.comfd8c28a2010-05-25 03:04:43 +0000732 break;
733 }
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000734 case op_to_this: {
mjs@apple.com8b246d62008-10-04 07:15:33 +0000735 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000736 printLocationOpAndRegisterOperand(out, exec, location, it, "to_this", r0);
fpizlo@apple.com12803e22014-02-02 06:38:51 +0000737 Structure* structure = (++it)->u.structure.get();
738 if (structure)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000739 out.print(", cache(struct = ", RawPointer(structure), ")");
740 out.print(", ", (++it)->u.toThisStatus);
mjs@apple.com8b246d62008-10-04 07:15:33 +0000741 break;
742 }
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000743 case op_check_tdz: {
744 int r0 = (++it)->u.operand;
745 printLocationOpAndRegisterOperand(out, exec, location, it, "op_check_tdz", r0);
746 break;
747 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000748 case op_new_object: {
749 int r0 = (++it)->u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000750 unsigned inferredInlineCapacity = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000751 printLocationAndOp(out, exec, location, it, "new_object");
752 out.printf("%s, %u", registerName(r0).data(), inferredInlineCapacity);
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000753 ++it; // Skip object allocation profile.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000754 break;
755 }
756 case op_new_array: {
darin@apple.com9ce79022008-06-28 15:50:49 +0000757 int dst = (++it)->u.operand;
758 int argv = (++it)->u.operand;
759 int argc = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000760 printLocationAndOp(out, exec, location, it, "new_array");
761 out.printf("%s, %s, %d", registerName(dst).data(), registerName(argv).data(), argc);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000762 ++it; // Skip array allocation profile.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000763 break;
764 }
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000765 case op_new_array_with_size: {
766 int dst = (++it)->u.operand;
767 int length = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000768 printLocationAndOp(out, exec, location, it, "new_array_with_size");
769 out.printf("%s, %s", registerName(dst).data(), registerName(length).data());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000770 ++it; // Skip array allocation profile.
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000771 break;
772 }
oliver@apple.coma991d692011-06-14 23:39:25 +0000773 case op_new_array_buffer: {
774 int dst = (++it)->u.operand;
775 int argv = (++it)->u.operand;
776 int argc = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000777 printLocationAndOp(out, exec, location, it, "new_array_buffer");
778 out.printf("%s, %d, %d", registerName(dst).data(), argv, argc);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000779 ++it; // Skip array allocation profile.
oliver@apple.coma991d692011-06-14 23:39:25 +0000780 break;
781 }
oliver@apple.com22d55c32010-05-10 01:41:07 +0000782 case op_new_regexp: {
783 int r0 = (++it)->u.operand;
784 int re0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000785 printLocationAndOp(out, exec, location, it, "new_regexp");
786 out.printf("%s, ", registerName(r0).data());
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000787 if (r0 >=0 && r0 < (int)m_unlinkedCode->numberOfRegExps())
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000788 out.printf("%s", regexpName(re0, regexp(re0)).data());
fpizlo@apple.com68186e12011-08-17 20:54:32 +0000789 else
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000790 out.printf("bad_regexp(%d)", re0);
oliver@apple.com22d55c32010-05-10 01:41:07 +0000791 break;
792 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000793 case op_mov: {
794 int r0 = (++it)->u.operand;
795 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000796 printLocationAndOp(out, exec, location, it, "mov");
797 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000798 break;
799 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000800 case op_profile_type: {
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000801 int r0 = (++it)->u.operand;
802 ++it;
803 ++it;
commit-queue@webkit.org0163f122014-08-21 02:29:47 +0000804 ++it;
805 ++it;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000806 printLocationAndOp(out, exec, location, it, "op_profile_type");
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000807 out.printf("%s", registerName(r0).data());
808 break;
809 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +0000810 case op_profile_control_flow: {
811 BasicBlockLocation* basicBlockLocation = (++it)->u.basicBlockLocation;
812 printLocationAndOp(out, exec, location, it, "profile_control_flow");
813 out.printf("[%d, %d]", basicBlockLocation->startOffset(), basicBlockLocation->endOffset());
814 break;
815 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000816 case op_not: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000817 printUnaryOp(out, exec, location, it, "not");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000818 break;
819 }
820 case op_eq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000821 printBinaryOp(out, exec, location, it, "eq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000822 break;
823 }
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000824 case op_eq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000825 printUnaryOp(out, exec, location, it, "eq_null");
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000826 break;
827 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000828 case op_neq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000829 printBinaryOp(out, exec, location, it, "neq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000830 break;
831 }
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000832 case op_neq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000833 printUnaryOp(out, exec, location, it, "neq_null");
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000834 break;
835 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000836 case op_stricteq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000837 printBinaryOp(out, exec, location, it, "stricteq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000838 break;
839 }
840 case op_nstricteq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000841 printBinaryOp(out, exec, location, it, "nstricteq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000842 break;
843 }
844 case op_less: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000845 printBinaryOp(out, exec, location, it, "less");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000846 break;
847 }
848 case op_lesseq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000849 printBinaryOp(out, exec, location, it, "lesseq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000850 break;
851 }
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +0000852 case op_greater: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000853 printBinaryOp(out, exec, location, it, "greater");
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +0000854 break;
855 }
856 case op_greatereq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000857 printBinaryOp(out, exec, location, it, "greatereq");
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +0000858 break;
859 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000860 case op_inc: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000861 int r0 = (++it)->u.operand;
fpizlo@apple.com9bca4b82013-11-11 21:46:37 +0000862 printLocationOpAndRegisterOperand(out, exec, location, it, "inc", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000863 break;
864 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000865 case op_dec: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000866 int r0 = (++it)->u.operand;
fpizlo@apple.com9bca4b82013-11-11 21:46:37 +0000867 printLocationOpAndRegisterOperand(out, exec, location, it, "dec", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000868 break;
869 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000870 case op_to_number: {
871 printUnaryOp(out, exec, location, it, "to_number");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000872 break;
873 }
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000874 case op_to_string: {
875 printUnaryOp(out, exec, location, it, "to_string");
876 break;
877 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000878 case op_negate: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000879 printUnaryOp(out, exec, location, it, "negate");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000880 break;
881 }
882 case op_add: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000883 printBinaryOp(out, exec, location, it, "add");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000884 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000885 break;
886 }
887 case op_mul: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000888 printBinaryOp(out, exec, location, it, "mul");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000889 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000890 break;
891 }
892 case op_div: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000893 printBinaryOp(out, exec, location, it, "div");
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000894 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000895 break;
896 }
897 case op_mod: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000898 printBinaryOp(out, exec, location, it, "mod");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000899 break;
900 }
901 case op_sub: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000902 printBinaryOp(out, exec, location, it, "sub");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000903 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000904 break;
905 }
906 case op_lshift: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000907 printBinaryOp(out, exec, location, it, "lshift");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000908 break;
909 }
910 case op_rshift: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000911 printBinaryOp(out, exec, location, it, "rshift");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000912 break;
913 }
914 case op_urshift: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000915 printBinaryOp(out, exec, location, it, "urshift");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000916 break;
917 }
918 case op_bitand: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000919 printBinaryOp(out, exec, location, it, "bitand");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000920 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000921 break;
922 }
923 case op_bitxor: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000924 printBinaryOp(out, exec, location, it, "bitxor");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000925 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000926 break;
927 }
928 case op_bitor: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000929 printBinaryOp(out, exec, location, it, "bitor");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000930 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000931 break;
932 }
barraclough@apple.com8da6d972010-11-16 21:11:26 +0000933 case op_check_has_instance: {
barraclough@apple.comb46d57b42012-09-22 00:43:03 +0000934 int r0 = (++it)->u.operand;
935 int r1 = (++it)->u.operand;
936 int r2 = (++it)->u.operand;
937 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000938 printLocationAndOp(out, exec, location, it, "check_has_instance");
939 out.printf("%s, %s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), offset, location + offset);
barraclough@apple.com8da6d972010-11-16 21:11:26 +0000940 break;
941 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000942 case op_instanceof: {
mjs@apple.com988df6c2008-09-15 02:13:10 +0000943 int r0 = (++it)->u.operand;
944 int r1 = (++it)->u.operand;
945 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000946 printLocationAndOp(out, exec, location, it, "instanceof");
947 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000948 break;
949 }
fpizlo@apple.com9089acb2013-12-14 06:33:42 +0000950 case op_unsigned: {
951 printUnaryOp(out, exec, location, it, "unsigned");
952 break;
953 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000954 case op_typeof: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000955 printUnaryOp(out, exec, location, it, "typeof");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000956 break;
957 }
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000958 case op_is_undefined: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000959 printUnaryOp(out, exec, location, it, "is_undefined");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000960 break;
961 }
962 case op_is_boolean: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000963 printUnaryOp(out, exec, location, it, "is_boolean");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000964 break;
965 }
966 case op_is_number: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000967 printUnaryOp(out, exec, location, it, "is_number");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000968 break;
969 }
970 case op_is_string: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000971 printUnaryOp(out, exec, location, it, "is_string");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000972 break;
973 }
974 case op_is_object: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000975 printUnaryOp(out, exec, location, it, "is_object");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000976 break;
977 }
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +0000978 case op_is_object_or_null: {
979 printUnaryOp(out, exec, location, it, "is_object_or_null");
980 break;
981 }
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000982 case op_is_function: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000983 printUnaryOp(out, exec, location, it, "is_function");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +0000984 break;
985 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000986 case op_in: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000987 printBinaryOp(out, exec, location, it, "in");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000988 break;
989 }
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000990 case op_get_by_id:
fpizlo@apple.com970d8a92014-02-14 05:37:38 +0000991 case op_get_array_length: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000992 printGetByIdOp(out, exec, location, it);
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000993 printGetByIdCacheStatus(out, exec, location, stubInfos);
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000994 dumpValueProfiling(out, it, hasPrintedProfiling);
ggaren@apple.combc363092008-09-03 05:04:39 +0000995 break;
996 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000997 case op_put_by_id: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000998 printPutByIdOp(out, exec, location, it, "put_by_id");
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000999 printPutByIdCacheStatus(out, location, stubInfos);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +00001000 break;
1001 }
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001002 case op_put_getter_by_id: {
1003 int r0 = (++it)->u.operand;
1004 int id0 = (++it)->u.operand;
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001005 int n0 = (++it)->u.operand;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001006 int r1 = (++it)->u.operand;
1007 printLocationAndOp(out, exec, location, it, "put_getter_by_id");
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001008 out.printf("%s, %s, %d, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001009 break;
1010 }
1011 case op_put_setter_by_id: {
1012 int r0 = (++it)->u.operand;
1013 int id0 = (++it)->u.operand;
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001014 int n0 = (++it)->u.operand;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001015 int r1 = (++it)->u.operand;
1016 printLocationAndOp(out, exec, location, it, "put_setter_by_id");
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001017 out.printf("%s, %s, %d, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001018 break;
1019 }
barraclough@apple.com09a55682012-01-30 18:28:39 +00001020 case op_put_getter_setter: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001021 int r0 = (++it)->u.operand;
1022 int id0 = (++it)->u.operand;
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001023 int n0 = (++it)->u.operand;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001024 int r1 = (++it)->u.operand;
barraclough@apple.com09a55682012-01-30 18:28:39 +00001025 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001026 printLocationAndOp(out, exec, location, it, "put_getter_setter");
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001027 out.printf("%s, %s, %d, %s, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), n0, registerName(r1).data(), registerName(r2).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001028 break;
1029 }
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +00001030 case op_put_getter_by_val: {
1031 int r0 = (++it)->u.operand;
1032 int r1 = (++it)->u.operand;
1033 int n0 = (++it)->u.operand;
1034 int r2 = (++it)->u.operand;
1035 printLocationAndOp(out, exec, location, it, "put_getter_by_val");
1036 out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
1037 break;
1038 }
1039 case op_put_setter_by_val: {
1040 int r0 = (++it)->u.operand;
1041 int r1 = (++it)->u.operand;
1042 int n0 = (++it)->u.operand;
1043 int r2 = (++it)->u.operand;
1044 printLocationAndOp(out, exec, location, it, "put_setter_by_val");
1045 out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
1046 break;
1047 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001048 case op_del_by_id: {
1049 int r0 = (++it)->u.operand;
1050 int r1 = (++it)->u.operand;
1051 int id0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001052 printLocationAndOp(out, exec, location, it, "del_by_id");
1053 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001054 break;
1055 }
1056 case op_get_by_val: {
1057 int r0 = (++it)->u.operand;
1058 int r1 = (++it)->u.operand;
1059 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001060 printLocationAndOp(out, exec, location, it, "get_by_val");
1061 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001062 dumpArrayProfiling(out, it, hasPrintedProfiling);
1063 dumpValueProfiling(out, it, hasPrintedProfiling);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001064 break;
1065 }
1066 case op_put_by_val: {
1067 int r0 = (++it)->u.operand;
1068 int r1 = (++it)->u.operand;
1069 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001070 printLocationAndOp(out, exec, location, it, "put_by_val");
1071 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001072 dumpArrayProfiling(out, it, hasPrintedProfiling);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001073 break;
1074 }
oliver@apple.come050d642013-10-19 00:09:28 +00001075 case op_put_by_val_direct: {
1076 int r0 = (++it)->u.operand;
1077 int r1 = (++it)->u.operand;
1078 int r2 = (++it)->u.operand;
1079 printLocationAndOp(out, exec, location, it, "put_by_val_direct");
1080 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
1081 dumpArrayProfiling(out, it, hasPrintedProfiling);
1082 break;
1083 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001084 case op_del_by_val: {
1085 int r0 = (++it)->u.operand;
1086 int r1 = (++it)->u.operand;
1087 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001088 printLocationAndOp(out, exec, location, it, "del_by_val");
1089 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001090 break;
1091 }
1092 case op_put_by_index: {
1093 int r0 = (++it)->u.operand;
1094 unsigned n0 = (++it)->u.operand;
1095 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001096 printLocationAndOp(out, exec, location, it, "put_by_index");
1097 out.printf("%s, %u, %s", registerName(r0).data(), n0, registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001098 break;
1099 }
1100 case op_jmp: {
1101 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001102 printLocationAndOp(out, exec, location, it, "jmp");
1103 out.printf("%d(->%d)", offset, location + offset);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001104 break;
1105 }
1106 case op_jtrue: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001107 printConditionalJump(out, exec, begin, it, location, "jtrue");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001108 break;
1109 }
1110 case op_jfalse: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001111 printConditionalJump(out, exec, begin, it, location, "jfalse");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001112 break;
1113 }
cwzwarich@webkit.orgb8b30242008-10-22 21:06:30 +00001114 case op_jeq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001115 printConditionalJump(out, exec, begin, it, location, "jeq_null");
cwzwarich@webkit.orgb8b30242008-10-22 21:06:30 +00001116 break;
1117 }
1118 case op_jneq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001119 printConditionalJump(out, exec, begin, it, location, "jneq_null");
cwzwarich@webkit.orgb8b30242008-10-22 21:06:30 +00001120 break;
1121 }
oliver@apple.com6c106002009-03-28 03:50:39 +00001122 case op_jneq_ptr: {
cwzwarich@webkit.org7b04fef2008-06-30 06:17:01 +00001123 int r0 = (++it)->u.operand;
fpizlo@apple.com4500e352012-10-17 21:39:11 +00001124 Special::Pointer pointer = (++it)->u.specialPointer;
cwzwarich@webkit.org7b04fef2008-06-30 06:17:01 +00001125 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001126 printLocationAndOp(out, exec, location, it, "jneq_ptr");
1127 out.printf("%s, %d (%p), %d(->%d)", registerName(r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset);
oliver@apple.com6c106002009-03-28 03:50:39 +00001128 break;
1129 }
mjs@apple.coma46c49c2009-12-06 09:42:03 +00001130 case op_jless: {
1131 int r0 = (++it)->u.operand;
1132 int r1 = (++it)->u.operand;
1133 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001134 printLocationAndOp(out, exec, location, it, "jless");
1135 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
mjs@apple.coma46c49c2009-12-06 09:42:03 +00001136 break;
1137 }
oliver@apple.com5230bd32010-05-06 19:39:54 +00001138 case op_jlesseq: {
1139 int r0 = (++it)->u.operand;
1140 int r1 = (++it)->u.operand;
1141 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001142 printLocationAndOp(out, exec, location, it, "jlesseq");
1143 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
oliver@apple.com5230bd32010-05-06 19:39:54 +00001144 break;
1145 }
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001146 case op_jgreater: {
1147 int r0 = (++it)->u.operand;
1148 int r1 = (++it)->u.operand;
1149 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001150 printLocationAndOp(out, exec, location, it, "jgreater");
1151 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001152 break;
1153 }
1154 case op_jgreatereq: {
1155 int r0 = (++it)->u.operand;
1156 int r1 = (++it)->u.operand;
1157 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001158 printLocationAndOp(out, exec, location, it, "jgreatereq");
1159 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001160 break;
1161 }
1162 case op_jnless: {
1163 int r0 = (++it)->u.operand;
1164 int r1 = (++it)->u.operand;
1165 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001166 printLocationAndOp(out, exec, location, it, "jnless");
1167 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001168 break;
1169 }
1170 case op_jnlesseq: {
1171 int r0 = (++it)->u.operand;
1172 int r1 = (++it)->u.operand;
1173 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001174 printLocationAndOp(out, exec, location, it, "jnlesseq");
1175 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001176 break;
1177 }
1178 case op_jngreater: {
1179 int r0 = (++it)->u.operand;
1180 int r1 = (++it)->u.operand;
1181 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001182 printLocationAndOp(out, exec, location, it, "jngreater");
1183 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001184 break;
1185 }
1186 case op_jngreatereq: {
1187 int r0 = (++it)->u.operand;
1188 int r1 = (++it)->u.operand;
1189 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001190 printLocationAndOp(out, exec, location, it, "jngreatereq");
1191 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001192 break;
1193 }
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001194 case op_loop_hint: {
msaboff@apple.comc5808642013-09-05 23:27:41 +00001195 printLocationAndOp(out, exec, location, it, "loop_hint");
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001196 break;
1197 }
oliver@apple.com8007f462008-07-24 00:49:46 +00001198 case op_switch_imm: {
1199 int tableIndex = (++it)->u.operand;
1200 int defaultTarget = (++it)->u.operand;
1201 int scrutineeRegister = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001202 printLocationAndOp(out, exec, location, it, "switch_imm");
1203 out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
oliver@apple.com8007f462008-07-24 00:49:46 +00001204 break;
1205 }
1206 case op_switch_char: {
1207 int tableIndex = (++it)->u.operand;
1208 int defaultTarget = (++it)->u.operand;
1209 int scrutineeRegister = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001210 printLocationAndOp(out, exec, location, it, "switch_char");
1211 out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
oliver@apple.com8007f462008-07-24 00:49:46 +00001212 break;
1213 }
1214 case op_switch_string: {
1215 int tableIndex = (++it)->u.operand;
1216 int defaultTarget = (++it)->u.operand;
1217 int scrutineeRegister = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001218 printLocationAndOp(out, exec, location, it, "switch_string");
1219 out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
oliver@apple.com8007f462008-07-24 00:49:46 +00001220 break;
1221 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001222 case op_new_func: {
1223 int r0 = (++it)->u.operand;
msaboff@apple.comea77cd02014-11-14 01:07:48 +00001224 int r1 = (++it)->u.operand;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001225 int f0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001226 printLocationAndOp(out, exec, location, it, "new_func");
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001227 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001228 break;
1229 }
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00001230 case op_new_arrow_func_exp: {
1231 int r0 = (++it)->u.operand;
1232 int r1 = (++it)->u.operand;
1233 int f0 = (++it)->u.operand;
1234 int r2 = (++it)->u.operand;
1235 printLocationAndOp(out, exec, location, it, "op_new_arrow_func_exp");
1236 out.printf("%s, %s, f%d, %s", registerName(r0).data(), registerName(r1).data(), f0, registerName(r2).data());
1237 break;
1238 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001239 case op_new_func_exp: {
1240 int r0 = (++it)->u.operand;
msaboff@apple.comea77cd02014-11-14 01:07:48 +00001241 int r1 = (++it)->u.operand;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001242 int f0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001243 printLocationAndOp(out, exec, location, it, "new_func_exp");
msaboff@apple.comea77cd02014-11-14 01:07:48 +00001244 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001245 break;
1246 }
1247 case op_call: {
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001248 printCallOp(out, exec, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001249 break;
1250 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001251 case op_tail_call: {
1252 printCallOp(out, exec, location, it, "tail_call", DumpCaches, hasPrintedProfiling, callLinkInfos);
1253 break;
1254 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001255 case op_call_eval: {
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001256 printCallOp(out, exec, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001257 break;
1258 }
oliver@apple.com177c2b92014-03-28 01:10:25 +00001259
1260 case op_construct_varargs:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001261 case op_call_varargs:
1262 case op_tail_call_varargs: {
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001263 int result = (++it)->u.operand;
ggaren@apple.com539d1bb2011-11-14 19:21:40 +00001264 int callee = (++it)->u.operand;
1265 int thisValue = (++it)->u.operand;
1266 int arguments = (++it)->u.operand;
1267 int firstFreeRegister = (++it)->u.operand;
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001268 int varArgOffset = (++it)->u.operand;
oliver@apple.comdc48dc32013-07-25 04:01:42 +00001269 ++it;
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001270 printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? "call_varargs" : opcode == op_construct_varargs ? "construct_varargs" : "tail_call_varargs");
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001271 out.printf("%s, %s, %s, %s, %d, %d", registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001272 dumpValueProfiling(out, it, hasPrintedProfiling);
oliver@apple.com65e286e2009-04-08 23:08:28 +00001273 break;
1274 }
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001275
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001276 case op_ret: {
1277 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001278 printLocationOpAndRegisterOperand(out, exec, location, it, "ret", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001279 break;
1280 }
1281 case op_construct: {
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001282 printCallOp(out, exec, location, it, "construct", DumpCaches, hasPrintedProfiling, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001283 break;
1284 }
barraclough@apple.com14dc4e12009-05-07 00:06:07 +00001285 case op_strcat: {
1286 int r0 = (++it)->u.operand;
1287 int r1 = (++it)->u.operand;
1288 int count = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001289 printLocationAndOp(out, exec, location, it, "strcat");
1290 out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), count);
barraclough@apple.com14dc4e12009-05-07 00:06:07 +00001291 break;
1292 }
1293 case op_to_primitive: {
1294 int r0 = (++it)->u.operand;
1295 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001296 printLocationAndOp(out, exec, location, it, "to_primitive");
1297 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
barraclough@apple.com14dc4e12009-05-07 00:06:07 +00001298 break;
1299 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001300 case op_get_enumerable_length: {
1301 int dst = it[1].u.operand;
1302 int base = it[2].u.operand;
1303 printLocationAndOp(out, exec, location, it, "op_get_enumerable_length");
1304 out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
1305 it += OPCODE_LENGTH(op_get_enumerable_length) - 1;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001306 break;
1307 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001308 case op_has_indexed_property: {
1309 int dst = it[1].u.operand;
xan@webkit.orgb469f502010-10-13 15:39:37 +00001310 int base = it[2].u.operand;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001311 int propertyName = it[3].u.operand;
1312 ArrayProfile* arrayProfile = it[4].u.arrayProfile;
1313 printLocationAndOp(out, exec, location, it, "op_has_indexed_property");
1314 out.printf("%s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), arrayProfile);
1315 it += OPCODE_LENGTH(op_has_indexed_property) - 1;
1316 break;
1317 }
1318 case op_has_structure_property: {
1319 int dst = it[1].u.operand;
1320 int base = it[2].u.operand;
1321 int propertyName = it[3].u.operand;
1322 int enumerator = it[4].u.operand;
1323 printLocationAndOp(out, exec, location, it, "op_has_structure_property");
1324 out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(enumerator).data());
1325 it += OPCODE_LENGTH(op_has_structure_property) - 1;
1326 break;
1327 }
1328 case op_has_generic_property: {
1329 int dst = it[1].u.operand;
1330 int base = it[2].u.operand;
1331 int propertyName = it[3].u.operand;
1332 printLocationAndOp(out, exec, location, it, "op_has_generic_property");
1333 out.printf("%s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data());
1334 it += OPCODE_LENGTH(op_has_generic_property) - 1;
1335 break;
1336 }
1337 case op_get_direct_pname: {
1338 int dst = it[1].u.operand;
1339 int base = it[2].u.operand;
1340 int propertyName = it[3].u.operand;
1341 int index = it[4].u.operand;
1342 int enumerator = it[5].u.operand;
1343 ValueProfile* profile = it[6].u.profile;
1344 printLocationAndOp(out, exec, location, it, "op_get_direct_pname");
1345 out.printf("%s, %s, %s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(index).data(), registerName(enumerator).data(), profile);
1346 it += OPCODE_LENGTH(op_get_direct_pname) - 1;
1347 break;
1348
1349 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00001350 case op_get_property_enumerator: {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001351 int dst = it[1].u.operand;
1352 int base = it[2].u.operand;
msaboff@apple.comb644c252015-03-24 10:05:21 +00001353 printLocationAndOp(out, exec, location, it, "op_get_property_enumerator");
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001354 out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
msaboff@apple.comb644c252015-03-24 10:05:21 +00001355 it += OPCODE_LENGTH(op_get_property_enumerator) - 1;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001356 break;
1357 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00001358 case op_enumerator_structure_pname: {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001359 int dst = it[1].u.operand;
1360 int enumerator = it[2].u.operand;
1361 int index = it[3].u.operand;
msaboff@apple.comb644c252015-03-24 10:05:21 +00001362 printLocationAndOp(out, exec, location, it, "op_enumerator_structure_pname");
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001363 out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
msaboff@apple.comb644c252015-03-24 10:05:21 +00001364 it += OPCODE_LENGTH(op_enumerator_structure_pname) - 1;
1365 break;
1366 }
1367 case op_enumerator_generic_pname: {
1368 int dst = it[1].u.operand;
1369 int enumerator = it[2].u.operand;
1370 int index = it[3].u.operand;
1371 printLocationAndOp(out, exec, location, it, "op_enumerator_generic_pname");
1372 out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
1373 it += OPCODE_LENGTH(op_enumerator_generic_pname) - 1;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001374 break;
1375 }
1376 case op_to_index_string: {
1377 int dst = it[1].u.operand;
1378 int index = it[2].u.operand;
1379 printLocationAndOp(out, exec, location, it, "op_to_index_string");
1380 out.printf("%s, %s", registerName(dst).data(), registerName(index).data());
1381 it += OPCODE_LENGTH(op_to_index_string) - 1;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001382 break;
1383 }
ggaren@apple.com170d6f22012-09-02 21:27:23 +00001384 case op_push_with_scope: {
msaboff@apple.comc5b95392014-10-31 21:27:10 +00001385 int dst = (++it)->u.operand;
1386 int newScope = (++it)->u.operand;
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00001387 int currentScope = (++it)->u.operand;
msaboff@apple.comc5b95392014-10-31 21:27:10 +00001388 printLocationAndOp(out, exec, location, it, "push_with_scope");
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00001389 out.printf("%s, %s, %s", registerName(dst).data(), registerName(newScope).data(), registerName(currentScope).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001390 break;
1391 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001392 case op_get_parent_scope: {
1393 int dst = (++it)->u.operand;
1394 int parentScope = (++it)->u.operand;
1395 printLocationAndOp(out, exec, location, it, "get_parent_scope");
1396 out.printf("%s, %s", registerName(dst).data(), registerName(parentScope).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001397 break;
1398 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001399 case op_create_lexical_environment: {
1400 int dst = (++it)->u.operand;
1401 int scope = (++it)->u.operand;
1402 int symbolTable = (++it)->u.operand;
1403 int initialValue = (++it)->u.operand;
1404 printLocationAndOp(out, exec, location, it, "create_lexical_environment");
1405 out.printf("%s, %s, %s, %s",
1406 registerName(dst).data(), registerName(scope).data(), registerName(symbolTable).data(), registerName(initialValue).data());
1407 break;
1408 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001409 case op_catch: {
1410 int r0 = (++it)->u.operand;
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00001411 int r1 = (++it)->u.operand;
1412 printLocationAndOp(out, exec, location, it, "catch");
1413 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001414 break;
1415 }
1416 case op_throw: {
1417 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001418 printLocationOpAndRegisterOperand(out, exec, location, it, "throw", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001419 break;
1420 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001421 case op_throw_static_error: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001422 int k0 = (++it)->u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001423 int k1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001424 printLocationAndOp(out, exec, location, it, "throw_static_error");
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00001425 out.printf("%s, %s", constantName(k0).data(), k1 ? "true" : "false");
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001426 break;
1427 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001428 case op_debug: {
1429 int debugHookID = (++it)->u.operand;
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001430 int hasBreakpointFlag = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001431 printLocationAndOp(out, exec, location, it, "debug");
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001432 out.printf("%s %d", debugHookName(debugHookID), hasBreakpointFlag);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001433 break;
1434 }
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +00001435 case op_profile_will_call: {
1436 int function = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001437 printLocationOpAndRegisterOperand(out, exec, location, it, "profile_will_call", function);
ggaren@apple.com4b8c0fb2008-10-20 16:48:30 +00001438 break;
1439 }
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +00001440 case op_profile_did_call: {
1441 int function = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001442 printLocationOpAndRegisterOperand(out, exec, location, it, "profile_did_call", function);
ggaren@apple.com4b8c0fb2008-10-20 16:48:30 +00001443 break;
1444 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001445 case op_end: {
1446 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001447 printLocationOpAndRegisterOperand(out, exec, location, it, "end", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001448 break;
1449 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001450 case op_resolve_scope: {
1451 int r0 = (++it)->u.operand;
msaboff@apple.com44641f02014-11-03 17:56:29 +00001452 int scope = (++it)->u.operand;
oliver@apple.com58c86752013-07-25 04:02:40 +00001453 int id0 = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001454 ResolveType resolveType = static_cast<ResolveType>((++it)->u.operand);
mark.lam@apple.com65a636f2014-02-01 01:24:39 +00001455 int depth = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001456 void* pointer = (++it)->u.pointer;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001457 printLocationAndOp(out, exec, location, it, "resolve_scope");
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001458 out.printf("%s, %s, %s, <%s>, %d, %p", registerName(r0).data(), registerName(scope).data(), idName(id0, identifier(id0)).data(), resolveTypeName(resolveType), depth, pointer);
oliver@apple.com58c86752013-07-25 04:02:40 +00001459 break;
1460 }
1461 case op_get_from_scope: {
1462 int r0 = (++it)->u.operand;
1463 int r1 = (++it)->u.operand;
1464 int id0 = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001465 GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
oliver@apple.com58c86752013-07-25 04:02:40 +00001466 ++it; // Structure
mark.lam@apple.com65a636f2014-02-01 01:24:39 +00001467 int operand = (++it)->u.operand; // Operand
msaboff@apple.comc5808642013-09-05 23:27:41 +00001468 printLocationAndOp(out, exec, location, it, "get_from_scope");
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001469 out.print(registerName(r0), ", ", registerName(r1));
1470 if (static_cast<unsigned>(id0) == UINT_MAX)
1471 out.print(", anonymous");
1472 else
1473 out.print(", ", idName(id0, identifier(id0)));
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001474 out.print(", ", getPutInfo.operand(), "<", resolveModeName(getPutInfo.resolveMode()), "|", resolveTypeName(getPutInfo.resolveType()), "|", initializationModeName(getPutInfo.initializationMode()), ">, ", operand);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001475 dumpValueProfiling(out, it, hasPrintedProfiling);
oliver@apple.com58c86752013-07-25 04:02:40 +00001476 break;
1477 }
1478 case op_put_to_scope: {
1479 int r0 = (++it)->u.operand;
1480 int id0 = (++it)->u.operand;
1481 int r1 = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001482 GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
oliver@apple.com58c86752013-07-25 04:02:40 +00001483 ++it; // Structure
mark.lam@apple.com65a636f2014-02-01 01:24:39 +00001484 int operand = (++it)->u.operand; // Operand
msaboff@apple.comc5808642013-09-05 23:27:41 +00001485 printLocationAndOp(out, exec, location, it, "put_to_scope");
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001486 out.print(registerName(r0));
1487 if (static_cast<unsigned>(id0) == UINT_MAX)
1488 out.print(", anonymous");
1489 else
1490 out.print(", ", idName(id0, identifier(id0)));
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001491 out.print(", ", registerName(r1), ", ", getPutInfo.operand(), "<", resolveModeName(getPutInfo.resolveMode()), "|", resolveTypeName(getPutInfo.resolveType()), "|", initializationModeName(getPutInfo.initializationMode()), ">, <structure>, ", operand);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001492 break;
1493 }
1494 case op_get_from_arguments: {
1495 int r0 = (++it)->u.operand;
1496 int r1 = (++it)->u.operand;
1497 int offset = (++it)->u.operand;
1498 printLocationAndOp(out, exec, location, it, "get_from_arguments");
1499 out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), offset);
1500 dumpValueProfiling(out, it, hasPrintedProfiling);
1501 break;
1502 }
1503 case op_put_to_arguments: {
1504 int r0 = (++it)->u.operand;
1505 int offset = (++it)->u.operand;
1506 int r1 = (++it)->u.operand;
1507 printLocationAndOp(out, exec, location, it, "put_to_arguments");
1508 out.printf("%s, %d, %s", registerName(r0).data(), offset, registerName(r1).data());
oliver@apple.com58c86752013-07-25 04:02:40 +00001509 break;
1510 }
commit-queue@webkit.orge13567f2012-09-01 17:36:51 +00001511 default:
oliver@apple.com903b0c02013-01-24 01:40:37 +00001512 RELEASE_ASSERT_NOT_REACHED();
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001513 }
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001514
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001515 dumpRareCaseProfile(out, "rare case: ", rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
1516 dumpRareCaseProfile(out, "special fast case: ", specialFastCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001517
fpizlo@apple.com105ea9b2013-02-17 05:36:48 +00001518#if ENABLE(DFG_JIT)
oliver@apple.com02b179b2013-07-25 03:58:20 +00001519 Vector<DFG::FrequentExitSite> exitSites = exitProfile().exitSitesFor(location);
fpizlo@apple.com105ea9b2013-02-17 05:36:48 +00001520 if (!exitSites.isEmpty()) {
1521 out.print(" !! frequent exits: ");
1522 CommaPrinter comma;
1523 for (unsigned i = 0; i < exitSites.size(); ++i)
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001524 out.print(comma, exitSites[i].kind(), " ", exitSites[i].jitType());
fpizlo@apple.com105ea9b2013-02-17 05:36:48 +00001525 }
1526#else // ENABLE(DFG_JIT)
1527 UNUSED_PARAM(location);
1528#endif // ENABLE(DFG_JIT)
1529 out.print("\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001530}
1531
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001532void CodeBlock::dumpBytecode(
1533 PrintStream& out, unsigned bytecodeOffset,
1534 const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
fpizlo@apple.com1949f322012-11-22 00:46:57 +00001535{
1536 ExecState* exec = m_globalObject->globalExec();
1537 const Instruction* it = instructions().begin() + bytecodeOffset;
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001538 dumpBytecode(out, exec, instructions().begin(), it, stubInfos, callLinkInfos);
fpizlo@apple.com1949f322012-11-22 00:46:57 +00001539}
1540
weinig@apple.com67940d52008-12-09 00:14:58 +00001541#define FOR_EACH_MEMBER_VECTOR(macro) \
1542 macro(instructions) \
weinig@apple.com67940d52008-12-09 00:14:58 +00001543 macro(callLinkInfos) \
1544 macro(linkedCallerList) \
1545 macro(identifiers) \
1546 macro(functionExpressions) \
weinig@apple.com93675542009-01-09 18:47:37 +00001547 macro(constantRegisters)
weinig@apple.com4557e842008-12-09 01:06:14 +00001548
1549#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
weinig@apple.com67940d52008-12-09 00:14:58 +00001550 macro(regexps) \
1551 macro(functions) \
weinig@apple.com67940d52008-12-09 00:14:58 +00001552 macro(exceptionHandlers) \
oliver@apple.coma14cea52013-07-25 04:03:23 +00001553 macro(switchJumpTables) \
weinig@apple.comc7b19892008-12-18 00:00:01 +00001554 macro(stringSwitchJumpTables) \
barraclough@apple.com87dbd5e2010-11-19 02:35:25 +00001555 macro(evalCodeCache) \
weinig@apple.comaf0231a2009-01-08 01:46:14 +00001556 macro(expressionInfo) \
1557 macro(lineInfo) \
barraclough@apple.com87dbd5e2010-11-19 02:35:25 +00001558 macro(callReturnIndexVector)
weinig@apple.comaf0231a2009-01-08 01:46:14 +00001559
weinig@apple.comff037a02008-12-10 20:05:53 +00001560template<typename T>
1561static size_t sizeInBytes(const Vector<T>& vector)
1562{
1563 return vector.capacity() * sizeof(T);
1564}
1565
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001566namespace {
1567
1568class PutToScopeFireDetail : public FireDetail {
1569public:
1570 PutToScopeFireDetail(CodeBlock* codeBlock, const Identifier& ident)
1571 : m_codeBlock(codeBlock)
1572 , m_ident(ident)
1573 {
1574 }
1575
1576 virtual void dump(PrintStream& out) const override
1577 {
1578 out.print("Linking put_to_scope in ", FunctionExecutableDump(jsCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())), " for ", m_ident);
1579 }
1580
1581private:
1582 CodeBlock* m_codeBlock;
1583 const Identifier& m_ident;
1584};
1585
1586} // anonymous namespace
1587
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001588CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
1589 : m_globalObject(other.m_globalObject)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001590 , m_heap(other.m_heap)
1591 , m_numCalleeRegisters(other.m_numCalleeRegisters)
1592 , m_numVars(other.m_numVars)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001593 , m_isConstructor(other.m_isConstructor)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00001594 , m_shouldAlwaysBeInlined(true)
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001595 , m_didFailFTLCompilation(false)
msaboff@apple.com95894332014-01-29 19:18:54 +00001596 , m_hasBeenCompiledWithFTL(false)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001597 , m_unlinkedCode(*other.m_vm, other.m_ownerExecutable.get(), other.m_unlinkedCode.get())
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +00001598 , m_hasDebuggerStatement(false)
mark.lam@apple.com9c304882014-01-24 19:07:31 +00001599 , m_steppingMode(SteppingModeDisabled)
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001600 , m_numBreakpoints(0)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001601 , m_ownerExecutable(*other.m_vm, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001602 , m_vm(other.m_vm)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001603 , m_instructions(other.m_instructions)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001604 , m_thisRegister(other.m_thisRegister)
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +00001605 , m_scopeRegister(other.m_scopeRegister)
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +00001606 , m_lexicalEnvironmentRegister(other.m_lexicalEnvironmentRegister)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001607 , m_isStrictMode(other.m_isStrictMode)
oliver@apple.com75f804e2013-03-07 00:25:20 +00001608 , m_needsActivation(other.m_needsActivation)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001609 , m_source(other.m_source)
1610 , m_sourceOffset(other.m_sourceOffset)
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001611 , m_firstLineColumnOffset(other.m_firstLineColumnOffset)
oliver@apple.com75f804e2013-03-07 00:25:20 +00001612 , m_codeType(other.m_codeType)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001613 , m_constantRegisters(other.m_constantRegisters)
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00001614 , m_constantsSourceCodeRepresentation(other.m_constantsSourceCodeRepresentation)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001615 , m_functionDecls(other.m_functionDecls)
1616 , m_functionExprs(other.m_functionExprs)
fpizlo@apple.com39c94a42012-07-10 09:18:47 +00001617 , m_osrExitCounter(0)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001618 , m_optimizationDelayCounter(0)
1619 , m_reoptimizationRetryCounter(0)
ggaren@apple.com05483852015-09-17 00:28:34 +00001620 , m_creationTime(std::chrono::steady_clock::now())
oliver@apple.comacdde492013-07-25 04:02:57 +00001621 , m_hash(other.m_hash)
barraclough@apple.coma2d77342012-01-30 20:38:32 +00001622#if ENABLE(JIT)
oliver@apple.com07f66d42013-07-25 04:00:58 +00001623 , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
barraclough@apple.coma2d77342012-01-30 20:38:32 +00001624#endif
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001625{
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001626 m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
1627 m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
mark.lam@apple.com5d1b2b62015-03-13 18:02:40 +00001628
fpizlo@apple.com195d7b82013-09-03 16:39:29 +00001629 ASSERT(m_heap->isDeferred());
msaboff@apple.com2f145bc2015-01-23 19:52:25 +00001630 ASSERT(m_scopeRegister.isLocal());
1631
fpizlo@apple.comc4d54962012-01-10 22:08:47 +00001632 setNumParameters(other.numParameters());
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001633 optimizeAfterWarmUp();
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00001634 jitAfterWarmUp();
commit-queue@webkit.org3e0a1a02012-06-19 06:07:28 +00001635
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001636 if (other.m_rareData) {
1637 createRareDataIfNecessary();
1638
1639 m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001640 m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
oliver@apple.coma14cea52013-07-25 04:03:23 +00001641 m_rareData->m_switchJumpTables = other.m_rareData->m_switchJumpTables;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001642 m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001643 }
fpizlo@apple.com195d7b82013-09-03 16:39:29 +00001644
1645 m_heap->m_codeBlocks.add(this);
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001646 m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001647}
1648
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001649CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
1650 : m_globalObject(scope->globalObject()->vm(), ownerExecutable, scope->globalObject())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001651 , m_heap(&m_globalObject->vm().heap)
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001652 , m_numCalleeRegisters(unlinkedCodeBlock->m_numCalleeRegisters)
1653 , m_numVars(unlinkedCodeBlock->m_numVars)
1654 , m_isConstructor(unlinkedCodeBlock->isConstructor())
oliver@apple.comd2cdd312013-07-25 04:01:00 +00001655 , m_shouldAlwaysBeInlined(true)
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001656 , m_didFailFTLCompilation(false)
msaboff@apple.com95894332014-01-29 19:18:54 +00001657 , m_hasBeenCompiledWithFTL(false)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001658 , m_unlinkedCode(m_globalObject->vm(), ownerExecutable, unlinkedCodeBlock)
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +00001659 , m_hasDebuggerStatement(false)
mark.lam@apple.com9c304882014-01-24 19:07:31 +00001660 , m_steppingMode(SteppingModeDisabled)
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001661 , m_numBreakpoints(0)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001662 , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001663 , m_vm(unlinkedCodeBlock->vm())
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001664 , m_thisRegister(unlinkedCodeBlock->thisRegister())
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +00001665 , m_scopeRegister(unlinkedCodeBlock->scopeRegister())
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +00001666 , m_lexicalEnvironmentRegister(unlinkedCodeBlock->activationRegister())
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001667 , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
mark.lam@apple.com65a636f2014-02-01 01:24:39 +00001668 , m_needsActivation(unlinkedCodeBlock->hasActivationRegister() && unlinkedCodeBlock->codeType() == FunctionCode)
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00001669 , m_source(sourceProvider)
1670 , m_sourceOffset(sourceOffset)
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001671 , m_firstLineColumnOffset(firstLineColumnOffset)
oliver@apple.com75f804e2013-03-07 00:25:20 +00001672 , m_codeType(unlinkedCodeBlock->codeType())
fpizlo@apple.com39c94a42012-07-10 09:18:47 +00001673 , m_osrExitCounter(0)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00001674 , m_optimizationDelayCounter(0)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00001675 , m_reoptimizationRetryCounter(0)
ggaren@apple.com05483852015-09-17 00:28:34 +00001676 , m_creationTime(std::chrono::steady_clock::now())
oliver@apple.comacdde492013-07-25 04:02:57 +00001677#if ENABLE(JIT)
1678 , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
1679#endif
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00001680{
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001681 m_visitStronglyHasBeenCalled.store(false, std::memory_order_relaxed);
1682 m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
mark.lam@apple.com5d1b2b62015-03-13 18:02:40 +00001683
fpizlo@apple.com195d7b82013-09-03 16:39:29 +00001684 ASSERT(m_heap->isDeferred());
msaboff@apple.com2f145bc2015-01-23 19:52:25 +00001685 ASSERT(m_scopeRegister.isLocal());
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001686
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00001687 ASSERT(m_source);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001688 setNumParameters(unlinkedCodeBlock->numParameters());
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001689
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001690 if (vm()->typeProfiler() || vm()->controlFlowProfiler())
1691 vm()->functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001692
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00001693 setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
oliver@apple.com75f804e2013-03-07 00:25:20 +00001694 if (unlinkedCodeBlock->usesGlobalObject())
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001695 m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, ownerExecutable, m_globalObject.get());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00001696
1697 for (unsigned i = 0; i < LinkTimeConstantCount; i++) {
1698 LinkTimeConstant type = static_cast<LinkTimeConstant>(i);
1699 if (unsigned registerIndex = unlinkedCodeBlock->registerIndexForLinkTimeConstant(type))
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001700 m_constantRegisters[registerIndex].set(*m_vm, ownerExecutable, m_globalObject->jsCellForLinkTimeConstant(type));
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00001701 }
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00001702
1703 HashSet<int, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> clonedConstantSymbolTables;
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00001704 {
1705 HashSet<SymbolTable*> clonedSymbolTables;
1706 for (unsigned i = 0; i < m_constantRegisters.size(); i++) {
1707 if (m_constantRegisters[i].get().isEmpty())
1708 continue;
1709 if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(m_constantRegisters[i].get())) {
1710 RELEASE_ASSERT(clonedSymbolTables.add(symbolTable).isNewEntry);
1711 if (m_vm->typeProfiler()) {
1712 ConcurrentJITLocker locker(symbolTable->m_lock);
1713 symbolTable->prepareForTypeProfiling(locker);
1714 }
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001715 m_constantRegisters[i].set(*m_vm, ownerExecutable, symbolTable->cloneScopePart(*m_vm));
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00001716 clonedConstantSymbolTables.add(i + FirstConstantRegisterIndex);
1717 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001718 }
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00001719 }
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00001720
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00001721 // We already have the cloned symbol table for the module environment since we need to instantiate
1722 // the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
1723 if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(unlinkedCodeBlock)) {
1724 SymbolTable* clonedSymbolTable = jsCast<ModuleProgramExecutable*>(ownerExecutable)->moduleEnvironmentSymbolTable();
1725 if (m_vm->typeProfiler()) {
1726 ConcurrentJITLocker locker(clonedSymbolTable->m_lock);
1727 clonedSymbolTable->prepareForTypeProfiling(locker);
1728 }
1729 replaceConstant(unlinkedModuleProgramCodeBlock->moduleEnvironmentSymbolTableConstantRegisterOffset(), clonedSymbolTable);
1730 }
1731
akling@apple.comf1241692014-01-18 23:35:34 +00001732 m_functionDecls.resizeToFit(unlinkedCodeBlock->numberOfFunctionDecls());
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001733 for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
1734 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001735 if (vm()->typeProfiler() || vm()->controlFlowProfiler())
1736 vm()->functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
1737 m_functionDecls[i].set(*m_vm, ownerExecutable, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001738 }
1739
akling@apple.comf1241692014-01-18 23:35:34 +00001740 m_functionExprs.resizeToFit(unlinkedCodeBlock->numberOfFunctionExprs());
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001741 for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
1742 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001743 if (vm()->typeProfiler() || vm()->controlFlowProfiler())
1744 vm()->functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
1745 m_functionExprs[i].set(*m_vm, ownerExecutable, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001746 }
1747
1748 if (unlinkedCodeBlock->hasRareData()) {
1749 createRareDataIfNecessary();
1750 if (size_t count = unlinkedCodeBlock->constantBufferCount()) {
1751 m_rareData->m_constantBuffers.grow(count);
1752 for (size_t i = 0; i < count; i++) {
1753 const UnlinkedCodeBlock::ConstantBuffer& buffer = unlinkedCodeBlock->constantBuffer(i);
1754 m_rareData->m_constantBuffers[i] = buffer;
1755 }
1756 }
1757 if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) {
akling@apple.comb2ad1692014-01-18 23:09:48 +00001758 m_rareData->m_exceptionHandlers.resizeToFit(count);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001759 for (size_t i = 0; i < count; i++) {
mark.lam@apple.com4585ce92015-05-30 00:19:01 +00001760 const UnlinkedHandlerInfo& unlinkedHandler = unlinkedCodeBlock->exceptionHandler(i);
1761 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
mark.lam@apple.com3280e072015-06-01 17:57:18 +00001762#if ENABLE(JIT)
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00001763 handler.initialize(unlinkedHandler, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(op_catch))));
mark.lam@apple.com3280e072015-06-01 17:57:18 +00001764#else
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00001765 handler.initialize(unlinkedHandler);
mark.lam@apple.com3280e072015-06-01 17:57:18 +00001766#endif
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001767 }
1768 }
1769
1770 if (size_t count = unlinkedCodeBlock->numberOfStringSwitchJumpTables()) {
1771 m_rareData->m_stringSwitchJumpTables.grow(count);
1772 for (size_t i = 0; i < count; i++) {
1773 UnlinkedStringJumpTable::StringOffsetTable::iterator ptr = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.begin();
1774 UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end();
1775 for (; ptr != end; ++ptr) {
1776 OffsetLocation offset;
1777 offset.branchOffset = ptr->value;
1778 m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset);
1779 }
1780 }
1781 }
1782
oliver@apple.coma14cea52013-07-25 04:03:23 +00001783 if (size_t count = unlinkedCodeBlock->numberOfSwitchJumpTables()) {
1784 m_rareData->m_switchJumpTables.grow(count);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001785 for (size_t i = 0; i < count; i++) {
oliver@apple.coma14cea52013-07-25 04:03:23 +00001786 UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->switchJumpTable(i);
1787 SimpleJumpTable& destTable = m_rareData->m_switchJumpTables[i];
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001788 destTable.branchOffsets = sourceTable.branchOffsets;
1789 destTable.min = sourceTable.min;
1790 }
1791 }
1792 }
1793
1794 // Allocate metadata buffers for the bytecode
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001795 if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos())
akling@apple.com8b46ebc2013-08-30 01:21:23 +00001796 m_llintCallLinkInfos.resizeToFit(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001797 if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
1798 m_arrayProfiles.grow(size);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001799 if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles())
akling@apple.come25e7692013-11-12 07:56:39 +00001800 m_arrayAllocationProfiles.resizeToFit(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001801 if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
akling@apple.come25e7692013-11-12 07:56:39 +00001802 m_valueProfiles.resizeToFit(size);
ggaren@apple.comc862eac2013-01-29 05:48:01 +00001803 if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
akling@apple.come25e7692013-11-12 07:56:39 +00001804 m_objectAllocationProfiles.resizeToFit(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001805
msaboff@apple.com02085462015-09-10 17:47:16 +00001806#if ENABLE(JIT)
1807 setCalleeSaveRegisters(RegisterSet::llintBaselineCalleeSaveRegisters());
1808#endif
1809
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001810 // Copy and translate the UnlinkedInstructions
akling@apple.com8427aaf2014-01-27 05:45:30 +00001811 unsigned instructionCount = unlinkedCodeBlock->instructions().count();
1812 UnlinkedInstructionStream::Reader instructionReader(unlinkedCodeBlock->instructions());
1813
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00001814 // Bookkeep the strongly referenced module environments.
1815 HashSet<JSModuleEnvironment*> stronglyReferencedModuleEnvironments;
1816
oliver@apple.com4e3f9652013-04-08 04:14:50 +00001817 Vector<Instruction, 0, UnsafeVectorOverflow> instructions(instructionCount);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001818
akling@apple.com8427aaf2014-01-27 05:45:30 +00001819 for (unsigned i = 0; !instructionReader.atEnd(); ) {
1820 const UnlinkedInstruction* pc = instructionReader.next();
1821
1822 unsigned opLength = opcodeLength(pc[0].u.opcode);
1823
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001824 instructions[i] = vm()->interpreter->getOpcode(pc[0].u.opcode);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001825 for (size_t j = 1; j < opLength; ++j) {
1826 if (sizeof(int32_t) != sizeof(intptr_t))
1827 instructions[i + j].u.pointer = 0;
akling@apple.com8427aaf2014-01-27 05:45:30 +00001828 instructions[i + j].u.operand = pc[j].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001829 }
akling@apple.com8427aaf2014-01-27 05:45:30 +00001830 switch (pc[0].u.opcode) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001831 case op_has_indexed_property: {
1832 int arrayProfileIndex = pc[opLength - 1].u.operand;
1833 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
1834
1835 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
1836 break;
1837 }
msaboff@apple.com74aef1f2014-02-01 15:30:41 +00001838 case op_call_varargs:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001839 case op_tail_call_varargs:
oliver@apple.com177c2b92014-03-28 01:10:25 +00001840 case op_construct_varargs:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001841 case op_get_by_val: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001842 int arrayProfileIndex = pc[opLength - 2].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001843 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
1844
1845 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
joepeck@webkit.org899544a2014-01-28 04:04:45 +00001846 FALLTHROUGH;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001847 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001848 case op_get_direct_pname:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001849 case op_get_by_id:
1850 case op_get_from_arguments: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001851 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001852 ASSERT(profile->m_bytecodeOffset == -1);
1853 profile->m_bytecodeOffset = i;
1854 instructions[i + opLength - 1] = profile;
1855 break;
1856 }
1857 case op_put_by_val: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001858 int arrayProfileIndex = pc[opLength - 1].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001859 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
1860 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
1861 break;
1862 }
oliver@apple.come050d642013-10-19 00:09:28 +00001863 case op_put_by_val_direct: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001864 int arrayProfileIndex = pc[opLength - 1].u.operand;
oliver@apple.come050d642013-10-19 00:09:28 +00001865 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
1866 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
1867 break;
1868 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001869
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001870 case op_new_array:
1871 case op_new_array_buffer:
1872 case op_new_array_with_size: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001873 int arrayAllocationProfileIndex = pc[opLength - 1].u.operand;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00001874 instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
1875 break;
1876 }
ggaren@apple.comc862eac2013-01-29 05:48:01 +00001877 case op_new_object: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001878 int objectAllocationProfileIndex = pc[opLength - 1].u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +00001879 ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex];
akling@apple.com8427aaf2014-01-27 05:45:30 +00001880 int inferredInlineCapacity = pc[opLength - 2].u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +00001881
1882 instructions[i + opLength - 1] = objectAllocationProfile;
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001883 objectAllocationProfile->initialize(*vm(),
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001884 ownerExecutable, m_globalObject->objectPrototype(), inferredInlineCapacity);
ggaren@apple.comc862eac2013-01-29 05:48:01 +00001885 break;
1886 }
1887
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001888 case op_call:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001889 case op_tail_call:
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001890 case op_call_eval: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001891 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001892 ASSERT(profile->m_bytecodeOffset == -1);
1893 profile->m_bytecodeOffset = i;
1894 instructions[i + opLength - 1] = profile;
akling@apple.com8427aaf2014-01-27 05:45:30 +00001895 int arrayProfileIndex = pc[opLength - 2].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001896 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001897 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
akling@apple.com8427aaf2014-01-27 05:45:30 +00001898 instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
fpizlo@apple.com0ed51fc2012-11-09 01:27:25 +00001899 break;
1900 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001901 case op_construct: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00001902 instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
akling@apple.com8427aaf2014-01-27 05:45:30 +00001903 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001904 ASSERT(profile->m_bytecodeOffset == -1);
1905 profile->m_bytecodeOffset = i;
1906 instructions[i + opLength - 1] = profile;
fpizlo@apple.com0ed51fc2012-11-09 01:27:25 +00001907 break;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001908 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001909 case op_get_array_length:
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001910 CRASH();
1911
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00001912 case op_create_lexical_environment: {
1913 int symbolTableIndex = pc[3].u.operand;
1914 RELEASE_ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex));
1915 break;
1916 }
1917
oliver@apple.com58c86752013-07-25 04:02:40 +00001918 case op_resolve_scope: {
msaboff@apple.com44641f02014-11-03 17:56:29 +00001919 const Identifier& ident = identifier(pc[3].u.operand);
1920 ResolveType type = static_cast<ResolveType>(pc[4].u.operand);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +00001921 RELEASE_ASSERT(type != LocalClosureVar);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001922 int localScopeDepth = pc[5].u.operand;
oliver@apple.com58c86752013-07-25 04:02:40 +00001923
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001924 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, NotInitialization);
msaboff@apple.com44641f02014-11-03 17:56:29 +00001925 instructions[i + 4].u.operand = op.type;
1926 instructions[i + 5].u.operand = op.depth;
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00001927 if (op.lexicalEnvironment) {
1928 if (op.type == ModuleVar) {
1929 // Keep the linked module environment strongly referenced.
1930 if (stronglyReferencedModuleEnvironments.add(jsCast<JSModuleEnvironment*>(op.lexicalEnvironment)).isNewEntry)
1931 addConstant(op.lexicalEnvironment);
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001932 instructions[i + 6].u.jsCell.set(*vm(), ownerExecutable, op.lexicalEnvironment);
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00001933 } else
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001934 instructions[i + 6].u.symbolTable.set(*vm(), ownerExecutable, op.lexicalEnvironment->symbolTable());
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00001935 } else if (JSScope* constantScope = JSScope::constantScopeForCodeBlock(op.type, this))
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001936 instructions[i + 6].u.jsCell.set(*vm(), ownerExecutable, constantScope);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001937 else
1938 instructions[i + 6].u.pointer = nullptr;
oliver@apple.com58c86752013-07-25 04:02:40 +00001939 break;
1940 }
1941
1942 case op_get_from_scope: {
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001943 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.com58c86752013-07-25 04:02:40 +00001944 ASSERT(profile->m_bytecodeOffset == -1);
1945 profile->m_bytecodeOffset = i;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001946 instructions[i + opLength - 1] = profile;
oliver@apple.com58c86752013-07-25 04:02:40 +00001947
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001948 // get_from_scope dst, scope, id, GetPutInfo, Structure, Operand
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001949
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001950 int localScopeDepth = pc[5].u.operand;
1951 instructions[i + 5].u.pointer = nullptr;
1952
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001953 GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand);
1954 ASSERT(getPutInfo.initializationMode() == NotInitialization);
1955 if (getPutInfo.resolveType() == LocalClosureVar) {
1956 instructions[i + 4] = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand();
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001957 break;
1958 }
1959
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001960 const Identifier& ident = identifier(pc[3].u.operand);
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001961 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, getPutInfo.resolveType(), NotInitialization);
oliver@apple.com58c86752013-07-25 04:02:40 +00001962
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001963 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00001964 if (op.type == ModuleVar)
1965 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand();
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001966 if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
fpizlo@apple.com1a724092013-11-28 07:10:10 +00001967 instructions[i + 5].u.watchpointSet = op.watchpointSet;
1968 else if (op.structure)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00001969 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
oliver@apple.com58c86752013-07-25 04:02:40 +00001970 instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
1971 break;
1972 }
1973
1974 case op_put_to_scope: {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001975 // put_to_scope scope, id, value, GetPutInfo, Structure, Operand
1976 GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand);
1977 if (getPutInfo.resolveType() == LocalClosureVar) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001978 // Only do watching if the property we're putting to is not anonymous.
1979 if (static_cast<unsigned>(pc[2].u.operand) != UINT_MAX) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001980 int symbolTableIndex = pc[5].u.operand;
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00001981 RELEASE_ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001982 SymbolTable* symbolTable = jsCast<SymbolTable*>(getConstant(symbolTableIndex));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001983 const Identifier& ident = identifier(pc[2].u.operand);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001984 ConcurrentJITLocker locker(symbolTable->m_lock);
1985 auto iter = symbolTable->find(locker, ident.impl());
1986 RELEASE_ASSERT(iter != symbolTable->end(locker));
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00001987 iter->value.prepareToWatch();
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001988 instructions[i + 5].u.watchpointSet = iter->value.watchpointSet();
1989 } else
1990 instructions[i + 5].u.watchpointSet = nullptr;
1991 break;
1992 }
1993
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001994 const Identifier& ident = identifier(pc[2].u.operand);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001995 int localScopeDepth = pc[5].u.operand;
1996 instructions[i + 5].u.pointer = nullptr;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001997 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Put, getPutInfo.resolveType(), getPutInfo.initializationMode());
oliver@apple.com58c86752013-07-25 04:02:40 +00001998
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001999 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
2000 if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
fpizlo@apple.com40f7cbf2013-11-18 23:19:53 +00002001 instructions[i + 5].u.watchpointSet = op.watchpointSet;
fpizlo@apple.com88fedde2013-12-04 19:29:19 +00002002 else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) {
2003 if (op.watchpointSet)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002004 op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident));
fpizlo@apple.com88fedde2013-12-04 19:29:19 +00002005 } else if (op.structure)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002006 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
oliver@apple.com58c86752013-07-25 04:02:40 +00002007 instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002008
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002009 break;
2010 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002011
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002012 case op_profile_type: {
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002013 RELEASE_ASSERT(vm()->typeProfiler());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002014 // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002015 size_t instructionOffset = i + opLength - 1;
2016 unsigned divotStart, divotEnd;
mark.lam@apple.comca860af2014-10-06 22:17:09 +00002017 GlobalVariableID globalVariableID = 0;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002018 RefPtr<TypeSet> globalTypeSet;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002019 bool shouldAnalyze = m_unlinkedCode->typeProfilerExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002020 VirtualRegister profileRegister(pc[1].u.operand);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002021 ProfileTypeBytecodeFlag flag = static_cast<ProfileTypeBytecodeFlag>(pc[3].u.operand);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002022 SymbolTable* symbolTable = nullptr;
2023
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002024 switch (flag) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002025 case ProfileTypeBytecodeClosureVar: {
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002026 const Identifier& ident = identifier(pc[4].u.operand);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002027 int localScopeDepth = pc[2].u.operand;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002028 ResolveType type = static_cast<ResolveType>(pc[5].u.operand);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002029 // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
2030 // we're abstractly "read"ing from a JSScope.
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002031 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, NotInitialization);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002032
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002033 if (op.type == ClosureVar || op.type == ModuleVar)
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +00002034 symbolTable = op.lexicalEnvironment->symbolTable();
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002035 else if (op.type == GlobalVar)
2036 symbolTable = m_globalObject.get()->symbolTable();
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002037
2038 UniquedStringImpl* impl = (op.type == ModuleVar) ? op.importedName.get() : ident.impl();
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002039 if (symbolTable) {
2040 ConcurrentJITLocker locker(symbolTable->m_lock);
2041 // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002042 symbolTable->prepareForTypeProfiling(locker);
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002043 globalVariableID = symbolTable->uniqueIDForVariable(locker, impl, *vm());
2044 globalTypeSet = symbolTable->globalTypeSetForVariable(locker, impl, *vm());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002045 } else
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002046 globalVariableID = TypeProfilerNoGlobalIDExists;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002047
2048 break;
2049 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002050 case ProfileTypeBytecodeLocallyResolved: {
2051 int symbolTableIndex = pc[2].u.operand;
2052 RELEASE_ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex));
2053 SymbolTable* symbolTable = jsCast<SymbolTable*>(getConstant(symbolTableIndex));
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002054 const Identifier& ident = identifier(pc[4].u.operand);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002055 ConcurrentJITLocker locker(symbolTable->m_lock);
2056 // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002057 globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
2058 globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002059
2060 break;
2061 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002062 case ProfileTypeBytecodeDoesNotHaveGlobalID:
2063 case ProfileTypeBytecodeFunctionArgument: {
2064 globalVariableID = TypeProfilerNoGlobalIDExists;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002065 break;
2066 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002067 case ProfileTypeBytecodeFunctionReturnStatement: {
commit-queue@webkit.orgf6bd2fb2014-08-26 02:17:58 +00002068 RELEASE_ASSERT(ownerExecutable->isFunctionExecutable());
2069 globalTypeSet = jsCast<FunctionExecutable*>(ownerExecutable)->returnStatementTypeSet();
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002070 globalVariableID = TypeProfilerReturnStatement;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002071 if (!shouldAnalyze) {
commit-queue@webkit.org9653c662014-08-26 04:36:42 +00002072 // Because a return statement can be added implicitly to return undefined at the end of a function,
2073 // and these nodes don't emit expression ranges because they aren't in the actual source text of
2074 // the user's program, give the type profiler some range to identify these return statements.
commit-queue@webkit.orgf1d9ed82015-08-17 22:57:23 +00002075 // Currently, the text offset that is used as identification is "f" in the function keyword
commit-queue@webkit.org9653c662014-08-26 04:36:42 +00002076 // and is stored on TypeLocation's m_divotForFunctionOffsetIfReturnStatement member variable.
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002077 divotStart = divotEnd = ownerExecutable->typeProfilingStartOffset();
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002078 shouldAnalyze = true;
2079 }
2080 break;
2081 }
2082 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002083
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002084 std::pair<TypeLocation*, bool> locationPair = vm()->typeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID,
2085 ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, vm());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002086 TypeLocation* location = locationPair.first;
2087 bool isNewLocation = locationPair.second;
2088
commit-queue@webkit.org9653c662014-08-26 04:36:42 +00002089 if (flag == ProfileTypeBytecodeFunctionReturnStatement)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002090 location->m_divotForFunctionOffsetIfReturnStatement = ownerExecutable->typeProfilingStartOffset();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002091
2092 if (shouldAnalyze && isNewLocation)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002093 vm()->typeProfiler()->insertNewLocation(location);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002094
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002095 instructions[i + 2].u.location = location;
2096 break;
2097 }
2098
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +00002099 case op_debug: {
2100 if (pc[1].u.index == DidReachBreakpoint)
2101 m_hasDebuggerStatement = true;
2102 break;
2103 }
2104
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002105 default:
2106 break;
2107 }
2108 i += opLength;
2109 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002110
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002111 if (vm()->controlFlowProfiler())
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002112 insertBasicBlockBoundariesForControlFlowProfiler(instructions);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002113
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002114 m_instructions = WTF::RefCountedArray<Instruction>(instructions);
2115
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002116 // Set optimization thresholds only after m_instructions is initialized, since these
2117 // rely on the instruction count (and are in theory permitted to also inspect the
2118 // instruction stream to more accurate assess the cost of tier-up).
2119 optimizeAfterWarmUp();
2120 jitAfterWarmUp();
2121
oliver@apple.com9e1c8092013-07-25 04:03:16 +00002122 // If the concurrent thread will want the code block's hash, then compute it here
2123 // synchronously.
msaboff@apple.com95894332014-01-29 19:18:54 +00002124 if (Options::alwaysComputeHash())
oliver@apple.com9e1c8092013-07-25 04:03:16 +00002125 hash();
2126
msaboff@apple.com77adfde2012-11-29 03:16:11 +00002127 if (Options::dumpGeneratedBytecodes())
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00002128 dumpBytecode();
msaboff@apple.com95894332014-01-29 19:18:54 +00002129
fpizlo@apple.com195d7b82013-09-03 16:39:29 +00002130 m_heap->m_codeBlocks.add(this);
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002131 m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock) + m_instructions.size() * sizeof(Instruction));
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00002132}
2133
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002134#if ENABLE(WEBASSEMBLY)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002135CodeBlock::CodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)
2136 : m_globalObject(globalObject->vm(), ownerExecutable, globalObject)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002137 , m_heap(&m_globalObject->vm().heap)
2138 , m_numCalleeRegisters(0)
2139 , m_numVars(0)
2140 , m_isConstructor(false)
2141 , m_shouldAlwaysBeInlined(false)
2142 , m_didFailFTLCompilation(false)
2143 , m_hasBeenCompiledWithFTL(false)
2144 , m_hasDebuggerStatement(false)
2145 , m_steppingMode(SteppingModeDisabled)
2146 , m_numBreakpoints(0)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002147 , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002148 , m_vm(&vm)
2149 , m_isStrictMode(false)
2150 , m_needsActivation(false)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002151 , m_codeType(FunctionCode)
2152 , m_osrExitCounter(0)
2153 , m_optimizationDelayCounter(0)
2154 , m_reoptimizationRetryCounter(0)
ggaren@apple.com05483852015-09-17 00:28:34 +00002155 , m_creationTime(std::chrono::steady_clock::now())
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002156#if ENABLE(JIT)
2157 , m_capabilityLevelState(DFG::CannotCompile)
2158#endif
2159{
2160 ASSERT(m_heap->isDeferred());
2161
2162 m_heap->m_codeBlocks.add(this);
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002163 m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002164}
2165#endif
2166
weinig@apple.com3412bb42008-09-01 21:22:54 +00002167CodeBlock::~CodeBlock()
2168{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00002169 if (m_vm->m_perBytecodeProfiler)
2170 m_vm->m_perBytecodeProfiler->notifyDestruction(this);
fpizlo@apple.com4a81fa42012-12-05 01:26:13 +00002171
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +00002172#if ENABLE(VERBOSE_VALUE_PROFILE)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002173 dumpValueProfiles();
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +00002174#endif
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002175 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
2176 m_incomingLLIntCalls.begin()->remove();
2177#if ENABLE(JIT)
fpizlo@apple.coma4749642011-09-07 02:05:02 +00002178 // We may be destroyed before any CodeBlocks that refer to us are destroyed.
2179 // Consider that two CodeBlocks become unreachable at the same time. There
2180 // is no guarantee about the order in which the CodeBlocks are destroyed.
2181 // So, if we don't remove incoming calls, and get destroyed before the
2182 // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's
2183 // destructor will try to remove nodes from our (no longer valid) linked list.
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002184 while (m_incomingCalls.begin() != m_incomingCalls.end())
2185 m_incomingCalls.begin()->remove();
2186 while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
2187 m_incomingPolymorphicCalls.begin()->remove();
fpizlo@apple.com594887a2011-09-06 09:23:55 +00002188
2189 // Note that our outgoing calls will be removed from other CodeBlocks'
2190 // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
2191 // destructors.
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +00002192
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00002193 for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter)
2194 (*iter)->deref();
oliver@apple.com942e37d2010-07-07 01:35:56 +00002195#endif // ENABLE(JIT)
weinig@apple.com3412bb42008-09-01 21:22:54 +00002196}
2197
fpizlo@apple.comc4d54962012-01-10 22:08:47 +00002198void CodeBlock::setNumParameters(int newValue)
2199{
2200 m_numParameters = newValue;
2201
akling@apple.comd22d1e82013-07-18 16:50:38 +00002202 m_argumentValueProfiles.resizeToFit(newValue);
fpizlo@apple.comc4d54962012-01-10 22:08:47 +00002203}
2204
oliver@apple.com433d02f2011-04-21 23:08:15 +00002205void EvalCodeCache::visitAggregate(SlotVisitor& visitor)
oliver@apple.comba10bec2011-03-08 23:17:32 +00002206{
2207 EvalCacheMap::iterator end = m_cacheMap.end();
2208 for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
benjamin@webkit.orgee554052012-10-07 23:12:07 +00002209 visitor.append(&ptr->value);
oliver@apple.comba10bec2011-03-08 23:17:32 +00002210}
2211
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002212CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
2213{
2214#if ENABLE(FTL_JIT)
2215 if (jitType() != JITCode::DFGJIT)
2216 return 0;
2217 DFG::JITCode* jitCode = m_jitCode->dfg();
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002218 return jitCode->osrEntryBlock.get();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002219#else // ENABLE(FTL_JIT)
2220 return 0;
2221#endif // ENABLE(FTL_JIT)
2222}
2223
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002224void CodeBlock::visitStrongly(SlotVisitor& visitor)
ggaren@apple.com51be9a22015-09-09 22:00:58 +00002225{
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002226 bool setByMe = m_visitStronglyHasBeenCalled.compareExchangeStrong(false, true);
ggaren@apple.com156eb592015-09-09 22:06:49 +00002227 if (!setByMe)
2228 return;
2229
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002230 visitAggregate(visitor);
ggaren@apple.comec9fd6c2015-10-02 04:48:24 +00002231
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002232 stronglyVisitStrongReferences(visitor);
2233 stronglyVisitWeakReferences(visitor);
2234 propagateTransitions(visitor);
2235}
2236
2237void CodeBlock::visitAggregate(SlotVisitor& visitor)
2238{
2239 // I may be asked to scan myself more than once, and it may even happen concurrently.
2240 // To this end, use an atomic operation to check (and set) if I've been called already.
2241 // Only one thread may proceed past this point - whichever one wins the atomic set race.
2242 bool setByMe = m_visitAggregateHasBeenCalled.compareExchangeStrong(false, true);
2243 if (!setByMe)
ggaren@apple.com0e29f572015-10-02 21:16:20 +00002244 return;
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002245
2246 if (!!m_alternative)
2247 m_alternative->visitAggregate(visitor);
2248
2249 if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
2250 otherBlock->visitAggregate(visitor);
2251
2252 visitor.reportExtraMemoryVisited(ownerExecutable(), sizeof(CodeBlock));
2253 if (m_jitCode)
2254 visitor.reportExtraMemoryVisited(ownerExecutable(), m_jitCode->size());
2255 if (m_instructions.size()) {
2256 // Divide by refCount() because m_instructions points to something that is shared
2257 // by multiple CodeBlocks, and we only want to count it towards the heap size once.
2258 // Having each CodeBlock report only its proportional share of the size is one way
2259 // of accomplishing this.
2260 visitor.reportExtraMemoryVisited(ownerExecutable(), m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
fpizlo@apple.com7c084e02013-09-04 05:48:06 +00002261 }
2262
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002263 visitor.append(&m_unlinkedCode);
2264
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002265 // There are two things that may use unconditional finalizers: inline cache clearing
2266 // and jettisoning. The probability of us wanting to do at least one of those things
2267 // is probably quite close to 1. So we add one no matter what and when it runs, it
2268 // figures out whether it has any work to do.
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002269 visitor.addUnconditionalFinalizer(this);
2270
2271 m_allTransitionsHaveBeenMarked = false;
2272
2273 if (shouldVisitStrongly()) {
2274 visitStrongly(visitor);
2275 return;
2276 }
2277
ggaren@apple.com05483852015-09-17 00:28:34 +00002278 if (!JITCode::isOptimizingJIT(jitType()))
2279 return;
2280
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +00002281 // There are two things that we use weak reference harvesters for: DFG fixpoint for
2282 // jettisoning, and trying to find structures that would be live based on some
2283 // inline cache. So it makes sense to register them regardless.
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002284 visitor.addWeakReferenceHarvester(this);
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +00002285
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002286#if ENABLE(DFG_JIT)
2287 // We get here if we're live in the sense that our owner executable is live,
2288 // but we're not yet live for sure in another sense: we may yet decide that this
2289 // code block should be jettisoned based on its outgoing weak references being
2290 // stale. Set a flag to indicate that we're still assuming that we're dead, and
2291 // perform one round of determining if we're live. The GC may determine, based on
2292 // either us marking additional objects, or by other objects being marked for
2293 // other reasons, that this iteration should run again; it will notify us of this
2294 // decision by calling harvestWeakReferences().
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002295
ggaren@apple.com0e29f572015-10-02 21:16:20 +00002296 m_jitCode->dfgCommon()->livenessHasBeenProved = false;
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002297
2298 propagateTransitions(visitor);
oliver@apple.coma1524712013-07-25 04:01:56 +00002299 determineLiveness(visitor);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002300#endif // ENABLE(DFG_JIT)
2301}
2302
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002303bool CodeBlock::shouldVisitStrongly()
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002304{
ggaren@apple.com05483852015-09-17 00:28:34 +00002305 if (Options::forceCodeBlockLiveness())
2306 return true;
2307
2308 if (shouldJettisonDueToOldAge())
2309 return false;
2310
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002311 // Interpreter and Baseline JIT CodeBlocks don't need to be jettisoned when
2312 // their weak references go stale. So if a basline JIT CodeBlock gets
2313 // scanned, we can assume that this means that it's live.
2314 if (!JITCode::isOptimizingJIT(jitType()))
2315 return true;
2316
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002317 return false;
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002318}
2319
2320bool CodeBlock::isKnownToBeLiveDuringGC()
2321{
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002322 // This should return true for:
2323 // - Code blocks that behave like normal objects - i.e. if they are referenced then they
2324 // are live.
2325 // - Code blocks that were running on the stack.
2326 // - Code blocks that survived the last GC if the current GC is an Eden GC. This is
ggaren@apple.com51be9a22015-09-09 22:00:58 +00002327 // because livenessHasBeenProved would have survived as true.
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002328 // - Code blocks that don't have any dead weak references.
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002329
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002330 if (m_visitStronglyHasBeenCalled.load(std::memory_order_relaxed))
2331 return true;
2332
2333#if ENABLE(DFG_JIT)
2334 if (JITCode::isOptimizingJIT(jitType())) {
2335 if (m_jitCode->dfgCommon()->livenessHasBeenProved)
2336 return true;
2337 }
2338#endif
2339
2340 return false;
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002341}
2342
2343bool CodeBlock::shouldJettisonDueToWeakReference()
2344{
ggaren@apple.com05483852015-09-17 00:28:34 +00002345 if (!JITCode::isOptimizingJIT(jitType()))
2346 return false;
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002347 return !isKnownToBeLiveDuringGC();
2348}
2349
2350bool CodeBlock::shouldJettisonDueToOldAge()
2351{
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002352 if (m_visitStronglyHasBeenCalled.load(std::memory_order_relaxed))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002353 return false;
2354
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002355 if (timeSinceCreation() < JITCode::timeToLive(jitType()))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002356 return false;
2357
2358 return true;
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002359}
2360
fpizlo@apple.com4adaa962014-08-06 05:55:39 +00002361#if ENABLE(DFG_JIT)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002362static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition)
2363{
2364 if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get()))
2365 return false;
2366
2367 if (!Heap::isMarked(transition.m_from.get()))
2368 return false;
2369
2370 return true;
2371}
fpizlo@apple.com4adaa962014-08-06 05:55:39 +00002372#endif // ENABLE(DFG_JIT)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002373
oliver@apple.coma1524712013-07-25 04:01:56 +00002374void CodeBlock::propagateTransitions(SlotVisitor& visitor)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002375{
2376 UNUSED_PARAM(visitor);
oliver@apple.coma1524712013-07-25 04:01:56 +00002377
2378 if (m_allTransitionsHaveBeenMarked)
2379 return;
2380
2381 bool allAreMarkedSoFar = true;
2382
oliver@apple.coma1524712013-07-25 04:01:56 +00002383 Interpreter* interpreter = m_vm->interpreter;
2384 if (jitType() == JITCode::InterpreterThunk) {
2385 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
oliver@apple.comc0a31d72013-07-25 04:03:36 +00002386 for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) {
oliver@apple.coma1524712013-07-25 04:01:56 +00002387 Instruction* instruction = &instructions()[propertyAccessInstructions[i]];
2388 switch (interpreter->getOpcodeID(instruction[0].u.opcode)) {
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002389 case op_put_by_id: {
2390 StructureID oldStructureID = instruction[4].u.structureID;
2391 StructureID newStructureID = instruction[6].u.structureID;
2392 if (!oldStructureID || !newStructureID)
2393 break;
2394 Structure* oldStructure =
2395 m_vm->heap.structureIDTable().get(oldStructureID);
2396 Structure* newStructure =
2397 m_vm->heap.structureIDTable().get(newStructureID);
2398 if (Heap::isMarked(oldStructure))
2399 visitor.appendUnbarrieredReadOnlyPointer(newStructure);
oliver@apple.coma1524712013-07-25 04:01:56 +00002400 else
2401 allAreMarkedSoFar = false;
2402 break;
2403 }
2404 default:
2405 break;
2406 }
2407 }
2408 }
oliver@apple.coma1524712013-07-25 04:01:56 +00002409
2410#if ENABLE(JIT)
2411 if (JITCode::isJIT(jitType())) {
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00002412 for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
2413 StructureStubInfo& stubInfo = **iter;
fpizlo@apple.comb26b5242015-09-10 19:49:36 +00002414 if (stubInfo.cacheType != CacheType::Stub)
2415 continue;
2416 PolymorphicAccess* list = stubInfo.u.stub;
2417 JSCell* origin = stubInfo.codeOrigin.codeOriginOwner();
2418 if (origin && !Heap::isMarked(origin)) {
2419 allAreMarkedSoFar = false;
2420 continue;
2421 }
2422 for (unsigned j = list->size(); j--;) {
2423 const AccessCase& access = list->at(j);
2424 if (access.type() != AccessCase::Transition)
2425 continue;
2426 if (Heap::isMarked(access.structure()))
2427 visitor.appendUnbarrieredReadOnlyPointer(access.newStructure());
oliver@apple.coma1524712013-07-25 04:01:56 +00002428 else
2429 allAreMarkedSoFar = false;
oliver@apple.coma1524712013-07-25 04:01:56 +00002430 }
2431 }
2432 }
2433#endif // ENABLE(JIT)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002434
2435#if ENABLE(DFG_JIT)
oliver@apple.coma1524712013-07-25 04:01:56 +00002436 if (JITCode::isOptimizingJIT(jitType())) {
2437 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002438
oliver@apple.com02b179b2013-07-25 03:58:20 +00002439 for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002440 if (shouldMarkTransition(dfgCommon->transitions[i])) {
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002441 // If the following three things are live, then the target of the
2442 // transition is also live:
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002443 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002444 // - This code block. We know it's live already because otherwise
2445 // we wouldn't be scanning ourselves.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002446 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002447 // - The code origin of the transition. Transitions may arise from
2448 // code that was inlined. They are not relevant if the user's
2449 // object that is required for the inlinee to run is no longer
2450 // live.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002451 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002452 // - The source of the transition. The transition checks if some
2453 // heap location holds the source, and if so, stores the target.
2454 // Hence the source must be live for the transition to be live.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002455 //
2456 // We also short-circuit the liveness if the structure is harmless
2457 // to mark (i.e. its global object and prototype are both already
2458 // live).
2459
oliver@apple.com02b179b2013-07-25 03:58:20 +00002460 visitor.append(&dfgCommon->transitions[i].m_to);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002461 } else
2462 allAreMarkedSoFar = false;
2463 }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002464 }
oliver@apple.coma1524712013-07-25 04:01:56 +00002465#endif // ENABLE(DFG_JIT)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002466
oliver@apple.coma1524712013-07-25 04:01:56 +00002467 if (allAreMarkedSoFar)
2468 m_allTransitionsHaveBeenMarked = true;
2469}
2470
2471void CodeBlock::determineLiveness(SlotVisitor& visitor)
2472{
2473 UNUSED_PARAM(visitor);
2474
oliver@apple.coma1524712013-07-25 04:01:56 +00002475#if ENABLE(DFG_JIT)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002476 // Check if we have any remaining work to do.
oliver@apple.coma1524712013-07-25 04:01:56 +00002477 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
oliver@apple.com02b179b2013-07-25 03:58:20 +00002478 if (dfgCommon->livenessHasBeenProved)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002479 return;
2480
2481 // Now check all of our weak references. If all of them are live, then we
2482 // have proved liveness and so we scan our strong references. If at end of
2483 // GC we still have not proved liveness, then this code block is toast.
2484 bool allAreLiveSoFar = true;
oliver@apple.com02b179b2013-07-25 03:58:20 +00002485 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
2486 if (!Heap::isMarked(dfgCommon->weakReferences[i].get())) {
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002487 allAreLiveSoFar = false;
2488 break;
2489 }
2490 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002491 if (allAreLiveSoFar) {
2492 for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) {
2493 if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) {
2494 allAreLiveSoFar = false;
2495 break;
2496 }
2497 }
2498 }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002499
2500 // If some weak references are dead, then this fixpoint iteration was
2501 // unsuccessful.
2502 if (!allAreLiveSoFar)
2503 return;
2504
2505 // All weak references are live. Record this information so we don't
2506 // come back here again, and scan the strong references.
oliver@apple.com02b179b2013-07-25 03:58:20 +00002507 dfgCommon->livenessHasBeenProved = true;
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002508 stronglyVisitStrongReferences(visitor);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002509#endif // ENABLE(DFG_JIT)
2510}
2511
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002512void CodeBlock::visitWeakReferences(SlotVisitor& visitor)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002513{
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002514 propagateTransitions(visitor);
2515 determineLiveness(visitor);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002516}
2517
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002518void CodeBlock::finalizeLLIntInlineCaches()
fpizlo@apple.comcf716122012-07-13 06:41:18 +00002519{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002520#if ENABLE(WEBASSEMBLY)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002521 if (m_ownerExecutable->isWebAssemblyExecutable())
2522 return;
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002523#endif
oliver@apple.comc909f5f2012-10-18 23:37:40 +00002524
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002525 Interpreter* interpreter = m_vm->interpreter;
2526 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
2527 for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
2528 Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
2529 switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002530 case op_get_by_id: {
2531 StructureID oldStructureID = curInstruction[4].u.structureID;
2532 if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002533 break;
2534 if (Options::verboseOSR())
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002535 dataLogF("Clearing LLInt property access.\n");
2536 curInstruction[4].u.structureID = 0;
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002537 curInstruction[5].u.operand = 0;
2538 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002539 }
2540 case op_put_by_id: {
2541 StructureID oldStructureID = curInstruction[4].u.structureID;
2542 StructureID newStructureID = curInstruction[6].u.structureID;
2543 StructureChain* chain = curInstruction[7].u.structureChain.get();
2544 if ((!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) &&
2545 (!newStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(newStructureID))) &&
2546 (!chain || Heap::isMarked(chain)))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002547 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002548 if (Options::verboseOSR())
2549 dataLogF("Clearing LLInt put transition.\n");
2550 curInstruction[4].u.structureID = 0;
2551 curInstruction[5].u.operand = 0;
2552 curInstruction[6].u.structureID = 0;
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002553 curInstruction[7].u.structureChain.clear();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002554 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002555 }
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002556 case op_get_array_length:
2557 break;
2558 case op_to_this:
2559 if (!curInstruction[2].u.structure || Heap::isMarked(curInstruction[2].u.structure.get()))
2560 break;
2561 if (Options::verboseOSR())
2562 dataLogF("Clearing LLInt to_this with structure %p.\n", curInstruction[2].u.structure.get());
2563 curInstruction[2].u.structure.clear();
2564 curInstruction[3].u.toThisStatus = merge(
2565 curInstruction[3].u.toThisStatus, ToThisClearedByGC);
2566 break;
2567 case op_create_this: {
2568 auto& cacheWriteBarrier = curInstruction[4].u.jsCell;
2569 if (!cacheWriteBarrier || cacheWriteBarrier.unvalidatedGet() == JSCell::seenMultipleCalleeObjects())
2570 break;
2571 JSCell* cachedFunction = cacheWriteBarrier.get();
2572 if (Heap::isMarked(cachedFunction))
2573 break;
2574 if (Options::verboseOSR())
2575 dataLogF("Clearing LLInt create_this with cached callee %p.\n", cachedFunction);
2576 cacheWriteBarrier.clear();
2577 break;
2578 }
2579 case op_resolve_scope: {
2580 // Right now this isn't strictly necessary. Any symbol tables that this will refer to
2581 // are for outer functions, and we refer to those functions strongly, and they refer
2582 // to the symbol table strongly. But it's nice to be on the safe side.
2583 WriteBarrierBase<SymbolTable>& symbolTable = curInstruction[6].u.symbolTable;
2584 if (!symbolTable || Heap::isMarked(symbolTable.get()))
2585 break;
2586 if (Options::verboseOSR())
2587 dataLogF("Clearing dead symbolTable %p.\n", symbolTable.get());
2588 symbolTable.clear();
2589 break;
2590 }
2591 case op_get_from_scope:
2592 case op_put_to_scope: {
2593 GetPutInfo getPutInfo = GetPutInfo(curInstruction[4].u.operand);
2594 if (getPutInfo.resolveType() == GlobalVar || getPutInfo.resolveType() == GlobalVarWithVarInjectionChecks
2595 || getPutInfo.resolveType() == LocalClosureVar || getPutInfo.resolveType() == GlobalLexicalVar || getPutInfo.resolveType() == GlobalLexicalVarWithVarInjectionChecks)
2596 continue;
2597 WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;
2598 if (!structure || Heap::isMarked(structure.get()))
2599 break;
2600 if (Options::verboseOSR())
2601 dataLogF("Clearing scope access with structure %p.\n", structure.get());
2602 structure.clear();
2603 break;
2604 }
2605 default:
2606 OpcodeID opcodeID = interpreter->getOpcodeID(curInstruction[0].u.opcode);
2607 ASSERT_WITH_MESSAGE_UNUSED(opcodeID, false, "Unhandled opcode in CodeBlock::finalizeUnconditionally, %s(%d) at bc %u", opcodeNames[opcodeID], opcodeID, propertyAccessInstructions[i]);
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00002608 }
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00002609 }
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00002610
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002611 for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
2612 if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
2613 if (Options::verboseOSR())
2614 dataLog("Clearing LLInt call from ", *this, "\n");
2615 m_llintCallLinkInfos[i].unlink();
fpizlo@apple.com1e89af32012-11-19 02:55:14 +00002616 }
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002617 if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
2618 m_llintCallLinkInfos[i].lastSeenCallee.clear();
2619 }
2620}
2621
2622void CodeBlock::finalizeBaselineJITInlineCaches()
2623{
ggaren@apple.com95bf67e2015-09-11 17:35:59 +00002624#if ENABLE(JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002625 for (auto iter = callLinkInfosBegin(); !!iter; ++iter)
2626 (*iter)->visitWeak(*vm());
2627
2628 for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
2629 StructureStubInfo& stubInfo = **iter;
2630 stubInfo.visitWeakReferences(this);
2631 }
ggaren@apple.com95bf67e2015-09-11 17:35:59 +00002632#endif
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002633}
2634
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002635void CodeBlock::finalizeUnconditionally()
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002636{
2637#if ENABLE(DFG_JIT)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002638 if (shouldJettisonDueToWeakReference()) {
2639 jettison(Profiler::JettisonDueToWeakReference);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002640 return;
2641 }
2642#endif // ENABLE(DFG_JIT)
oliver@apple.comc909f5f2012-10-18 23:37:40 +00002643
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002644 if (shouldJettisonDueToOldAge()) {
2645 jettison(Profiler::JettisonDueToOldAge);
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002646 return;
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002647 }
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002648
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002649 if (JITCode::couldBeInterpreted(jitType()))
2650 finalizeLLIntInlineCaches();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002651
2652#if ENABLE(JIT)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002653 if (!!jitCode())
2654 finalizeBaselineJITInlineCaches();
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002655#endif
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002656}
2657
msaboff@apple.com95894332014-01-29 19:18:54 +00002658void CodeBlock::getStubInfoMap(const ConcurrentJITLocker&, StubInfoMap& result)
2659{
2660#if ENABLE(JIT)
2661 toHashMap(m_stubInfos, getStructureStubInfoCodeOrigin, result);
2662#else
2663 UNUSED_PARAM(result);
2664#endif
2665}
2666
2667void CodeBlock::getStubInfoMap(StubInfoMap& result)
2668{
2669 ConcurrentJITLocker locker(m_lock);
2670 getStubInfoMap(locker, result);
2671}
2672
fpizlo@apple.comba262b22014-03-23 04:34:38 +00002673void CodeBlock::getCallLinkInfoMap(const ConcurrentJITLocker&, CallLinkInfoMap& result)
2674{
2675#if ENABLE(JIT)
2676 toHashMap(m_callLinkInfos, getCallLinkInfoCodeOrigin, result);
2677#else
2678 UNUSED_PARAM(result);
2679#endif
2680}
2681
2682void CodeBlock::getCallLinkInfoMap(CallLinkInfoMap& result)
2683{
2684 ConcurrentJITLocker locker(m_lock);
2685 getCallLinkInfoMap(locker, result);
2686}
2687
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002688void CodeBlock::getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result)
2689{
2690#if ENABLE(JIT)
2691 for (auto* byValInfo : m_byValInfos)
2692 result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo);
2693#else
2694 UNUSED_PARAM(result);
2695#endif
2696}
2697
2698void CodeBlock::getByValInfoMap(ByValInfoMap& result)
2699{
2700 ConcurrentJITLocker locker(m_lock);
2701 getByValInfoMap(locker, result);
2702}
2703
fpizlo@apple.comcf716122012-07-13 06:41:18 +00002704#if ENABLE(JIT)
fpizlo@apple.comb26b5242015-09-10 19:49:36 +00002705StructureStubInfo* CodeBlock::addStubInfo(AccessType accessType)
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00002706{
2707 ConcurrentJITLocker locker(m_lock);
fpizlo@apple.comb26b5242015-09-10 19:49:36 +00002708 return m_stubInfos.add(accessType);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00002709}
2710
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00002711StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
2712{
2713 for (StructureStubInfo* stubInfo : m_stubInfos) {
2714 if (stubInfo->codeOrigin == codeOrigin)
2715 return stubInfo;
2716 }
2717 return nullptr;
2718}
2719
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002720ByValInfo* CodeBlock::addByValInfo()
2721{
2722 ConcurrentJITLocker locker(m_lock);
2723 return m_byValInfos.add();
2724}
2725
fpizlo@apple.comba262b22014-03-23 04:34:38 +00002726CallLinkInfo* CodeBlock::addCallLinkInfo()
2727{
2728 ConcurrentJITLocker locker(m_lock);
2729 return m_callLinkInfos.add();
2730}
2731
fpizlo@apple.comf7100b62014-03-24 17:29:51 +00002732CallLinkInfo* CodeBlock::getCallLinkInfoForBytecodeIndex(unsigned index)
2733{
2734 for (auto iter = m_callLinkInfos.begin(); !!iter; ++iter) {
msaboff@apple.com203a56e2015-06-24 22:37:30 +00002735 if ((*iter)->codeOrigin() == CodeOrigin(index))
fpizlo@apple.comf7100b62014-03-24 17:29:51 +00002736 return *iter;
2737 }
2738 return nullptr;
2739}
fpizlo@apple.comcf716122012-07-13 06:41:18 +00002740#endif
2741
ggaren@apple.com156eb592015-09-09 22:06:49 +00002742void CodeBlock::visitOSRExitTargets(SlotVisitor& visitor)
2743{
ggaren@apple.com05483852015-09-17 00:28:34 +00002744 // We strongly visit OSR exits targets because we don't want to deal with
2745 // the complexity of generating an exit target CodeBlock on demand and
2746 // guaranteeing that it matches the details of the CodeBlock we compiled
2747 // the OSR exit against.
ggaren@apple.com156eb592015-09-09 22:06:49 +00002748
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002749 alternative()->visitStrongly(visitor);
ggaren@apple.com156eb592015-09-09 22:06:49 +00002750
ggaren@apple.com6520f0c2015-09-09 22:26:16 +00002751#if ENABLE(DFG_JIT)
ggaren@apple.com156eb592015-09-09 22:06:49 +00002752 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
2753 if (dfgCommon->inlineCallFrames) {
ggaren@apple.com05483852015-09-17 00:28:34 +00002754 for (auto* inlineCallFrame : *dfgCommon->inlineCallFrames) {
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002755 ASSERT(inlineCallFrame->baselineCodeBlock());
2756 inlineCallFrame->baselineCodeBlock()->visitStrongly(visitor);
ggaren@apple.com05483852015-09-17 00:28:34 +00002757 }
ggaren@apple.com156eb592015-09-09 22:06:49 +00002758 }
ggaren@apple.com6520f0c2015-09-09 22:26:16 +00002759#endif
ggaren@apple.com156eb592015-09-09 22:06:49 +00002760}
2761
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002762void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
2763{
oliver@apple.com433d02f2011-04-21 23:08:15 +00002764 visitor.append(&m_globalObject);
2765 visitor.append(&m_ownerExecutable);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002766 visitor.append(&m_unlinkedCode);
2767 if (m_rareData)
oliver@apple.com433d02f2011-04-21 23:08:15 +00002768 m_rareData->m_evalCodeCache.visitAggregate(visitor);
2769 visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
barraclough@apple.com306bb122009-08-18 05:34:52 +00002770 for (size_t i = 0; i < m_functionExprs.size(); ++i)
oliver@apple.com433d02f2011-04-21 23:08:15 +00002771 visitor.append(&m_functionExprs[i]);
barraclough@apple.com306bb122009-08-18 05:34:52 +00002772 for (size_t i = 0; i < m_functionDecls.size(); ++i)
oliver@apple.com433d02f2011-04-21 23:08:15 +00002773 visitor.append(&m_functionDecls[i]);
ggaren@apple.comc862eac2013-01-29 05:48:01 +00002774 for (unsigned i = 0; i < m_objectAllocationProfiles.size(); ++i)
2775 m_objectAllocationProfiles[i].visitAggregate(visitor);
fpizlo@apple.comd13163d2011-09-03 05:14:04 +00002776
ggaren@apple.com156eb592015-09-09 22:06:49 +00002777#if ENABLE(DFG_JIT)
2778 if (JITCode::isOptimizingJIT(jitType()))
2779 visitOSRExitTargets(visitor);
2780#endif
2781
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002782 updateAllPredictions();
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00002783}
2784
2785void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor)
2786{
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00002787 UNUSED_PARAM(visitor);
2788
2789#if ENABLE(DFG_JIT)
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00002790 if (!JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00002791 return;
oliver@apple.com02b179b2013-07-25 03:58:20 +00002792
2793 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00002794
oliver@apple.com02b179b2013-07-25 03:58:20 +00002795 for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
2796 if (!!dfgCommon->transitions[i].m_codeOrigin)
2797 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.
2798 visitor.append(&dfgCommon->transitions[i].m_from);
2799 visitor.append(&dfgCommon->transitions[i].m_to);
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00002800 }
2801
oliver@apple.com02b179b2013-07-25 03:58:20 +00002802 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i)
2803 visitor.append(&dfgCommon->weakReferences[i]);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002804
2805 for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i)
2806 visitor.append(&dfgCommon->weakStructureReferences[i]);
ggaren@apple.com51be9a22015-09-09 22:00:58 +00002807
2808 dfgCommon->livenessHasBeenProved = true;
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00002809#endif
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00002810}
2811
fpizlo@apple.com501e6062013-11-01 22:10:52 +00002812CodeBlock* CodeBlock::baselineAlternative()
2813{
2814#if ENABLE(JIT)
2815 CodeBlock* result = this;
2816 while (result->alternative())
2817 result = result->alternative();
2818 RELEASE_ASSERT(result);
2819 RELEASE_ASSERT(JITCode::isBaselineCode(result->jitType()) || result->jitType() == JITCode::None);
2820 return result;
2821#else
2822 return this;
2823#endif
2824}
2825
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002826CodeBlock* CodeBlock::baselineVersion()
2827{
fpizlo@apple.com501e6062013-11-01 22:10:52 +00002828#if ENABLE(JIT)
fpizlo@apple.com669223d2013-09-01 02:02:47 +00002829 if (JITCode::isBaselineCode(jitType()))
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002830 return this;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002831 CodeBlock* result = replacement();
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00002832 if (!result) {
2833 // This can happen if we're creating the original CodeBlock for an executable.
2834 // Assume that we're the baseline CodeBlock.
fpizlo@apple.com501e6062013-11-01 22:10:52 +00002835 RELEASE_ASSERT(jitType() == JITCode::None);
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00002836 return this;
2837 }
fpizlo@apple.com501e6062013-11-01 22:10:52 +00002838 result = result->baselineAlternative();
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002839 return result;
2840#else
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00002841 return this;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002842#endif
2843}
2844
2845#if ENABLE(JIT)
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002846bool CodeBlock::hasOptimizedReplacement(JITCode::JITType typeToReplace)
2847{
2848 return JITCode::isHigherTier(replacement()->jitType(), typeToReplace);
2849}
2850
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002851bool CodeBlock::hasOptimizedReplacement()
2852{
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002853 return hasOptimizedReplacement(jitType());
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002854}
2855#endif
2856
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002857HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler requiredHandler)
mrowe@apple.comf88a4632008-09-07 05:44:58 +00002858{
oliver@apple.com49a2c142013-04-04 21:25:26 +00002859 RELEASE_ASSERT(bytecodeOffset < instructions().size());
sbarati@apple.com36c13402015-09-18 23:37:42 +00002860 return handlerForIndex(bytecodeOffset, requiredHandler);
2861}
weinig@apple.com06885cf2008-12-17 21:25:40 +00002862
sbarati@apple.com36c13402015-09-18 23:37:42 +00002863HandlerInfo* CodeBlock::handlerForIndex(unsigned index, RequiredHandler requiredHandler)
2864{
weinig@apple.com4557e842008-12-09 01:06:14 +00002865 if (!m_rareData)
2866 return 0;
mrowe@apple.comf88a4632008-09-07 05:44:58 +00002867
weinig@apple.com18064e72008-12-10 00:26:13 +00002868 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
2869 for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
mark.lam@apple.com4585ce92015-05-30 00:19:01 +00002870 HandlerInfo& handler = exceptionHandlers[i];
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002871 if ((requiredHandler == RequiredHandler::CatchHandler) && !handler.isCatchHandler())
2872 continue;
2873
weinig@apple.com18064e72008-12-10 00:26:13 +00002874 // Handlers are ordered innermost first, so the first handler we encounter
2875 // that contains the source address is the correct handler to use.
sbarati@apple.com36c13402015-09-18 23:37:42 +00002876 // This index used is either the BytecodeOffset or a CallSiteIndex.
2877 if (handler.start <= index && handler.end > index)
mark.lam@apple.com4585ce92015-05-30 00:19:01 +00002878 return &handler;
mrowe@apple.comf88a4632008-09-07 05:44:58 +00002879 }
2880
2881 return 0;
2882}
2883
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00002884unsigned CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00002885{
oliver@apple.com903b0c02013-01-24 01:40:37 +00002886 RELEASE_ASSERT(bytecodeOffset < instructions().size());
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002887 return ownerScriptExecutable()->firstLine() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00002888}
2889
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00002890unsigned CodeBlock::columnNumberForBytecodeOffset(unsigned bytecodeOffset)
oliver@apple.com90b88ae2008-07-19 01:44:24 +00002891{
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00002892 int divot;
2893 int startOffset;
2894 int endOffset;
2895 unsigned line;
2896 unsigned column;
2897 expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
2898 return column;
2899}
2900
2901void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
2902{
2903 m_unlinkedCode->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002904 divot += m_sourceOffset;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00002905 column += line ? 1 : firstLineColumnOffset();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002906 line += ownerScriptExecutable()->firstLine();
oliver@apple.com90b88ae2008-07-19 01:44:24 +00002907}
2908
mark.lam@apple.com945b1392014-01-23 07:39:58 +00002909bool CodeBlock::hasOpDebugForLineAndColumn(unsigned line, unsigned column)
2910{
2911 Interpreter* interpreter = vm()->interpreter;
2912 const Instruction* begin = instructions().begin();
2913 const Instruction* end = instructions().end();
2914 for (const Instruction* it = begin; it != end;) {
2915 OpcodeID opcodeID = interpreter->getOpcodeID(it->u.opcode);
2916 if (opcodeID == op_debug) {
2917 unsigned bytecodeOffset = it - begin;
2918 int unused;
2919 unsigned opDebugLine;
2920 unsigned opDebugColumn;
2921 expressionRangeForBytecodeOffset(bytecodeOffset, unused, unused, unused, opDebugLine, opDebugColumn);
2922 if (line == opDebugLine && (column == Breakpoint::unspecifiedColumn || column == opDebugColumn))
2923 return true;
2924 }
2925 it += opcodeLengths[opcodeID];
2926 }
2927 return false;
2928}
2929
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00002930void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
weinig@apple.com9d9d25d2008-12-05 20:27:58 +00002931{
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00002932 m_rareCaseProfiles.shrinkToFit();
2933 m_specialFastCaseProfiles.shrinkToFit();
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00002934
2935 if (shrinkMode == EarlyShrink) {
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00002936 m_constantRegisters.shrinkToFit();
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00002937 m_constantsSourceCodeRepresentation.shrinkToFit();
oliver@apple.com9b7647b2013-07-25 04:03:00 +00002938
2939 if (m_rareData) {
oliver@apple.coma14cea52013-07-25 04:03:23 +00002940 m_rareData->m_switchJumpTables.shrinkToFit();
oliver@apple.com9b7647b2013-07-25 04:03:00 +00002941 m_rareData->m_stringSwitchJumpTables.shrinkToFit();
2942 }
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00002943 } // else don't shrink these, because we would have already pointed pointers into these tables.
weinig@apple.com9d9d25d2008-12-05 20:27:58 +00002944}
2945
oliver@apple.com1db480d2011-06-28 01:32:01 +00002946#if ENABLE(JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002947void CodeBlock::linkIncomingCall(ExecState* callerFrame, CallLinkInfo* incoming)
2948{
2949 noticeIncomingCall(callerFrame);
2950 m_incomingCalls.push(incoming);
2951}
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002952
2953void CodeBlock::linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode* incoming)
2954{
2955 noticeIncomingCall(callerFrame);
2956 m_incomingPolymorphicCalls.push(incoming);
2957}
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00002958#endif // ENABLE(JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002959
fpizlo@apple.com594887a2011-09-06 09:23:55 +00002960void CodeBlock::unlinkIncomingCalls()
2961{
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00002962 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
2963 m_incomingLLIntCalls.begin()->unlink();
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00002964#if ENABLE(JIT)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002965 if (m_incomingCalls.isEmpty() && m_incomingPolymorphicCalls.isEmpty())
2966 return;
fpizlo@apple.com594887a2011-09-06 09:23:55 +00002967 while (m_incomingCalls.begin() != m_incomingCalls.end())
fpizlo@apple.com7a797262015-09-03 21:11:59 +00002968 m_incomingCalls.begin()->unlink(*vm());
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002969 while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
fpizlo@apple.com7a797262015-09-03 21:11:59 +00002970 m_incomingPolymorphicCalls.begin()->unlink(*vm());
commit-queue@webkit.orgea1f9022013-08-29 16:41:07 +00002971#endif // ENABLE(JIT)
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00002972}
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00002973
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002974void CodeBlock::linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo* incoming)
2975{
2976 noticeIncomingCall(callerFrame);
2977 m_incomingLLIntCalls.push(incoming);
2978}
commit-queue@webkit.orgf76b9d52012-08-20 23:48:00 +00002979
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002980PassRefPtr<CodeBlock> CodeBlock::newReplacement()
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00002981{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002982 return ownerScriptExecutable()->newReplacementCodeBlockFor(specializationKind());
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00002983}
2984
fpizlo@apple.comaf478bb2011-09-06 23:36:51 +00002985#if ENABLE(JIT)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002986CodeBlock* ProgramCodeBlock::replacement()
fpizlo@apple.com594887a2011-09-06 09:23:55 +00002987{
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002988 return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock();
2989}
fpizlo@apple.com594887a2011-09-06 09:23:55 +00002990
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002991CodeBlock* ModuleProgramCodeBlock::replacement()
2992{
2993 return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock();
2994}
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002995
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00002996CodeBlock* EvalCodeBlock::replacement()
2997{
2998 return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock();
2999}
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003000
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00003001CodeBlock* FunctionCodeBlock::replacement()
3002{
3003 return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
3004}
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003005
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00003006DFG::CapabilityLevel ProgramCodeBlock::capabilityLevelInternal()
3007{
3008 return DFG::programCapabilityLevel(this);
3009}
3010
3011DFG::CapabilityLevel ModuleProgramCodeBlock::capabilityLevelInternal()
3012{
3013 return DFG::programCapabilityLevel(this);
3014}
3015
3016DFG::CapabilityLevel EvalCodeBlock::capabilityLevelInternal()
3017{
3018 return DFG::evalCapabilityLevel(this);
3019}
3020
3021DFG::CapabilityLevel FunctionCodeBlock::capabilityLevelInternal()
3022{
3023 if (m_isConstructor)
3024 return DFG::functionForConstructCapabilityLevel(this);
3025 return DFG::functionForCallCapabilityLevel(this);
3026}
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003027
3028#if ENABLE(WEBASSEMBLY)
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00003029CodeBlock* WebAssemblyCodeBlock::replacement()
3030{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003031 return nullptr;
3032}
3033
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00003034DFG::CapabilityLevel WebAssemblyCodeBlock::capabilityLevelInternal()
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003035{
3036 return DFG::CannotCompile;
3037}
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00003038#endif
3039#endif
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003040
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003041void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003042{
ggaren@apple.com05483852015-09-17 00:28:34 +00003043#if !ENABLE(DFG_JIT)
3044 UNUSED_PARAM(mode);
3045 UNUSED_PARAM(detail);
3046#endif
3047
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00003048 RELEASE_ASSERT(reason != Profiler::NotJettisoned);
3049
fpizlo@apple.com580c6f02013-10-30 20:22:40 +00003050#if ENABLE(DFG_JIT)
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003051 if (DFG::shouldShowDisassembly()) {
3052 dataLog("Jettisoning ", *this);
3053 if (mode == CountReoptimization)
3054 dataLog(" and counting reoptimization");
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003055 dataLog(" due to ", reason);
3056 if (detail)
3057 dataLog(", ", *detail);
3058 dataLog(".\n");
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003059 }
3060
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003061 if (reason == Profiler::JettisonDueToWeakReference) {
3062 if (DFG::shouldShowDisassembly()) {
3063 dataLog(*this, " will be jettisoned because of the following dead references:\n");
3064 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
3065 for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
3066 DFG::WeakReferenceTransition& transition = dfgCommon->transitions[i];
3067 JSCell* origin = transition.m_codeOrigin.get();
3068 JSCell* from = transition.m_from.get();
3069 JSCell* to = transition.m_to.get();
3070 if ((!origin || Heap::isMarked(origin)) && Heap::isMarked(from))
3071 continue;
3072 dataLog(" Transition under ", RawPointer(origin), ", ", RawPointer(from), " -> ", RawPointer(to), ".\n");
3073 }
3074 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
3075 JSCell* weak = dfgCommon->weakReferences[i].get();
3076 if (Heap::isMarked(weak))
3077 continue;
3078 dataLog(" Weak reference ", RawPointer(weak), ".\n");
3079 }
3080 }
3081 }
ggaren@apple.com05483852015-09-17 00:28:34 +00003082#endif // ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003083
fpizlo@apple.com4917df22013-10-31 03:52:23 +00003084 DeferGCForAWhile deferGC(*m_heap);
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00003085
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003086 // We want to accomplish two things here:
3087 // 1) Make sure that if this CodeBlock is on the stack right now, then if we return to it
3088 // we should OSR exit at the top of the next bytecode instruction after the return.
3089 // 2) Make sure that if we call the owner executable, then we shouldn't call this CodeBlock.
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003090
ggaren@apple.com05483852015-09-17 00:28:34 +00003091#if ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003092 if (reason != Profiler::JettisonDueToOldAge) {
ggaren@apple.com05483852015-09-17 00:28:34 +00003093 if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get())
3094 compilation->setJettisonReason(reason, detail);
3095
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003096 // This accomplishes (1), and does its own book-keeping about whether it has already happened.
3097 if (!jitCode()->dfgCommon()->invalidate()) {
3098 // We've already been invalidated.
3099 RELEASE_ASSERT(this != replacement());
3100 return;
3101 }
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003102 }
3103
3104 if (DFG::shouldShowDisassembly())
3105 dataLog(" Did invalidate ", *this, "\n");
3106
3107 // Count the reoptimization if that's what the user wanted.
3108 if (mode == CountReoptimization) {
fpizlo@apple.com78e1b2b2013-11-03 00:32:23 +00003109 // FIXME: Maybe this should call alternative().
3110 // https://bugs.webkit.org/show_bug.cgi?id=123677
3111 baselineAlternative()->countReoptimization();
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003112 if (DFG::shouldShowDisassembly())
3113 dataLog(" Did count reoptimization for ", *this, "\n");
3114 }
3115
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003116 if (this != replacement()) {
3117 // This means that we were never the entrypoint. This can happen for OSR entry code
3118 // blocks.
3119 return;
3120 }
ggaren@apple.com05483852015-09-17 00:28:34 +00003121
3122 if (alternative())
3123 alternative()->optimizeAfterWarmUp();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003124
3125 if (reason != Profiler::JettisonDueToOldAge)
3126 tallyFrequentExitSites();
ggaren@apple.com05483852015-09-17 00:28:34 +00003127#endif // ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003128
ggaren@apple.com05483852015-09-17 00:28:34 +00003129 // This accomplishes (2).
3130 ownerScriptExecutable()->installCode(
3131 m_globalObject->vm(), alternative(), codeType(), specializationKind());
3132
3133#if ENABLE(DFG_JIT)
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003134 if (DFG::shouldShowDisassembly())
3135 dataLog(" Did install baseline version of ", *this, "\n");
fpizlo@apple.com580c6f02013-10-30 20:22:40 +00003136#endif // ENABLE(DFG_JIT)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003137}
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003138
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00003139JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin)
3140{
3141 if (!codeOrigin.inlineCallFrame)
3142 return globalObject();
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00003143 return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->eitherCodeBlock()->globalObject();
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00003144}
3145
msaboff@apple.com4d563e42014-08-16 01:45:40 +00003146class RecursionCheckFunctor {
3147public:
3148 RecursionCheckFunctor(CallFrame* startCallFrame, CodeBlock* codeBlock, unsigned depthToCheck)
3149 : m_startCallFrame(startCallFrame)
3150 , m_codeBlock(codeBlock)
3151 , m_depthToCheck(depthToCheck)
3152 , m_foundStartCallFrame(false)
3153 , m_didRecurse(false)
3154 { }
3155
3156 StackVisitor::Status operator()(StackVisitor& visitor)
3157 {
3158 CallFrame* currentCallFrame = visitor->callFrame();
3159
3160 if (currentCallFrame == m_startCallFrame)
3161 m_foundStartCallFrame = true;
3162
3163 if (m_foundStartCallFrame) {
3164 if (visitor->callFrame()->codeBlock() == m_codeBlock) {
3165 m_didRecurse = true;
3166 return StackVisitor::Done;
3167 }
3168
3169 if (!m_depthToCheck--)
3170 return StackVisitor::Done;
3171 }
3172
3173 return StackVisitor::Continue;
3174 }
3175
3176 bool didRecurse() const { return m_didRecurse; }
3177
3178private:
3179 CallFrame* m_startCallFrame;
3180 CodeBlock* m_codeBlock;
3181 unsigned m_depthToCheck;
3182 bool m_foundStartCallFrame;
3183 bool m_didRecurse;
3184};
3185
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003186void CodeBlock::noticeIncomingCall(ExecState* callerFrame)
3187{
3188 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
3189
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003190 if (Options::verboseCallLink())
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003191 dataLog("Noticing call link from ", pointerDump(callerCodeBlock), " to ", *this, "\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003192
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003193#if ENABLE(DFG_JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003194 if (!m_shouldAlwaysBeInlined)
3195 return;
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003196
3197 if (!callerCodeBlock) {
3198 m_shouldAlwaysBeInlined = false;
3199 if (Options::verboseCallLink())
3200 dataLog(" Clearing SABI because caller is native.\n");
3201 return;
3202 }
oliver@apple.com58c86752013-07-25 04:02:40 +00003203
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003204 if (!hasBaselineJITProfiling())
3205 return;
oliver@apple.com58c86752013-07-25 04:02:40 +00003206
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003207 if (!DFG::mightInlineFunction(this))
3208 return;
oliver@apple.com58c86752013-07-25 04:02:40 +00003209
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003210 if (!canInline(m_capabilityLevelState))
3211 return;
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003212
3213 if (!DFG::isSmallEnoughToInlineCodeInto(callerCodeBlock)) {
3214 m_shouldAlwaysBeInlined = false;
3215 if (Options::verboseCallLink())
3216 dataLog(" Clearing SABI because caller is too large.\n");
3217 return;
3218 }
oliver@apple.com58c86752013-07-25 04:02:40 +00003219
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003220 if (callerCodeBlock->jitType() == JITCode::InterpreterThunk) {
3221 // If the caller is still in the interpreter, then we can't expect inlining to
3222 // happen anytime soon. Assume it's profitable to optimize it separately. This
3223 // ensures that a function is SABI only if it is called no more frequently than
3224 // any of its callers.
3225 m_shouldAlwaysBeInlined = false;
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003226 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003227 dataLog(" Clearing SABI because caller is in LLInt.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003228 return;
3229 }
3230
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003231 if (JITCode::isOptimizingJIT(callerCodeBlock->jitType())) {
3232 m_shouldAlwaysBeInlined = false;
3233 if (Options::verboseCallLink())
3234 dataLog(" Clearing SABI bcause caller was already optimized.\n");
3235 return;
3236 }
3237
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003238 if (callerCodeBlock->codeType() != FunctionCode) {
3239 // If the caller is either eval or global code, assume that that won't be
3240 // optimized anytime soon. For eval code this is particularly true since we
3241 // delay eval optimization by a *lot*.
3242 m_shouldAlwaysBeInlined = false;
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003243 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003244 dataLog(" Clearing SABI because caller is not a function.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003245 return;
3246 }
msaboff@apple.com4d563e42014-08-16 01:45:40 +00003247
3248 // Recursive calls won't be inlined.
3249 RecursionCheckFunctor functor(callerFrame, this, Options::maximumInliningDepth());
3250 vm()->topCallFrame->iterate(functor);
3251
3252 if (functor.didRecurse()) {
3253 if (Options::verboseCallLink())
3254 dataLog(" Clearing SABI because recursion was detected.\n");
3255 m_shouldAlwaysBeInlined = false;
3256 return;
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003257 }
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003258
3259 if (callerCodeBlock->m_capabilityLevelState == DFG::CapabilityLevelNotSet) {
3260 dataLog("In call from ", *callerCodeBlock, " ", callerFrame->codeOrigin(), " to ", *this, ": caller's DFG capability level is not set.\n");
3261 CRASH();
3262 }
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003263
3264 if (canCompile(callerCodeBlock->m_capabilityLevelState))
3265 return;
3266
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003267 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003268 dataLog(" Clearing SABI because the caller is not a DFG candidate.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003269
3270 m_shouldAlwaysBeInlined = false;
oliver@apple.com58c86752013-07-25 04:02:40 +00003271#endif
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003272}
3273
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003274unsigned CodeBlock::reoptimizationRetryCounter() const
3275{
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00003276#if ENABLE(JIT)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003277 ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax());
3278 return m_reoptimizationRetryCounter;
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00003279#else
3280 return 0;
3281#endif // ENABLE(JIT)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003282}
3283
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00003284#if ENABLE(JIT)
msaboff@apple.com02085462015-09-10 17:47:16 +00003285void CodeBlock::setCalleeSaveRegisters(RegisterSet calleeSaveRegisters)
3286{
3287 m_calleeSaveRegisters = std::make_unique<RegisterAtOffsetList>(calleeSaveRegisters);
3288}
3289
3290void CodeBlock::setCalleeSaveRegisters(std::unique_ptr<RegisterAtOffsetList> registerAtOffsetList)
3291{
3292 m_calleeSaveRegisters = WTF::move(registerAtOffsetList);
3293}
3294
3295static size_t roundCalleeSaveSpaceAsVirtualRegisters(size_t calleeSaveRegisters)
3296{
3297 static const unsigned cpuRegisterSize = sizeof(void*);
3298 return (WTF::roundUpToMultipleOf(sizeof(Register), calleeSaveRegisters * cpuRegisterSize) / sizeof(Register));
3299
3300}
3301
3302size_t CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()
3303{
3304 return roundCalleeSaveSpaceAsVirtualRegisters(numberOfLLIntBaselineCalleeSaveRegisters());
3305}
3306
3307size_t CodeBlock::calleeSaveSpaceAsVirtualRegisters()
3308{
3309 return roundCalleeSaveSpaceAsVirtualRegisters(m_calleeSaveRegisters->size());
3310}
3311
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003312void CodeBlock::countReoptimization()
3313{
3314 m_reoptimizationRetryCounter++;
3315 if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax())
3316 m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax();
3317}
3318
oliver@apple.com37172f82013-07-25 04:01:17 +00003319unsigned CodeBlock::numberOfDFGCompiles()
3320{
3321 ASSERT(JITCode::isBaselineCode(jitType()));
msaboff@apple.com95894332014-01-29 19:18:54 +00003322 if (Options::testTheFTL()) {
3323 if (m_didFailFTLCompilation)
3324 return 1000000;
3325 return (m_hasBeenCompiledWithFTL ? 1 : 0) + m_reoptimizationRetryCounter;
3326 }
oliver@apple.com37172f82013-07-25 04:01:17 +00003327 return (JITCode::isOptimizingJIT(replacement()->jitType()) ? 1 : 0) + m_reoptimizationRetryCounter;
3328}
3329
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00003330int32_t CodeBlock::codeTypeThresholdMultiplier() const
3331{
3332 if (codeType() == EvalCode)
3333 return Options::evalThresholdMultiplier();
3334
3335 return 1;
3336}
3337
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003338double CodeBlock::optimizationThresholdScalingFactor()
3339{
ggaren@apple.comf0193982013-04-03 01:41:16 +00003340 // This expression arises from doing a least-squares fit of
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003341 //
3342 // F[x_] =: a * Sqrt[x + b] + Abs[c * x] + d
3343 //
3344 // against the data points:
3345 //
3346 // x F[x_]
3347 // 10 0.9 (smallest reasonable code block)
3348 // 200 1.0 (typical small-ish code block)
3349 // 320 1.2 (something I saw in 3d-cube that I wanted to optimize)
3350 // 1268 5.0 (something I saw in 3d-cube that I didn't want to optimize)
3351 // 4000 5.5 (random large size, used to cause the function to converge to a shallow curve of some sort)
3352 // 10000 6.0 (similar to above)
3353 //
ggaren@apple.comf0193982013-04-03 01:41:16 +00003354 // I achieve the minimization using the following Mathematica code:
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003355 //
3356 // MyFunctionTemplate[x_, a_, b_, c_, d_] := a*Sqrt[x + b] + Abs[c*x] + d
3357 //
3358 // samples = {{10, 0.9}, {200, 1}, {320, 1.2}, {1268, 5}, {4000, 5.5}, {10000, 6}}
3359 //
3360 // solution =
3361 // Minimize[Plus @@ ((MyFunctionTemplate[#[[1]], a, b, c, d] - #[[2]])^2 & /@ samples),
3362 // {a, b, c, d}][[2]]
3363 //
3364 // And the code below (to initialize a, b, c, d) is generated by:
3365 //
3366 // Print["const double " <> ToString[#[[1]]] <> " = " <>
3367 // If[#[[2]] < 0.00001, "0.0", ToString[#[[2]]]] <> ";"] & /@ solution
3368 //
3369 // We've long known the following to be true:
3370 // - Small code blocks are cheap to optimize and so we should do it sooner rather
3371 // than later.
3372 // - Large code blocks are expensive to optimize and so we should postpone doing so,
3373 // and sometimes have a large enough threshold that we never optimize them.
3374 // - The difference in cost is not totally linear because (a) just invoking the
3375 // DFG incurs some base cost and (b) for large code blocks there is enough slop
3376 // in the correlation between instruction count and the actual compilation cost
3377 // that for those large blocks, the instruction count should not have a strong
3378 // influence on our threshold.
3379 //
3380 // I knew the goals but I didn't know how to achieve them; so I picked an interesting
3381 // example where the heuristics were right (code block in 3d-cube with instruction
3382 // count 320, which got compiled early as it should have been) and one where they were
3383 // totally wrong (code block in 3d-cube with instruction count 1268, which was expensive
3384 // to compile and didn't run often enough to warrant compilation in my opinion), and
3385 // then threw in additional data points that represented my own guess of what our
3386 // heuristics should do for some round-numbered examples.
3387 //
3388 // The expression to which I decided to fit the data arose because I started with an
3389 // affine function, and then did two things: put the linear part in an Abs to ensure
3390 // that the fit didn't end up choosing a negative value of c (which would result in
3391 // the function turning over and going negative for large x) and I threw in a Sqrt
3392 // term because Sqrt represents my intution that the function should be more sensitive
3393 // to small changes in small values of x, but less sensitive when x gets large.
ggaren@apple.comf0193982013-04-03 01:41:16 +00003394
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003395 // Note that the current fit essentially eliminates the linear portion of the
3396 // expression (c == 0.0).
3397 const double a = 0.061504;
3398 const double b = 1.02406;
3399 const double c = 0.0;
3400 const double d = 0.825914;
3401
ggaren@apple.comf0193982013-04-03 01:41:16 +00003402 double instructionCount = this->instructionCount();
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003403
ggaren@apple.comf0193982013-04-03 01:41:16 +00003404 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.
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003405
ggaren@apple.comf0193982013-04-03 01:41:16 +00003406 double result = d + a * sqrt(instructionCount + b) + c * instructionCount;
fpizlo@apple.com3ce93232014-03-03 05:42:29 +00003407
3408 result *= codeTypeThresholdMultiplier();
3409
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003410 if (Options::verboseOSR()) {
3411 dataLog(
3412 *this, ": instruction count is ", instructionCount,
3413 ", scaling execution counter by ", result, " * ", codeTypeThresholdMultiplier(),
3414 "\n");
3415 }
fpizlo@apple.com3ce93232014-03-03 05:42:29 +00003416 return result;
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003417}
3418
3419static int32_t clipThreshold(double threshold)
3420{
3421 if (threshold < 1.0)
3422 return 1;
3423
3424 if (threshold > static_cast<double>(std::numeric_limits<int32_t>::max()))
3425 return std::numeric_limits<int32_t>::max();
3426
3427 return static_cast<int32_t>(threshold);
3428}
3429
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003430int32_t CodeBlock::adjustedCounterValue(int32_t desiredThreshold)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003431{
3432 return clipThreshold(
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003433 static_cast<double>(desiredThreshold) *
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003434 optimizationThresholdScalingFactor() *
3435 (1 << reoptimizationRetryCounter()));
3436}
3437
3438bool CodeBlock::checkIfOptimizationThresholdReached()
3439{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003440#if ENABLE(DFG_JIT)
msaboff@apple.com95894332014-01-29 19:18:54 +00003441 if (DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull()) {
fpizlo@apple.com6931c472013-08-29 23:45:26 +00003442 if (worklist->compilationState(DFG::CompilationKey(this, DFG::DFGMode))
3443 == DFG::Worklist::Compiled) {
3444 optimizeNextInvocation();
3445 return true;
3446 }
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003447 }
3448#endif
3449
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003450 return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
3451}
3452
3453void CodeBlock::optimizeNextInvocation()
3454{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003455 if (Options::verboseOSR())
3456 dataLog(*this, ": Optimizing next invocation.\n");
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003457 m_jitExecuteCounter.setNewThreshold(0, this);
3458}
3459
3460void CodeBlock::dontOptimizeAnytimeSoon()
3461{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003462 if (Options::verboseOSR())
3463 dataLog(*this, ": Not optimizing anytime soon.\n");
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003464 m_jitExecuteCounter.deferIndefinitely();
3465}
3466
3467void CodeBlock::optimizeAfterWarmUp()
3468{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003469 if (Options::verboseOSR())
3470 dataLog(*this, ": Optimizing after warm-up.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00003471#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003472 m_jitExecuteCounter.setNewThreshold(
3473 adjustedCounterValue(Options::thresholdForOptimizeAfterWarmUp()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00003474#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003475}
3476
3477void CodeBlock::optimizeAfterLongWarmUp()
3478{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003479 if (Options::verboseOSR())
3480 dataLog(*this, ": Optimizing after long warm-up.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00003481#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003482 m_jitExecuteCounter.setNewThreshold(
3483 adjustedCounterValue(Options::thresholdForOptimizeAfterLongWarmUp()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00003484#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003485}
3486
3487void CodeBlock::optimizeSoon()
3488{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003489 if (Options::verboseOSR())
3490 dataLog(*this, ": Optimizing soon.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00003491#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003492 m_jitExecuteCounter.setNewThreshold(
3493 adjustedCounterValue(Options::thresholdForOptimizeSoon()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00003494#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003495}
3496
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003497void CodeBlock::forceOptimizationSlowPathConcurrently()
3498{
3499 if (Options::verboseOSR())
3500 dataLog(*this, ": Forcing slow path concurrently.\n");
3501 m_jitExecuteCounter.forceSlowPathConcurrently();
3502}
3503
oliver@apple.com58c86752013-07-25 04:02:40 +00003504#if ENABLE(DFG_JIT)
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003505void CodeBlock::setOptimizationThresholdBasedOnCompilationResult(CompilationResult result)
3506{
fpizlo@apple.come7a417d2014-05-08 21:51:03 +00003507 JITCode::JITType type = jitType();
3508 if (type != JITCode::BaselineJIT) {
3509 dataLog(*this, ": expected to have baseline code but have ", type, "\n");
3510 RELEASE_ASSERT_NOT_REACHED();
3511 }
3512
3513 CodeBlock* theReplacement = replacement();
3514 if ((result == CompilationSuccessful) != (theReplacement != this)) {
3515 dataLog(*this, ": we have result = ", result, " but ");
3516 if (theReplacement == this)
3517 dataLog("we are our own replacement.\n");
3518 else
3519 dataLog("our replacement is ", pointerDump(theReplacement), "\n");
3520 RELEASE_ASSERT_NOT_REACHED();
3521 }
3522
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003523 switch (result) {
3524 case CompilationSuccessful:
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00003525 RELEASE_ASSERT(JITCode::isOptimizingJIT(replacement()->jitType()));
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003526 optimizeNextInvocation();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003527 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003528 case CompilationFailed:
3529 dontOptimizeAnytimeSoon();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003530 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003531 case CompilationDeferred:
3532 // We'd like to do dontOptimizeAnytimeSoon() but we cannot because
3533 // forceOptimizationSlowPathConcurrently() is inherently racy. It won't
3534 // necessarily guarantee anything. So, we make sure that even if that
3535 // function ends up being a no-op, we still eventually retry and realize
3536 // that we have optimized code ready.
3537 optimizeAfterWarmUp();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003538 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003539 case CompilationInvalidated:
3540 // Retry with exponential backoff.
3541 countReoptimization();
3542 optimizeAfterWarmUp();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003543 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003544 }
fpizlo@apple.come7a417d2014-05-08 21:51:03 +00003545
3546 dataLog("Unrecognized result: ", static_cast<int>(result), "\n");
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003547 RELEASE_ASSERT_NOT_REACHED();
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003548}
3549
oliver@apple.com807e7e12013-07-25 20:22:45 +00003550#endif
3551
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003552uint32_t CodeBlock::adjustedExitCountThreshold(uint32_t desiredThreshold)
3553{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00003554 ASSERT(JITCode::isOptimizingJIT(jitType()));
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003555 // Compute this the lame way so we don't saturate. This is called infrequently
3556 // enough that this loop won't hurt us.
3557 unsigned result = desiredThreshold;
3558 for (unsigned n = baselineVersion()->reoptimizationRetryCounter(); n--;) {
3559 unsigned newResult = result << 1;
3560 if (newResult < result)
3561 return std::numeric_limits<uint32_t>::max();
3562 result = newResult;
3563 }
3564 return result;
3565}
3566
3567uint32_t CodeBlock::exitCountThresholdForReoptimization()
3568{
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00003569 return adjustedExitCountThreshold(Options::osrExitCountForReoptimization() * codeTypeThresholdMultiplier());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003570}
3571
3572uint32_t CodeBlock::exitCountThresholdForReoptimizationFromLoop()
3573{
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00003574 return adjustedExitCountThreshold(Options::osrExitCountForReoptimizationFromLoop() * codeTypeThresholdMultiplier());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003575}
3576
3577bool CodeBlock::shouldReoptimizeNow()
3578{
3579 return osrExitCounter() >= exitCountThresholdForReoptimization();
3580}
3581
3582bool CodeBlock::shouldReoptimizeFromLoopNow()
3583{
3584 return osrExitCounter() >= exitCountThresholdForReoptimizationFromLoop();
3585}
3586#endif
3587
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00003588ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset)
3589{
3590 for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) {
3591 if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset)
3592 return &m_arrayProfiles[i];
3593 }
3594 return 0;
3595}
3596
3597ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset)
3598{
3599 ArrayProfile* result = getArrayProfile(bytecodeOffset);
3600 if (result)
3601 return result;
3602 return addArrayProfile(bytecodeOffset);
3603}
3604
fpizlo@apple.com8e470a22015-09-21 20:10:04 +00003605#if ENABLE(DFG_JIT)
3606Vector<CodeOrigin, 0, UnsafeVectorOverflow>& CodeBlock::codeOrigins()
3607{
3608 return m_jitCode->dfgCommon()->codeOrigins;
3609}
3610
3611size_t CodeBlock::numberOfDFGIdentifiers() const
3612{
3613 if (!JITCode::isOptimizingJIT(jitType()))
3614 return 0;
3615
3616 return m_jitCode->dfgCommon()->dfgIdentifiers.size();
3617}
3618
3619const Identifier& CodeBlock::identifier(int index) const
3620{
3621 size_t unlinkedIdentifiers = m_unlinkedCode->numberOfIdentifiers();
3622 if (static_cast<unsigned>(index) < unlinkedIdentifiers)
3623 return m_unlinkedCode->identifier(index);
3624 ASSERT(JITCode::isOptimizingJIT(jitType()));
3625 return m_jitCode->dfgCommon()->dfgIdentifiers[index - unlinkedIdentifiers];
3626}
3627#endif // ENABLE(DFG_JIT)
3628
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003629void CodeBlock::updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003630{
oliver@apple.comd2056662013-07-25 04:00:37 +00003631 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +00003632
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003633 numberOfLiveNonArgumentValueProfiles = 0;
3634 numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
3635 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
3636 ValueProfile* profile = getFromAllValueProfiles(i);
3637 unsigned numSamples = profile->totalNumberOfSamples();
3638 if (numSamples > ValueProfile::numberOfBuckets)
3639 numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
3640 numberOfSamplesInProfiles += numSamples;
3641 if (profile->m_bytecodeOffset < 0) {
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003642 profile->computeUpdatedPrediction(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003643 continue;
3644 }
3645 if (profile->numberOfSamples() || profile->m_prediction != SpecNone)
3646 numberOfLiveNonArgumentValueProfiles++;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003647 profile->computeUpdatedPrediction(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003648 }
3649
3650#if ENABLE(DFG_JIT)
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003651 m_lazyOperandValueProfiles.computeUpdatedPredictions(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003652#endif
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003653}
3654
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003655void CodeBlock::updateAllValueProfilePredictions()
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003656{
3657 unsigned ignoredValue1, ignoredValue2;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003658 updateAllPredictionsAndCountLiveness(ignoredValue1, ignoredValue2);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003659}
3660
oliver@apple.com58cdc332013-07-25 04:04:59 +00003661void CodeBlock::updateAllArrayPredictions()
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003662{
oliver@apple.comd2056662013-07-25 04:00:37 +00003663 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +00003664
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00003665 for (unsigned i = m_arrayProfiles.size(); i--;)
oliver@apple.com58cdc332013-07-25 04:04:59 +00003666 m_arrayProfiles[i].computeUpdatedPrediction(locker, this);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003667
3668 // Don't count these either, for similar reasons.
3669 for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
3670 m_arrayAllocationProfiles[i].updateIndexingType();
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003671}
3672
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003673void CodeBlock::updateAllPredictions()
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003674{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003675#if ENABLE(WEBASSEMBLY)
3676 if (m_ownerExecutable->isWebAssemblyExecutable())
3677 return;
3678#endif
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003679 updateAllValueProfilePredictions();
oliver@apple.com58cdc332013-07-25 04:04:59 +00003680 updateAllArrayPredictions();
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003681}
3682
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003683bool CodeBlock::shouldOptimizeNow()
3684{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003685 if (Options::verboseOSR())
3686 dataLog("Considering optimizing ", *this, "...\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003687
commit-queue@webkit.orgfbda60c2012-07-03 19:19:22 +00003688 if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay())
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003689 return true;
3690
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003691 updateAllArrayPredictions();
3692
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003693 unsigned numberOfLiveNonArgumentValueProfiles;
3694 unsigned numberOfSamplesInProfiles;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003695 updateAllPredictionsAndCountLiveness(numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003696
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003697 if (Options::verboseOSR()) {
3698 dataLogF(
3699 "Profile hotness: %lf (%u / %u), %lf (%u / %u)\n",
3700 (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(),
3701 numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(),
3702 (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(),
3703 numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles());
3704 }
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003705
commit-queue@webkit.orgfbda60c2012-07-03 19:19:22 +00003706 if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate())
3707 && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate())
3708 && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay())
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003709 return true;
3710
fpizlo@apple.com4043e812011-11-06 11:54:59 +00003711 ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max());
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003712 m_optimizationDelayCounter++;
3713 optimizeAfterWarmUp();
3714 return false;
3715}
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003716
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00003717#if ENABLE(DFG_JIT)
3718void CodeBlock::tallyFrequentExitSites()
3719{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00003720 ASSERT(JITCode::isOptimizingJIT(jitType()));
3721 ASSERT(alternative()->jitType() == JITCode::BaselineJIT);
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00003722
3723 CodeBlock* profiledBlock = alternative();
3724
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00003725 switch (jitType()) {
oliver@apple.comea771492013-07-25 03:58:38 +00003726 case JITCode::DFGJIT: {
3727 DFG::JITCode* jitCode = m_jitCode->dfg();
3728 for (unsigned i = 0; i < jitCode->osrExit.size(); ++i) {
3729 DFG::OSRExit& exit = jitCode->osrExit[i];
benjamin@webkit.org6f63a8b2015-02-18 07:04:10 +00003730 exit.considerAddingAsFrequentExitSite(profiledBlock);
oliver@apple.comea771492013-07-25 03:58:38 +00003731 }
3732 break;
3733 }
oliver@apple.com0c1b13e2013-07-25 03:58:43 +00003734
3735#if ENABLE(FTL_JIT)
oliver@apple.comea771492013-07-25 03:58:38 +00003736 case JITCode::FTLJIT: {
3737 // There is no easy way to avoid duplicating this code since the FTL::JITCode::osrExit
3738 // vector contains a totally different type, that just so happens to behave like
3739 // DFG::JITCode::osrExit.
oliver@apple.comea771492013-07-25 03:58:38 +00003740 FTL::JITCode* jitCode = m_jitCode->ftl();
3741 for (unsigned i = 0; i < jitCode->osrExit.size(); ++i) {
3742 FTL::OSRExit& exit = jitCode->osrExit[i];
benjamin@webkit.org6f63a8b2015-02-18 07:04:10 +00003743 exit.considerAddingAsFrequentExitSite(profiledBlock);
oliver@apple.comea771492013-07-25 03:58:38 +00003744 }
oliver@apple.comea771492013-07-25 03:58:38 +00003745 break;
oliver@apple.com0c1b13e2013-07-25 03:58:43 +00003746 }
3747#endif
oliver@apple.comea771492013-07-25 03:58:38 +00003748
3749 default:
3750 RELEASE_ASSERT_NOT_REACHED();
3751 break;
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00003752 }
3753}
3754#endif // ENABLE(DFG_JIT)
3755
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003756#if ENABLE(VERBOSE_VALUE_PROFILE)
3757void CodeBlock::dumpValueProfiles()
3758{
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00003759 dataLog("ValueProfile for ", *this, ":\n");
fpizlo@apple.com086d2af2011-12-21 02:29:15 +00003760 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
3761 ValueProfile* profile = getFromAllValueProfiles(i);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003762 if (profile->m_bytecodeOffset < 0) {
3763 ASSERT(profile->m_bytecodeOffset == -1);
fpizlo@apple.com01902c82012-11-22 04:23:36 +00003764 dataLogF(" arg = %u: ", i);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003765 } else
fpizlo@apple.com01902c82012-11-22 04:23:36 +00003766 dataLogF(" bc = %d: ", profile->m_bytecodeOffset);
fpizlo@apple.com62336162012-06-07 01:35:59 +00003767 if (!profile->numberOfSamples() && profile->m_prediction == SpecNone) {
fpizlo@apple.com01902c82012-11-22 04:23:36 +00003768 dataLogF("<empty>\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003769 continue;
3770 }
fpizlo@apple.comd095b242012-02-12 03:21:32 +00003771 profile->dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +00003772 dataLogF("\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003773 }
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00003774 dataLog("RareCaseProfile for ", *this, ":\n");
barraclough@apple.come32d4ec2011-09-21 22:43:11 +00003775 for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) {
3776 RareCaseProfile* profile = rareCaseProfile(i);
fpizlo@apple.com01902c82012-11-22 04:23:36 +00003777 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
fpizlo@apple.com9b0b31e2011-09-19 22:27:38 +00003778 }
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00003779 dataLog("SpecialFastCaseProfile for ", *this, ":\n");
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003780 for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) {
3781 RareCaseProfile* profile = specialFastCaseProfile(i);
fpizlo@apple.com01902c82012-11-22 04:23:36 +00003782 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003783 }
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003784}
fpizlo@apple.com8618e4b2012-07-03 01:27:16 +00003785#endif // ENABLE(VERBOSE_VALUE_PROFILE)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00003786
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00003787unsigned CodeBlock::frameRegisterCount()
3788{
3789 switch (jitType()) {
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00003790 case JITCode::InterpreterThunk:
3791 return LLInt::frameRegisterCountFor(this);
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00003792
3793#if ENABLE(JIT)
3794 case JITCode::BaselineJIT:
3795 return JIT::frameRegisterCountFor(this);
3796#endif // ENABLE(JIT)
3797
3798#if ENABLE(DFG_JIT)
3799 case JITCode::DFGJIT:
3800 case JITCode::FTLJIT:
3801 return jitCode()->dfgCommon()->frameRegisterCount;
3802#endif // ENABLE(DFG_JIT)
3803
3804 default:
3805 RELEASE_ASSERT_NOT_REACHED();
3806 return 0;
3807 }
3808}
3809
msaboff@apple.com95894332014-01-29 19:18:54 +00003810int CodeBlock::stackPointerOffset()
3811{
3812 return virtualRegisterForLocal(frameRegisterCount() - 1).offset();
3813}
3814
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00003815size_t CodeBlock::predictedMachineCodeSize()
3816{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00003817 // This will be called from CodeBlock::CodeBlock before either m_vm or the
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00003818 // instructions have been initialized. It's OK to return 0 because what will really
3819 // matter is the recomputation of this value when the slow path is triggered.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00003820 if (!m_vm)
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00003821 return 0;
3822
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00003823 if (!m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT)
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00003824 return 0; // It's as good of a prediction as we'll get.
3825
3826 // Be conservative: return a size that will be an overestimation 84% of the time.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00003827 double multiplier = m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.mean() +
3828 m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.standardDeviation();
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00003829
3830 // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing
3831 // here is OK, since this whole method is just a heuristic.
3832 if (multiplier < 0 || multiplier > 1000)
3833 return 0;
3834
3835 double doubleResult = multiplier * m_instructions.size();
3836
3837 // Be even more paranoid: silently reject values that won't fit into a size_t. If
3838 // the function is so huge that we can't even fit it into virtual memory then we
3839 // should probably have some other guards in place to prevent us from even getting
3840 // to this point.
3841 if (doubleResult > std::numeric_limits<size_t>::max())
3842 return 0;
3843
3844 return static_cast<size_t>(doubleResult);
3845}
3846
fpizlo@apple.comc828f142011-10-25 21:56:31 +00003847bool CodeBlock::usesOpcode(OpcodeID opcodeID)
3848{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00003849 Interpreter* interpreter = vm()->interpreter;
fpizlo@apple.comc828f142011-10-25 21:56:31 +00003850 Instruction* instructionsBegin = instructions().begin();
3851 unsigned instructionCount = instructions().size();
3852
3853 for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
3854 switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
3855#define DEFINE_OP(curOpcode, length) \
3856 case curOpcode: \
3857 if (curOpcode == opcodeID) \
3858 return true; \
3859 bytecodeOffset += length; \
3860 break;
3861 FOR_EACH_OPCODE_ID(DEFINE_OP)
3862#undef DEFINE_OP
3863 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00003864 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comc828f142011-10-25 21:56:31 +00003865 break;
3866 }
3867 }
3868
3869 return false;
3870}
fpizlo@apple.comc828f142011-10-25 21:56:31 +00003871
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00003872String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
oliver@apple.coma08210b2012-07-18 23:26:06 +00003873{
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00003874 for (unsigned i = 0; i < m_constantRegisters.size(); i++) {
3875 if (m_constantRegisters[i].get().isEmpty())
3876 continue;
3877 if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(m_constantRegisters[i].get())) {
3878 ConcurrentJITLocker locker(symbolTable->m_lock);
3879 auto end = symbolTable->end(locker);
3880 for (auto ptr = symbolTable->begin(locker); ptr != end; ++ptr) {
3881 if (ptr->value.varOffset() == VarOffset(virtualRegister)) {
3882 // FIXME: This won't work from the compilation thread.
3883 // https://bugs.webkit.org/show_bug.cgi?id=115300
3884 return ptr->key.get();
3885 }
3886 }
oliver@apple.comf72e22e2013-07-25 03:59:04 +00003887 }
oliver@apple.coma08210b2012-07-18 23:26:06 +00003888 }
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00003889 if (virtualRegister == thisRegister())
benjamin@webkit.org762e2c62012-09-04 21:19:25 +00003890 return ASCIILiteral("this");
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00003891 if (virtualRegister.isArgument())
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00003892 return String::format("arguments[%3d]", virtualRegister.toArgument());
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00003893
oliver@apple.coma08210b2012-07-18 23:26:06 +00003894 return "";
3895}
3896
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00003897ValueProfile* CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset)
3898{
3899 ValueProfile* result = binarySearch<ValueProfile, int>(
3900 m_valueProfiles, m_valueProfiles.size(), bytecodeOffset,
3901 getValueProfileBytecodeOffset<ValueProfile>);
3902 ASSERT(result->m_bytecodeOffset != -1);
3903 ASSERT(instructions()[bytecodeOffset + opcodeLength(
3904 m_vm->interpreter->getOpcodeID(
3905 instructions()[bytecodeOffset].u.opcode)) - 1].u.profile == result);
3906 return result;
3907}
3908
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00003909void CodeBlock::validate()
3910{
3911 BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
3912
3913 FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(0);
3914
3915 if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeRegisters)) {
3916 beginValidationDidFail();
3917 dataLog(" Wrong number of bits in result!\n");
3918 dataLog(" Result: ", liveAtHead, "\n");
3919 dataLog(" Bit count: ", liveAtHead.numBits(), "\n");
3920 endValidationDidFail();
3921 }
3922
3923 for (unsigned i = m_numCalleeRegisters; i--;) {
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00003924 VirtualRegister reg = virtualRegisterForLocal(i);
3925
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003926 if (liveAtHead.get(i)) {
3927 beginValidationDidFail();
3928 dataLog(" Variable ", reg, " is expected to be dead.\n");
3929 dataLog(" Result: ", liveAtHead, "\n");
3930 endValidationDidFail();
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00003931 }
3932 }
3933}
3934
3935void CodeBlock::beginValidationDidFail()
3936{
3937 dataLog("Validation failure in ", *this, ":\n");
3938 dataLog("\n");
3939}
3940
3941void CodeBlock::endValidationDidFail()
3942{
3943 dataLog("\n");
3944 dumpBytecode();
3945 dataLog("\n");
3946 dataLog("Validation failure.\n");
3947 RELEASE_ASSERT_NOT_REACHED();
3948}
3949
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00003950void CodeBlock::addBreakpoint(unsigned numBreakpoints)
3951{
3952 m_numBreakpoints += numBreakpoints;
3953 ASSERT(m_numBreakpoints);
mark.lam@apple.com51ccaab2014-02-01 20:29:23 +00003954 if (JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00003955 jettison(Profiler::JettisonDueToDebuggerBreakpoint);
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00003956}
3957
3958void CodeBlock::setSteppingMode(CodeBlock::SteppingMode mode)
3959{
3960 m_steppingMode = mode;
mark.lam@apple.com51ccaab2014-02-01 20:29:23 +00003961 if (mode == SteppingModeEnabled && JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00003962 jettison(Profiler::JettisonDueToDebuggerStepping);
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00003963}
3964
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00003965RareCaseProfile* CodeBlock::rareCaseProfileForBytecodeOffset(int bytecodeOffset)
3966{
3967 return tryBinarySearch<RareCaseProfile, int>(
3968 m_rareCaseProfiles, m_rareCaseProfiles.size(), bytecodeOffset,
3969 getRareCaseProfileBytecodeOffset);
3970}
3971
mark.lam@apple.comff2c14a2015-09-24 18:38:35 +00003972unsigned CodeBlock::rareCaseProfileCountForBytecodeOffset(int bytecodeOffset)
3973{
3974 RareCaseProfile* profile = rareCaseProfileForBytecodeOffset(bytecodeOffset);
3975 if (profile)
3976 return profile->m_counter;
3977 return 0;
3978}
3979
mhahnenberg@apple.com0ef30c42014-05-02 21:21:04 +00003980#if ENABLE(JIT)
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00003981DFG::CapabilityLevel CodeBlock::capabilityLevel()
3982{
commit-queue@webkit.org87dc3e72015-10-04 01:45:21 +00003983 DFG::CapabilityLevel result = capabilityLevelInternal();
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00003984 m_capabilityLevelState = result;
3985 return result;
3986}
mhahnenberg@apple.com0ef30c42014-05-02 21:21:04 +00003987#endif
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00003988
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003989void CodeBlock::insertBasicBlockBoundariesForControlFlowProfiler(Vector<Instruction, 0, UnsafeVectorOverflow>& instructions)
3990{
3991 const Vector<size_t>& bytecodeOffsets = unlinkedCodeBlock()->opProfileControlFlowBytecodeOffsets();
3992 for (size_t i = 0, offsetsLength = bytecodeOffsets.size(); i < offsetsLength; i++) {
3993 // Because op_profile_control_flow is emitted at the beginning of every basic block, finding
3994 // the next op_profile_control_flow will give us the text range of a single basic block.
3995 size_t startIdx = bytecodeOffsets[i];
3996 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[startIdx].u.opcode) == op_profile_control_flow);
3997 int basicBlockStartOffset = instructions[startIdx + 1].u.operand;
3998 int basicBlockEndOffset;
3999 if (i + 1 < offsetsLength) {
4000 size_t endIdx = bytecodeOffsets[i + 1];
4001 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[endIdx].u.opcode) == op_profile_control_flow);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00004002 basicBlockEndOffset = instructions[endIdx + 1].u.operand - 1;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004003 } else {
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00004004 basicBlockEndOffset = m_sourceOffset + ownerScriptExecutable()->source().length() - 1; // Offset before the closing brace.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004005 basicBlockStartOffset = std::min(basicBlockStartOffset, basicBlockEndOffset); // Some start offsets may be at the closing brace, ensure it is the offset before.
4006 }
4007
4008 // The following check allows for the same textual JavaScript basic block to have its bytecode emitted more
4009 // than once and still play nice with the control flow profiler. When basicBlockStartOffset is larger than
4010 // basicBlockEndOffset, it indicates that the bytecode generator has emitted code for the same AST node
4011 // more than once (for example: ForInNode, Finally blocks in TryNode, etc). Though these are different
4012 // basic blocks at the bytecode level, they are generated from the same textual basic block in the JavaScript
4013 // program. The condition:
4014 // (basicBlockEndOffset < basicBlockStartOffset)
4015 // is encountered when op_profile_control_flow lies across the boundary of these duplicated bytecode basic
4016 // blocks and the textual offset goes from the end of the duplicated block back to the beginning. These
4017 // ranges are dummy ranges and are ignored. The duplicated bytecode basic blocks point to the same
4018 // internal data structure, so if any of them execute, it will record the same textual basic block in the
4019 // JavaScript program as executing.
4020 // At the bytecode level, this situation looks like:
4021 // j: op_profile_control_flow (from j->k, we have basicBlockEndOffset < basicBlockStartOffset)
4022 // ...
4023 // k: op_profile_control_flow (we want to skip over the j->k block and start fresh at offset k as the start of a new basic block k->m).
4024 // ...
4025 // m: op_profile_control_flow
4026 if (basicBlockEndOffset < basicBlockStartOffset) {
4027 RELEASE_ASSERT(i + 1 < offsetsLength); // We should never encounter dummy blocks at the end of a CodeBlock.
4028 instructions[startIdx + 1].u.basicBlockLocation = vm()->controlFlowProfiler()->dummyBasicBlock();
4029 continue;
4030 }
4031
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00004032 BasicBlockLocation* basicBlockLocation = vm()->controlFlowProfiler()->getBasicBlockLocation(ownerScriptExecutable()->sourceID(), basicBlockStartOffset, basicBlockEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004033
4034 // Find all functions that are enclosed within the range: [basicBlockStartOffset, basicBlockEndOffset]
4035 // and insert these functions' start/end offsets as gaps in the current BasicBlockLocation.
4036 // This is necessary because in the original source text of a JavaScript program,
4037 // function literals form new basic blocks boundaries, but they aren't represented
4038 // inside the CodeBlock's instruction stream.
4039 auto insertFunctionGaps = [basicBlockLocation, basicBlockStartOffset, basicBlockEndOffset] (const WriteBarrier<FunctionExecutable>& functionExecutable) {
4040 const UnlinkedFunctionExecutable* executable = functionExecutable->unlinkedExecutable();
4041 int functionStart = executable->typeProfilingStartOffset();
4042 int functionEnd = executable->typeProfilingEndOffset();
4043 if (functionStart >= basicBlockStartOffset && functionEnd <= basicBlockEndOffset)
4044 basicBlockLocation->insertGap(functionStart, functionEnd);
4045 };
4046
4047 for (const WriteBarrier<FunctionExecutable>& executable : m_functionDecls)
4048 insertFunctionGaps(executable);
4049 for (const WriteBarrier<FunctionExecutable>& executable : m_functionExprs)
4050 insertFunctionGaps(executable);
4051
4052 instructions[startIdx + 1].u.basicBlockLocation = basicBlockLocation;
4053 }
4054}
4055
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +00004056} // namespace JSC