blob: 8c7b6e5b4c596924d8cd6196fe1c488fa2cc45ad [file] [log] [blame]
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001/*
fpizlo@apple.com39303e02016-04-05 22:17:35 +00002 * Copyright (C) 2008-2010, 2012-2016 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"
oliver@apple.comd04e0a02014-02-01 01:37:59 +000048#include "JSCJSValue.h"
barraclough@apple.com3dc12332009-08-12 05:22:33 +000049#include "JSFunction.h"
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +000050#include "JSLexicalEnvironment.h"
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +000051#include "JSModuleEnvironment.h"
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +000052#include "LLIntEntrypoint.h"
keith_miller@apple.com8350adf2016-05-24 23:49:57 +000053#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.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"
sbarati@apple.comd3d0c002016-01-30 01:11:05 +000056#include "PCToCodeOriginMap.h"
fpizlo@apple.comb26b5242015-09-10 19:49:36 +000057#include "PolymorphicAccess.h"
akling@apple.com5a0a87e2014-03-22 20:57:04 +000058#include "ProfilerDatabase.h"
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +000059#include "ReduceWhitespace.h"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +000060#include "Repatch.h"
mark.lam@apple.coma4fe7ab2012-11-09 03:03:44 +000061#include "SlotVisitorInlines.h"
msaboff@apple.com4d563e42014-08-16 01:45:40 +000062#include "StackVisitor.h"
fpizlo@apple.comd5f99462016-04-11 19:31:04 +000063#include "StructureStubInfo.h"
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +000064#include "TypeLocationCache.h"
65#include "TypeProfiler.h"
akling@apple.com8427aaf2014-01-27 05:45:30 +000066#include "UnlinkedInstructionStream.h"
fpizlo@apple.com4a528d02016-05-11 00:08:50 +000067#include "VMInlines.h"
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000068#include <wtf/BagToHashMap.h>
fpizlo@apple.com806b5822013-01-08 01:23:38 +000069#include <wtf/CommaPrinter.h>
aroben@apple.coma2fd5702008-09-02 15:15:21 +000070#include <wtf/StringExtras.h>
fpizlo@apple.com9fe49132012-12-04 19:29:13 +000071#include <wtf/StringPrintStream.h>
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +000072#include <wtf/text/UniquedStringImpl.h>
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000073
msaboff@apple.com02085462015-09-10 17:47:16 +000074#if ENABLE(JIT)
75#include "RegisterAtOffsetList.h"
76#endif
77
commit-queue@webkit.org4ea48922011-07-06 00:56:49 +000078#if ENABLE(DFG_JIT)
79#include "DFGOperations.h"
80#endif
81
carlosgc@webkit.org13f6daf22013-07-30 06:42:00 +000082#if ENABLE(FTL_JIT)
83#include "FTLJITCode.h"
84#endif
85
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000086namespace JSC {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000087
ggaren@apple.com81def5f2015-10-09 23:10:16 +000088const ClassInfo CodeBlock::s_info = {
89 "CodeBlock", 0, 0,
90 CREATE_METHOD_TABLE(CodeBlock)
91};
92
93const ClassInfo FunctionCodeBlock::s_info = {
94 "FunctionCodeBlock", &Base::s_info, 0,
95 CREATE_METHOD_TABLE(FunctionCodeBlock)
96};
97
98#if ENABLE(WEBASSEMBLY)
99const ClassInfo WebAssemblyCodeBlock::s_info = {
100 "WebAssemblyCodeBlock", &Base::s_info, 0,
101 CREATE_METHOD_TABLE(WebAssemblyCodeBlock)
102};
103#endif
104
105const ClassInfo GlobalCodeBlock::s_info = {
106 "GlobalCodeBlock", &Base::s_info, 0,
107 CREATE_METHOD_TABLE(GlobalCodeBlock)
108};
109
110const ClassInfo ProgramCodeBlock::s_info = {
111 "ProgramCodeBlock", &Base::s_info, 0,
112 CREATE_METHOD_TABLE(ProgramCodeBlock)
113};
114
115const ClassInfo ModuleProgramCodeBlock::s_info = {
116 "ModuleProgramCodeBlock", &Base::s_info, 0,
117 CREATE_METHOD_TABLE(ModuleProgramCodeBlock)
118};
119
120const ClassInfo EvalCodeBlock::s_info = {
121 "EvalCodeBlock", &Base::s_info, 0,
122 CREATE_METHOD_TABLE(EvalCodeBlock)
123};
124
125void FunctionCodeBlock::destroy(JSCell* cell)
126{
127 jsCast<FunctionCodeBlock*>(cell)->~FunctionCodeBlock();
128}
129
130#if ENABLE(WEBASSEMBLY)
131void WebAssemblyCodeBlock::destroy(JSCell* cell)
132{
133 jsCast<WebAssemblyCodeBlock*>(cell)->~WebAssemblyCodeBlock();
134}
135#endif
136
137void ProgramCodeBlock::destroy(JSCell* cell)
138{
139 jsCast<ProgramCodeBlock*>(cell)->~ProgramCodeBlock();
140}
141
142void ModuleProgramCodeBlock::destroy(JSCell* cell)
143{
144 jsCast<ModuleProgramCodeBlock*>(cell)->~ModuleProgramCodeBlock();
145}
146
147void EvalCodeBlock::destroy(JSCell* cell)
148{
149 jsCast<EvalCodeBlock*>(cell)->~EvalCodeBlock();
150}
151
oliver@apple.com02039462013-07-25 03:59:29 +0000152CString CodeBlock::inferredName() const
fpizlo@apple.com1a6da212012-12-10 18:38:15 +0000153{
154 switch (codeType()) {
155 case GlobalCode:
156 return "<global>";
157 case EvalCode:
158 return "<eval>";
159 case FunctionCode:
oliver@apple.com02039462013-07-25 03:59:29 +0000160 return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().utf8();
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +0000161 case ModuleCode:
162 return "<module>";
fpizlo@apple.com1a6da212012-12-10 18:38:15 +0000163 default:
164 CRASH();
oliver@apple.com02039462013-07-25 03:59:29 +0000165 return CString("", 0);
fpizlo@apple.com1a6da212012-12-10 18:38:15 +0000166 }
167}
168
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000169bool CodeBlock::hasHash() const
170{
171 return !!m_hash;
172}
173
174bool CodeBlock::isSafeToComputeHash() const
175{
176 return !isCompilationThread();
177}
178
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000179CodeBlockHash CodeBlock::hash() const
180{
oliver@apple.comacdde492013-07-25 04:02:57 +0000181 if (!m_hash) {
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000182 RELEASE_ASSERT(isSafeToComputeHash());
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000183 m_hash = CodeBlockHash(ownerScriptExecutable()->source(), specializationKind());
oliver@apple.comacdde492013-07-25 04:02:57 +0000184 }
185 return m_hash;
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000186}
187
oliver@apple.com02039462013-07-25 03:59:29 +0000188CString CodeBlock::sourceCodeForTools() const
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000189{
190 if (codeType() != FunctionCode)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000191 return ownerScriptExecutable()->source().toUTF8();
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000192
193 SourceProvider* provider = source();
194 FunctionExecutable* executable = jsCast<FunctionExecutable*>(ownerExecutable());
195 UnlinkedFunctionExecutable* unlinked = executable->unlinkedExecutable();
196 unsigned unlinkedStartOffset = unlinked->startOffset();
197 unsigned linkedStartOffset = executable->source().startOffset();
198 int delta = linkedStartOffset - unlinkedStartOffset;
mark.lam@apple.comfa35e782013-11-19 21:55:16 +0000199 unsigned rangeStart = delta + unlinked->unlinkedFunctionNameStart();
oliver@apple.com02039462013-07-25 03:59:29 +0000200 unsigned rangeEnd = delta + unlinked->startOffset() + unlinked->sourceLength();
201 return toCString(
202 "function ",
akling@apple.com73320982015-12-13 20:03:24 +0000203 provider->source().substring(rangeStart, rangeEnd - rangeStart).utf8());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000204}
205
oliver@apple.com02039462013-07-25 03:59:29 +0000206CString CodeBlock::sourceCodeOnOneLine() const
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000207{
208 return reduceWhitespace(sourceCodeForTools());
209}
210
fpizlo@apple.comf285f712014-03-13 01:50:41 +0000211CString CodeBlock::hashAsStringIfPossible() const
212{
213 if (hasHash() || isSafeToComputeHash())
214 return toCString(hash());
215 return "<no-hash>";
216}
217
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000218void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const
219{
fpizlo@apple.comf285f712014-03-13 01:50:41 +0000220 out.print(inferredName(), "#", hashAsStringIfPossible());
msaboff@apple.com95894332014-01-29 19:18:54 +0000221 out.print(":[", RawPointer(this), "->");
222 if (!!m_alternative)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000223 out.print(RawPointer(alternative()), "->");
msaboff@apple.com95894332014-01-29 19:18:54 +0000224 out.print(RawPointer(ownerExecutable()), ", ", jitType, codeType());
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000225
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000226 if (codeType() == FunctionCode)
227 out.print(specializationKind());
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000228 out.print(", ", instructionCount());
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000229 if (this->jitType() == JITCode::BaselineJIT && m_shouldAlwaysBeInlined)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000230 out.print(" (ShouldAlwaysBeInlined)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000231 if (ownerScriptExecutable()->neverInline())
oliver@apple.com4e67ae52013-07-25 04:01:24 +0000232 out.print(" (NeverInline)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000233 if (ownerScriptExecutable()->neverOptimize())
mark.lam@apple.com49e71b92015-08-28 05:59:44 +0000234 out.print(" (NeverOptimize)");
keith_miller@apple.coma64964a2016-04-22 02:28:00 +0000235 else if (ownerScriptExecutable()->neverFTLOptimize())
236 out.print(" (NeverFTLOptimize)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000237 if (ownerScriptExecutable()->didTryToEnterInLoop())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000238 out.print(" (DidTryToEnterInLoop)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000239 if (ownerScriptExecutable()->isStrictMode())
fpizlo@apple.com018818d2013-09-13 23:18:19 +0000240 out.print(" (StrictMode)");
msaboff@apple.com95894332014-01-29 19:18:54 +0000241 if (this->jitType() == JITCode::BaselineJIT && m_didFailFTLCompilation)
242 out.print(" (FTLFail)");
243 if (this->jitType() == JITCode::BaselineJIT && m_hasBeenCompiledWithFTL)
244 out.print(" (HadFTLReplacement)");
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000245 out.print("]");
246}
247
248void CodeBlock::dump(PrintStream& out) const
249{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +0000250 dumpAssumingJITType(out, jitType());
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000251}
252
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000253static CString idName(int id0, const Identifier& ident)
254{
oliver@apple.com02039462013-07-25 03:59:29 +0000255 return toCString(ident.impl(), "(@id", id0, ")");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000256}
257
oliver@apple.com02039462013-07-25 03:59:29 +0000258CString CodeBlock::registerName(int r) const
mrowe@apple.comd5316092009-11-05 02:22:08 +0000259{
mrowe@apple.comd5316092009-11-05 02:22:08 +0000260 if (isConstantRegisterIndex(r))
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000261 return constantName(r);
mrowe@apple.comd5316092009-11-05 02:22:08 +0000262
fpizlo@apple.com240c7a52015-02-02 23:32:00 +0000263 return toCString(VirtualRegister(r));
mrowe@apple.comd5316092009-11-05 02:22:08 +0000264}
265
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000266CString CodeBlock::constantName(int index) const
267{
268 JSValue value = getConstant(index);
269 return toCString(value, "(", VirtualRegister(index), ")");
270}
271
oliver@apple.com02039462013-07-25 03:59:29 +0000272static CString regexpToSourceString(RegExp* regExp)
oliver@apple.com22d55c32010-05-10 01:41:07 +0000273{
274 char postfix[5] = { '/', 0, 0, 0, 0 };
275 int index = 1;
276 if (regExp->global())
277 postfix[index++] = 'g';
278 if (regExp->ignoreCase())
279 postfix[index++] = 'i';
280 if (regExp->multiline())
281 postfix[index] = 'm';
msaboff@apple.com3f194652016-03-09 20:11:46 +0000282 if (regExp->sticky())
283 postfix[index++] = 'y';
284 if (regExp->unicode())
285 postfix[index++] = 'u';
oliver@apple.com22d55c32010-05-10 01:41:07 +0000286
oliver@apple.com02039462013-07-25 03:59:29 +0000287 return toCString("/", regExp->pattern().impl(), postfix);
oliver@apple.com22d55c32010-05-10 01:41:07 +0000288}
289
290static CString regexpName(int re, RegExp* regexp)
291{
oliver@apple.com02039462013-07-25 03:59:29 +0000292 return toCString(regexpToSourceString(regexp), "(@re", re, ")");
oliver@apple.com22d55c32010-05-10 01:41:07 +0000293}
294
ggaren@apple.comd0740c82008-05-28 20:47:13 +0000295NEVER_INLINE static const char* debugHookName(int debugHookID)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000296{
weinig@apple.coma963b962008-06-05 05:36:55 +0000297 switch (static_cast<DebugHookID>(debugHookID)) {
298 case DidEnterCallFrame:
299 return "didEnterCallFrame";
300 case WillLeaveCallFrame:
301 return "willLeaveCallFrame";
302 case WillExecuteStatement:
303 return "willExecuteStatement";
304 case WillExecuteProgram:
305 return "willExecuteProgram";
306 case DidExecuteProgram:
307 return "didExecuteProgram";
308 case DidReachBreakpoint:
309 return "didReachBreakpoint";
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000310 }
weinig@apple.coma963b962008-06-05 05:36:55 +0000311
oliver@apple.com5598c182013-01-23 22:25:07 +0000312 RELEASE_ASSERT_NOT_REACHED();
ggaren@apple.comd0740c82008-05-28 20:47:13 +0000313 return "";
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000314}
315
msaboff@apple.comc5808642013-09-05 23:27:41 +0000316void CodeBlock::printUnaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000317{
318 int r0 = (++it)->u.operand;
319 int r1 = (++it)->u.operand;
320
msaboff@apple.comc5808642013-09-05 23:27:41 +0000321 printLocationAndOp(out, exec, location, it, op);
322 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000323}
324
msaboff@apple.comc5808642013-09-05 23:27:41 +0000325void CodeBlock::printBinaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000326{
327 int r0 = (++it)->u.operand;
328 int r1 = (++it)->u.operand;
329 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000330 printLocationAndOp(out, exec, location, it, op);
331 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000332}
333
msaboff@apple.comc5808642013-09-05 23:27:41 +0000334void CodeBlock::printConditionalJump(PrintStream& out, ExecState* exec, const Instruction*, const Instruction*& it, int location, const char* op)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000335{
336 int r0 = (++it)->u.operand;
337 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000338 printLocationAndOp(out, exec, location, it, op);
339 out.printf("%s, %d(->%d)", registerName(r0).data(), offset, location + offset);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000340}
341
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000342void CodeBlock::printGetByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it)
weinig@apple.com3412bb42008-09-01 21:22:54 +0000343{
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000344 const char* op;
345 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
346 case op_get_by_id:
347 op = "get_by_id";
348 break;
keith_miller@apple.com8350adf2016-05-24 23:49:57 +0000349 case op_get_by_id_proto_load:
350 op = "get_by_id_proto_load";
351 break;
keith_miller@apple.com785c6512016-05-27 18:36:30 +0000352 case op_get_by_id_unset:
353 op = "get_by_id_unset";
354 break;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000355 case op_get_array_length:
356 op = "array_length";
357 break;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000358 default:
oliver@apple.com5598c182013-01-23 22:25:07 +0000359 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.com0a661162014-09-08 02:16:47 +0000360#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000361 op = 0;
mjs@apple.com0a661162014-09-08 02:16:47 +0000362#endif
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000363 }
weinig@apple.com3412bb42008-09-01 21:22:54 +0000364 int r0 = (++it)->u.operand;
365 int r1 = (++it)->u.operand;
366 int id0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000367 printLocationAndOp(out, exec, location, it, op);
368 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000369 it += 4; // Increment up to the value profiler.
weinig@apple.com3412bb42008-09-01 21:22:54 +0000370}
371
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000372static void dumpStructure(PrintStream& out, const char* name, Structure* structure, const Identifier& ident)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000373{
374 if (!structure)
375 return;
376
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000377 out.printf("%s = %p", name, structure);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000378
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000379 PropertyOffset offset = structure->getConcurrently(ident.impl());
fpizlo@apple.com961a9562012-07-24 02:13:19 +0000380 if (offset != invalidOffset)
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000381 out.printf(" (offset = %d)", offset);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000382}
383
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000384static void dumpChain(PrintStream& out, StructureChain* chain, const Identifier& ident)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000385{
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000386 out.printf("chain = %p: [", chain);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000387 bool first = true;
388 for (WriteBarrier<Structure>* currentStructure = chain->head();
389 *currentStructure;
390 ++currentStructure) {
391 if (first)
392 first = false;
393 else
fpizlo@apple.com304fbca2012-12-17 21:38:51 +0000394 out.printf(", ");
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000395 dumpStructure(out, "struct", currentStructure->get(), ident);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000396 }
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000397 out.printf("]");
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000398}
399
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000400void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000401{
402 Instruction* instruction = instructions().begin() + location;
403
oliver@apple.com9b652762013-08-12 22:39:13 +0000404 const Identifier& ident = identifier(instruction[3].u.operand);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000405
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000406 UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
407
fpizlo@apple.com4cafdbd2012-09-11 20:00:31 +0000408 if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000409 out.printf(" llint(array_length)");
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000410 else if (StructureID structureID = instruction[4].u.structureID) {
411 Structure* structure = m_vm->heap.structureIDTable().get(structureID);
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000412 out.printf(" llint(");
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000413 dumpStructure(out, "struct", structure, ident);
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000414 out.printf(")");
keith_miller@apple.com8350adf2016-05-24 23:49:57 +0000415 if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_by_id_proto_load)
416 out.printf(" proto(%p)", instruction[6].u.pointer);
fpizlo@apple.com4cafdbd2012-09-11 20:00:31 +0000417 }
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000418
419#if ENABLE(JIT)
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000420 if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
421 StructureStubInfo& stubInfo = *stubPtr;
fpizlo@apple.com12803e22014-02-02 06:38:51 +0000422 if (stubInfo.resetByGC)
423 out.print(" (Reset By GC)");
424
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000425 out.printf(" jit(");
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000426
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000427 Structure* baseStructure = nullptr;
428 PolymorphicAccess* stub = nullptr;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000429
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000430 switch (stubInfo.cacheType) {
431 case CacheType::GetByIdSelf:
432 out.printf("self");
433 baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get();
434 break;
435 case CacheType::Stub:
436 out.printf("stub");
437 stub = stubInfo.u.stub;
438 break;
439 case CacheType::Unset:
440 out.printf("unset");
441 break;
442 default:
443 RELEASE_ASSERT_NOT_REACHED();
444 break;
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000445 }
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000446
447 if (baseStructure) {
448 out.printf(", ");
449 dumpStructure(out, "struct", baseStructure, ident);
450 }
451
452 if (stub)
453 out.print(", ", *stub);
454
455 out.printf(")");
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000456 }
mark.lam@apple.comb1ea3ea2013-10-24 16:10:59 +0000457#else
458 UNUSED_PARAM(map);
fpizlo@apple.comd52a7942012-05-21 22:32:40 +0000459#endif
460}
461
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000462void CodeBlock::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000463{
464 Instruction* instruction = instructions().begin() + location;
465
466 const Identifier& ident = identifier(instruction[2].u.operand);
467
468 UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000469
470 out.print(", ", instruction[8].u.putByIdFlags);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000471
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000472 if (StructureID structureID = instruction[4].u.structureID) {
473 Structure* structure = m_vm->heap.structureIDTable().get(structureID);
474 out.print(" llint(");
475 if (StructureID newStructureID = instruction[6].u.structureID) {
476 Structure* newStructure = m_vm->heap.structureIDTable().get(newStructureID);
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000477 dumpStructure(out, "prev", structure, ident);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000478 out.print(", ");
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000479 dumpStructure(out, "next", newStructure, ident);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000480 if (StructureChain* chain = instruction[7].u.structureChain.get()) {
481 out.print(", ");
fpizlo@apple.com15ec1b22014-09-21 19:18:40 +0000482 dumpChain(out, chain, ident);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000483 }
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +0000484 } else
485 dumpStructure(out, "struct", structure, ident);
486 out.print(")");
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000487 }
488
489#if ENABLE(JIT)
490 if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
491 StructureStubInfo& stubInfo = *stubPtr;
492 if (stubInfo.resetByGC)
493 out.print(" (Reset By GC)");
494
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000495 out.printf(" jit(");
496
497 switch (stubInfo.cacheType) {
498 case CacheType::PutByIdReplace:
499 out.print("replace, ");
500 dumpStructure(out, "struct", stubInfo.u.byIdSelf.baseObjectStructure.get(), ident);
501 break;
502 case CacheType::Stub: {
503 out.print("stub, ", *stubInfo.u.stub);
504 break;
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000505 }
fpizlo@apple.com5566f232015-10-05 17:05:24 +0000506 case CacheType::Unset:
507 out.printf("unset");
508 break;
509 default:
510 RELEASE_ASSERT_NOT_REACHED();
511 break;
512 }
513 out.printf(")");
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000514 }
515#else
516 UNUSED_PARAM(map);
517#endif
518}
519
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000520void 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 +0000521{
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000522 int dst = (++it)->u.operand;
ggaren@apple.com6f82ad52012-01-12 01:00:58 +0000523 int func = (++it)->u.operand;
524 int argCount = (++it)->u.operand;
525 int registerOffset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000526 printLocationAndOp(out, exec, location, it, op);
527 out.printf("%s, %s, %d, %d", registerName(dst).data(), registerName(func).data(), argCount, registerOffset);
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000528 if (cacheDumpMode == DumpCaches) {
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000529 LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo;
530 if (callLinkInfo->lastSeenCallee) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000531 out.printf(
532 " llint(%p, exec %p)",
533 callLinkInfo->lastSeenCallee.get(),
534 callLinkInfo->lastSeenCallee->executable());
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000535 }
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000536#if ENABLE(JIT)
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000537 if (CallLinkInfo* info = map.get(CodeOrigin(location))) {
msaboff@apple.com203a56e2015-06-24 22:37:30 +0000538 JSFunction* target = info->lastSeenCallee();
fpizlo@apple.com5e3852d2012-05-24 00:05:21 +0000539 if (target)
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000540 out.printf(" jit(%p, exec %p)", target, target->executable());
fpizlo@apple.com5e3852d2012-05-24 00:05:21 +0000541 }
mark.lam@apple.com507b94e2015-04-17 00:25:14 +0000542
543 if (jitType() != JITCode::FTLJIT)
544 out.print(" status(", CallLinkStatus::computeFor(this, location, map), ")");
fpizlo@apple.comf7100b62014-03-24 17:29:51 +0000545#else
546 UNUSED_PARAM(map);
msaboff@apple.com95894332014-01-29 19:18:54 +0000547#endif
fpizlo@apple.comc6446112012-05-23 20:52:42 +0000548 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000549 ++it;
oliver@apple.com7ff89b12014-02-21 22:37:29 +0000550 ++it;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000551 dumpArrayProfiling(out, it, hasPrintedProfiling);
552 dumpValueProfiling(out, it, hasPrintedProfiling);
ggaren@apple.com6f82ad52012-01-12 01:00:58 +0000553}
554
msaboff@apple.comc5808642013-09-05 23:27:41 +0000555void CodeBlock::printPutByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op)
weinig@apple.com3412bb42008-09-01 21:22:54 +0000556{
557 int r0 = (++it)->u.operand;
558 int id0 = (++it)->u.operand;
559 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000560 printLocationAndOp(out, exec, location, it, op);
561 out.printf("%s, %s, %s", registerName(r0).data(), idName(id0, identifier(id0)).data(), registerName(r1).data());
oliver@apple.comef690aa2010-07-15 20:00:31 +0000562 it += 5;
weinig@apple.com3412bb42008-09-01 21:22:54 +0000563}
564
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000565void CodeBlock::dumpSource()
566{
567 dumpSource(WTF::dataFile());
568}
569
570void CodeBlock::dumpSource(PrintStream& out)
571{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000572 ScriptExecutable* executable = ownerScriptExecutable();
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000573 if (executable->isFunctionExecutable()) {
574 FunctionExecutable* functionExecutable = reinterpret_cast<FunctionExecutable*>(executable);
akling@apple.com73320982015-12-13 20:03:24 +0000575 StringView source = functionExecutable->source().provider()->getRange(
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000576 functionExecutable->parametersStartOffset(),
577 functionExecutable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
578
579 out.print("function ", inferredName(), source);
580 return;
581 }
akling@apple.com73320982015-12-13 20:03:24 +0000582 out.print(executable->source().view());
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000583}
584
585void CodeBlock::dumpBytecode()
586{
587 dumpBytecode(WTF::dataFile());
588}
589
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000590void CodeBlock::dumpBytecode(PrintStream& out)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000591{
fpizlo@apple.com1949f322012-11-22 00:46:57 +0000592 // We only use the ExecState* for things that don't actually lead to JS execution,
593 // like converting a JSString to a String. Hence the globalExec is appropriate.
594 ExecState* exec = m_globalObject->globalExec();
595
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000596 size_t instructionCount = 0;
weinig@apple.com0aaf82a2008-12-12 08:02:09 +0000597
fpizlo@apple.com9ac73f12011-11-10 04:37:32 +0000598 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 +0000599 ++instructionCount;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000600
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000601 out.print(*this);
602 out.printf(
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000603 ": %lu m_instructions; %lu bytes; %d parameter(s); %d callee register(s); %d variable(s)",
fpizlo@apple.comebe232e2012-02-27 02:07:34 +0000604 static_cast<unsigned long>(instructions().size()),
fpizlo@apple.com9ac73f12011-11-10 04:37:32 +0000605 static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000606 m_numParameters, m_numCalleeLocals, m_numVars);
msaboff@apple.comc5808642013-09-05 23:27:41 +0000607 out.printf("\n");
608
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000609 StubInfoMap stubInfos;
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000610 CallLinkInfoMap callLinkInfos;
msaboff@apple.com95894332014-01-29 19:18:54 +0000611 getStubInfoMap(stubInfos);
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000612 getCallLinkInfoMap(callLinkInfos);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000613
fpizlo@apple.com1949f322012-11-22 00:46:57 +0000614 const Instruction* begin = instructions().begin();
615 const Instruction* end = instructions().end();
616 for (const Instruction* it = begin; it != end; ++it)
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000617 dumpBytecode(out, exec, begin, it, stubInfos, callLinkInfos);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000618
oliver@apple.com9b652762013-08-12 22:39:13 +0000619 if (numberOfIdentifiers()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000620 out.printf("\nIdentifiers:\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000621 size_t i = 0;
622 do {
oliver@apple.com9b652762013-08-12 22:39:13 +0000623 out.printf(" id%u = %s\n", static_cast<unsigned>(i), identifier(i).string().utf8().data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000624 ++i;
oliver@apple.com9b652762013-08-12 22:39:13 +0000625 } while (i != numberOfIdentifiers());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000626 }
627
weinig@apple.comcb26d812008-12-06 22:01:05 +0000628 if (!m_constantRegisters.isEmpty()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000629 out.printf("\nConstants:\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000630 size_t i = 0;
631 do {
mark.lam@apple.com61ba1f32015-03-10 19:29:13 +0000632 const char* sourceCodeRepresentationDescription = nullptr;
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000633 switch (m_constantsSourceCodeRepresentation[i]) {
634 case SourceCodeRepresentation::Double:
635 sourceCodeRepresentationDescription = ": in source as double";
636 break;
637 case SourceCodeRepresentation::Integer:
638 sourceCodeRepresentationDescription = ": in source as integer";
639 break;
640 case SourceCodeRepresentation::Other:
641 sourceCodeRepresentationDescription = "";
642 break;
643 }
644 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 +0000645 ++i;
weinig@apple.comcb26d812008-12-06 22:01:05 +0000646 } while (i < m_constantRegisters.size());
cwzwarich@webkit.org300bb752008-08-06 10:37:34 +0000647 }
648
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000649 if (size_t count = m_unlinkedCode->numberOfRegExps()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000650 out.printf("\nm_regexps:\n");
oliver@apple.com22d55c32010-05-10 01:41:07 +0000651 size_t i = 0;
652 do {
oliver@apple.com02039462013-07-25 03:59:29 +0000653 out.printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).data());
oliver@apple.com22d55c32010-05-10 01:41:07 +0000654 ++i;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000655 } while (i < count);
oliver@apple.com22d55c32010-05-10 01:41:07 +0000656 }
657
fpizlo@apple.com21014282016-01-08 21:42:23 +0000658 dumpExceptionHandlers(out);
oliver@apple.com8007f462008-07-24 00:49:46 +0000659
oliver@apple.coma14cea52013-07-25 04:03:23 +0000660 if (m_rareData && !m_rareData->m_switchJumpTables.isEmpty()) {
661 out.printf("Switch Jump Tables:\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000662 unsigned i = 0;
663 do {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000664 out.printf(" %1d = {\n", i);
oliver@apple.com8007f462008-07-24 00:49:46 +0000665 int entry = 0;
oliver@apple.coma14cea52013-07-25 04:03:23 +0000666 Vector<int32_t>::const_iterator end = m_rareData->m_switchJumpTables[i].branchOffsets.end();
667 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 +0000668 if (!*iter)
669 continue;
oliver@apple.coma14cea52013-07-25 04:03:23 +0000670 out.printf("\t\t%4d => %04d\n", entry + m_rareData->m_switchJumpTables[i].min, *iter);
weinig@apple.com3412bb42008-09-01 21:22:54 +0000671 }
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000672 out.printf(" }\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000673 ++i;
oliver@apple.coma14cea52013-07-25 04:03:23 +0000674 } while (i < m_rareData->m_switchJumpTables.size());
oliver@apple.com8007f462008-07-24 00:49:46 +0000675 }
676
weinig@apple.com4557e842008-12-09 01:06:14 +0000677 if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000678 out.printf("\nString Switch Jump Tables:\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000679 unsigned i = 0;
680 do {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000681 out.printf(" %1d = {\n", i);
weinig@apple.com4557e842008-12-09 01:06:14 +0000682 StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
683 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
msaboff@apple.comc2d94712014-04-29 01:36:14 +0000684 out.printf("\t\t\"%s\" => %04d\n", iter->key->utf8().data(), iter->value.branchOffset);
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000685 out.printf(" }\n");
oliver@apple.com8007f462008-07-24 00:49:46 +0000686 ++i;
weinig@apple.com4557e842008-12-09 01:06:14 +0000687 } while (i < m_rareData->m_stringSwitchJumpTables.size());
oliver@apple.com8007f462008-07-24 00:49:46 +0000688 }
689
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000690 if (m_rareData && !m_rareData->m_liveCalleeLocalsAtYield.isEmpty()) {
691 out.printf("\nLive Callee Locals:\n");
692 unsigned i = 0;
693 do {
694 const FastBitVector& liveness = m_rareData->m_liveCalleeLocalsAtYield[i];
695 out.printf(" live%1u = ", i);
696 liveness.dump(out);
697 out.printf("\n");
698 ++i;
699 } while (i < m_rareData->m_liveCalleeLocalsAtYield.size());
700 }
701
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000702 out.printf("\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000703}
704
fpizlo@apple.com21014282016-01-08 21:42:23 +0000705void CodeBlock::dumpExceptionHandlers(PrintStream& out)
706{
707 if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
708 out.printf("\nException Handlers:\n");
709 unsigned i = 0;
710 do {
711 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
712 out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] } %s\n",
713 i + 1, handler.start, handler.end, handler.target, handler.typeName());
714 ++i;
715 } while (i < m_rareData->m_exceptionHandlers.size());
716 }
717}
718
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000719void CodeBlock::beginDumpProfiling(PrintStream& out, bool& hasPrintedProfiling)
720{
721 if (hasPrintedProfiling) {
722 out.print("; ");
723 return;
724 }
725
726 out.print(" ");
727 hasPrintedProfiling = true;
728}
729
730void CodeBlock::dumpValueProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000731{
oliver@apple.comd2056662013-07-25 04:00:37 +0000732 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000733
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000734 ++it;
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000735 CString description = it->u.profile->briefDescription(locker);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000736 if (!description.length())
737 return;
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000738 beginDumpProfiling(out, hasPrintedProfiling);
739 out.print(description);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000740}
741
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000742void CodeBlock::dumpArrayProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling)
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000743{
oliver@apple.comd2056662013-07-25 04:00:37 +0000744 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000745
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000746 ++it;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000747 if (!it->u.arrayProfile)
748 return;
oliver@apple.comc14eb7d2013-07-25 03:58:47 +0000749 CString description = it->u.arrayProfile->briefDescription(locker, this);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000750 if (!description.length())
751 return;
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000752 beginDumpProfiling(out, hasPrintedProfiling);
753 out.print(description);
fpizlo@apple.com77ef0e32012-12-12 00:21:43 +0000754}
755
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000756void CodeBlock::dumpRareCaseProfile(PrintStream& out, const char* name, RareCaseProfile* profile, bool& hasPrintedProfiling)
757{
758 if (!profile || !profile->m_counter)
759 return;
760
761 beginDumpProfiling(out, hasPrintedProfiling);
762 out.print(name, profile->m_counter);
763}
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000764
mark.lam@apple.combad59ea2015-12-18 22:03:30 +0000765void CodeBlock::dumpResultProfile(PrintStream& out, ResultProfile* profile, bool& hasPrintedProfiling)
766{
767 if (!profile)
768 return;
769
770 beginDumpProfiling(out, hasPrintedProfiling);
771 out.print("results: ", *profile);
772}
773
fpizlo@apple.com12803e22014-02-02 06:38:51 +0000774void CodeBlock::printLocationAndOp(PrintStream& out, ExecState*, int location, const Instruction*&, const char* op)
775{
776 out.printf("[%4d] %-17s ", location, op);
777}
778
779void CodeBlock::printLocationOpAndRegisterOperand(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, int operand)
780{
781 printLocationAndOp(out, exec, location, it, op);
782 out.printf("%s", registerName(operand).data());
783}
784
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000785void CodeBlock::dumpBytecode(
786 PrintStream& out, ExecState* exec, const Instruction* begin, const Instruction*& it,
787 const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000788{
789 int location = it - begin;
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +0000790 bool hasPrintedProfiling = false;
oliver@apple.com177c2b92014-03-28 01:10:25 +0000791 OpcodeID opcode = exec->interpreter()->getOpcodeID(it->u.opcode);
792 switch (opcode) {
mjs@apple.com8b246d62008-10-04 07:15:33 +0000793 case op_enter: {
msaboff@apple.comc5808642013-09-05 23:27:41 +0000794 printLocationAndOp(out, exec, location, it, "enter");
oliver@apple.comecfd2242008-09-20 03:00:43 +0000795 break;
796 }
msaboff@apple.com8b6b3412014-11-04 03:36:28 +0000797 case op_get_scope: {
798 int r0 = (++it)->u.operand;
799 printLocationOpAndRegisterOperand(out, exec, location, it, "get_scope", r0);
800 break;
801 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000802 case op_create_direct_arguments: {
ggaren@apple.com83ce11c2010-05-19 05:10:11 +0000803 int r0 = (++it)->u.operand;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000804 printLocationAndOp(out, exec, location, it, "create_direct_arguments");
805 out.printf("%s", registerName(r0).data());
cwzwarich@webkit.org9e464ca2008-09-29 03:04:08 +0000806 break;
807 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000808 case op_create_scoped_arguments: {
ggaren@apple.com83ce11c2010-05-19 05:10:11 +0000809 int r0 = (++it)->u.operand;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000810 int r1 = (++it)->u.operand;
811 printLocationAndOp(out, exec, location, it, "create_scoped_arguments");
812 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
813 break;
814 }
keith_miller@apple.com26367392016-03-14 20:55:15 +0000815 case op_create_cloned_arguments: {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000816 int r0 = (++it)->u.operand;
keith_miller@apple.com26367392016-03-14 20:55:15 +0000817 printLocationAndOp(out, exec, location, it, "create_cloned_arguments");
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000818 out.printf("%s", registerName(r0).data());
oliver@apple.combe38ac42009-05-12 08:58:56 +0000819 break;
820 }
sbarati@apple.comc0722da2015-11-20 02:37:47 +0000821 case op_copy_rest: {
822 int r0 = (++it)->u.operand;
sbarati@apple.com855d5602015-11-30 20:36:54 +0000823 int r1 = (++it)->u.operand;
824 unsigned argumentOffset = (++it)->u.unsignedValue;
sbarati@apple.comc0722da2015-11-20 02:37:47 +0000825 printLocationAndOp(out, exec, location, it, "copy_rest");
sbarati@apple.com855d5602015-11-30 20:36:54 +0000826 out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data());
827 out.printf("ArgumentsOffset: %u", argumentOffset);
828 break;
829 }
830 case op_get_rest_length: {
831 int r0 = (++it)->u.operand;
832 printLocationAndOp(out, exec, location, it, "get_rest_length");
sbarati@apple.comc0722da2015-11-20 02:37:47 +0000833 out.printf("%s, ", registerName(r0).data());
834 unsigned argumentOffset = (++it)->u.unsignedValue;
835 out.printf("ArgumentsOffset: %u", argumentOffset);
836 break;
837 }
barraclough@apple.comfd8c28a2010-05-25 03:04:43 +0000838 case op_create_this: {
839 int r0 = (++it)->u.operand;
fpizlo@apple.comc2c67632012-11-17 08:37:14 +0000840 int r1 = (++it)->u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000841 unsigned inferredInlineCapacity = (++it)->u.operand;
rniwa@webkit.org1b971d72015-05-14 04:19:18 +0000842 unsigned cachedFunction = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000843 printLocationAndOp(out, exec, location, it, "create_this");
rniwa@webkit.org1b971d72015-05-14 04:19:18 +0000844 out.printf("%s, %s, %u, %u", registerName(r0).data(), registerName(r1).data(), inferredInlineCapacity, cachedFunction);
barraclough@apple.comfd8c28a2010-05-25 03:04:43 +0000845 break;
846 }
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000847 case op_to_this: {
mjs@apple.com8b246d62008-10-04 07:15:33 +0000848 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000849 printLocationOpAndRegisterOperand(out, exec, location, it, "to_this", r0);
fpizlo@apple.com12803e22014-02-02 06:38:51 +0000850 Structure* structure = (++it)->u.structure.get();
851 if (structure)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000852 out.print(", cache(struct = ", RawPointer(structure), ")");
853 out.print(", ", (++it)->u.toThisStatus);
mjs@apple.com8b246d62008-10-04 07:15:33 +0000854 break;
855 }
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000856 case op_check_tdz: {
857 int r0 = (++it)->u.operand;
858 printLocationOpAndRegisterOperand(out, exec, location, it, "op_check_tdz", r0);
859 break;
860 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000861 case op_new_object: {
862 int r0 = (++it)->u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000863 unsigned inferredInlineCapacity = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000864 printLocationAndOp(out, exec, location, it, "new_object");
865 out.printf("%s, %u", registerName(r0).data(), inferredInlineCapacity);
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000866 ++it; // Skip object allocation profile.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000867 break;
868 }
869 case op_new_array: {
darin@apple.com9ce79022008-06-28 15:50:49 +0000870 int dst = (++it)->u.operand;
871 int argv = (++it)->u.operand;
872 int argc = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000873 printLocationAndOp(out, exec, location, it, "new_array");
874 out.printf("%s, %s, %d", registerName(dst).data(), registerName(argv).data(), argc);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000875 ++it; // Skip array allocation profile.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000876 break;
877 }
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000878 case op_new_array_with_size: {
879 int dst = (++it)->u.operand;
880 int length = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000881 printLocationAndOp(out, exec, location, it, "new_array_with_size");
882 out.printf("%s, %s", registerName(dst).data(), registerName(length).data());
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000883 ++it; // Skip array allocation profile.
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000884 break;
885 }
oliver@apple.coma991d692011-06-14 23:39:25 +0000886 case op_new_array_buffer: {
887 int dst = (++it)->u.operand;
888 int argv = (++it)->u.operand;
889 int argc = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000890 printLocationAndOp(out, exec, location, it, "new_array_buffer");
891 out.printf("%s, %d, %d", registerName(dst).data(), argv, argc);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000892 ++it; // Skip array allocation profile.
oliver@apple.coma991d692011-06-14 23:39:25 +0000893 break;
894 }
oliver@apple.com22d55c32010-05-10 01:41:07 +0000895 case op_new_regexp: {
896 int r0 = (++it)->u.operand;
897 int re0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000898 printLocationAndOp(out, exec, location, it, "new_regexp");
899 out.printf("%s, ", registerName(r0).data());
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000900 if (r0 >=0 && r0 < (int)m_unlinkedCode->numberOfRegExps())
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000901 out.printf("%s", regexpName(re0, regexp(re0)).data());
fpizlo@apple.com68186e12011-08-17 20:54:32 +0000902 else
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000903 out.printf("bad_regexp(%d)", re0);
oliver@apple.com22d55c32010-05-10 01:41:07 +0000904 break;
905 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000906 case op_mov: {
907 int r0 = (++it)->u.operand;
908 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +0000909 printLocationAndOp(out, exec, location, it, "mov");
910 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000911 break;
912 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000913 case op_profile_type: {
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000914 int r0 = (++it)->u.operand;
915 ++it;
916 ++it;
commit-queue@webkit.org0163f122014-08-21 02:29:47 +0000917 ++it;
918 ++it;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000919 printLocationAndOp(out, exec, location, it, "op_profile_type");
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000920 out.printf("%s", registerName(r0).data());
921 break;
922 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +0000923 case op_profile_control_flow: {
924 BasicBlockLocation* basicBlockLocation = (++it)->u.basicBlockLocation;
925 printLocationAndOp(out, exec, location, it, "profile_control_flow");
926 out.printf("[%d, %d]", basicBlockLocation->startOffset(), basicBlockLocation->endOffset());
927 break;
928 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000929 case op_not: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000930 printUnaryOp(out, exec, location, it, "not");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000931 break;
932 }
933 case op_eq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000934 printBinaryOp(out, exec, location, it, "eq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000935 break;
936 }
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000937 case op_eq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000938 printUnaryOp(out, exec, location, it, "eq_null");
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000939 break;
940 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000941 case op_neq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000942 printBinaryOp(out, exec, location, it, "neq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000943 break;
944 }
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000945 case op_neq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000946 printUnaryOp(out, exec, location, it, "neq_null");
ggaren@apple.comf15b18802008-09-03 02:58:14 +0000947 break;
948 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000949 case op_stricteq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000950 printBinaryOp(out, exec, location, it, "stricteq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000951 break;
952 }
953 case op_nstricteq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000954 printBinaryOp(out, exec, location, it, "nstricteq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000955 break;
956 }
957 case op_less: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000958 printBinaryOp(out, exec, location, it, "less");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000959 break;
960 }
961 case op_lesseq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000962 printBinaryOp(out, exec, location, it, "lesseq");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000963 break;
964 }
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +0000965 case op_greater: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000966 printBinaryOp(out, exec, location, it, "greater");
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +0000967 break;
968 }
969 case op_greatereq: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000970 printBinaryOp(out, exec, location, it, "greatereq");
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +0000971 break;
972 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000973 case op_inc: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000974 int r0 = (++it)->u.operand;
fpizlo@apple.com9bca4b82013-11-11 21:46:37 +0000975 printLocationOpAndRegisterOperand(out, exec, location, it, "inc", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000976 break;
977 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000978 case op_dec: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000979 int r0 = (++it)->u.operand;
fpizlo@apple.com9bca4b82013-11-11 21:46:37 +0000980 printLocationOpAndRegisterOperand(out, exec, location, it, "dec", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000981 break;
982 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000983 case op_to_number: {
984 printUnaryOp(out, exec, location, it, "to_number");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000985 break;
986 }
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000987 case op_to_string: {
988 printUnaryOp(out, exec, location, it, "to_string");
989 break;
990 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000991 case op_negate: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000992 printUnaryOp(out, exec, location, it, "negate");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000993 break;
994 }
995 case op_add: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000996 printBinaryOp(out, exec, location, it, "add");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000997 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000998 break;
999 }
1000 case op_mul: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001001 printBinaryOp(out, exec, location, it, "mul");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +00001002 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001003 break;
1004 }
1005 case op_div: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001006 printBinaryOp(out, exec, location, it, "div");
ggaren@apple.com540d71a62009-07-30 20:57:44 +00001007 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001008 break;
1009 }
1010 case op_mod: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001011 printBinaryOp(out, exec, location, it, "mod");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001012 break;
1013 }
1014 case op_sub: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001015 printBinaryOp(out, exec, location, it, "sub");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +00001016 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001017 break;
1018 }
1019 case op_lshift: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001020 printBinaryOp(out, exec, location, it, "lshift");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001021 break;
1022 }
1023 case op_rshift: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001024 printBinaryOp(out, exec, location, it, "rshift");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001025 break;
1026 }
1027 case op_urshift: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001028 printBinaryOp(out, exec, location, it, "urshift");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001029 break;
1030 }
1031 case op_bitand: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001032 printBinaryOp(out, exec, location, it, "bitand");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +00001033 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001034 break;
1035 }
1036 case op_bitxor: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001037 printBinaryOp(out, exec, location, it, "bitxor");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +00001038 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001039 break;
1040 }
1041 case op_bitor: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001042 printBinaryOp(out, exec, location, it, "bitor");
barraclough@apple.comb8b15e22008-09-27 01:44:15 +00001043 ++it;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001044 break;
1045 }
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001046 case op_overrides_has_instance: {
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001047 int r0 = (++it)->u.operand;
1048 int r1 = (++it)->u.operand;
1049 int r2 = (++it)->u.operand;
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001050 printLocationAndOp(out, exec, location, it, "overrides_has_instance");
1051 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001052 break;
1053 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001054 case op_instanceof: {
mjs@apple.com988df6c2008-09-15 02:13:10 +00001055 int r0 = (++it)->u.operand;
1056 int r1 = (++it)->u.operand;
1057 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001058 printLocationAndOp(out, exec, location, it, "instanceof");
1059 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001060 break;
1061 }
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001062 case op_instanceof_custom: {
1063 int r0 = (++it)->u.operand;
1064 int r1 = (++it)->u.operand;
1065 int r2 = (++it)->u.operand;
1066 int r3 = (++it)->u.operand;
1067 printLocationAndOp(out, exec, location, it, "instanceof_custom");
1068 out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
1069 break;
1070 }
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001071 case op_unsigned: {
1072 printUnaryOp(out, exec, location, it, "unsigned");
1073 break;
1074 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001075 case op_typeof: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001076 printUnaryOp(out, exec, location, it, "typeof");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001077 break;
1078 }
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00001079 case op_is_empty: {
1080 printUnaryOp(out, exec, location, it, "is_empty");
1081 break;
1082 }
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001083 case op_is_undefined: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001084 printUnaryOp(out, exec, location, it, "is_undefined");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001085 break;
1086 }
1087 case op_is_boolean: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001088 printUnaryOp(out, exec, location, it, "is_boolean");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001089 break;
1090 }
1091 case op_is_number: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001092 printUnaryOp(out, exec, location, it, "is_number");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001093 break;
1094 }
1095 case op_is_string: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001096 printUnaryOp(out, exec, location, it, "is_string");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001097 break;
1098 }
1099 case op_is_object: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001100 printUnaryOp(out, exec, location, it, "is_object");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001101 break;
1102 }
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00001103 case op_is_object_or_null: {
1104 printUnaryOp(out, exec, location, it, "is_object_or_null");
1105 break;
1106 }
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001107 case op_is_function: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001108 printUnaryOp(out, exec, location, it, "is_function");
cwzwarich@webkit.org32346622008-09-15 00:26:08 +00001109 break;
1110 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001111 case op_in: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001112 printBinaryOp(out, exec, location, it, "in");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001113 break;
1114 }
keith_miller@apple.com8844d302016-04-07 19:38:00 +00001115 case op_try_get_by_id: {
1116 int r0 = (++it)->u.operand;
1117 int r1 = (++it)->u.operand;
1118 int id0 = (++it)->u.operand;
1119 printLocationAndOp(out, exec, location, it, "try_get_by_id");
1120 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
1121 break;
1122 }
fpizlo@apple.comd52a7942012-05-21 22:32:40 +00001123 case op_get_by_id:
keith_miller@apple.com8350adf2016-05-24 23:49:57 +00001124 case op_get_by_id_proto_load:
keith_miller@apple.com785c6512016-05-27 18:36:30 +00001125 case op_get_by_id_unset:
fpizlo@apple.com970d8a92014-02-14 05:37:38 +00001126 case op_get_array_length: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001127 printGetByIdOp(out, exec, location, it);
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001128 printGetByIdCacheStatus(out, exec, location, stubInfos);
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001129 dumpValueProfiling(out, it, hasPrintedProfiling);
ggaren@apple.combc363092008-09-03 05:04:39 +00001130 break;
1131 }
sbarati@apple.com23315d62016-05-09 20:17:23 +00001132 case op_get_by_id_with_this: {
1133 printLocationAndOp(out, exec, location, it, "get_by_id_with_this");
1134 int r0 = (++it)->u.operand;
1135 int r1 = (++it)->u.operand;
1136 int r2 = (++it)->u.operand;
1137 int id0 = (++it)->u.operand;
1138 out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), idName(id0, identifier(id0)).data());
1139 break;
1140 }
1141 case op_get_by_val_with_this: {
1142 int r0 = (++it)->u.operand;
1143 int r1 = (++it)->u.operand;
1144 int r2 = (++it)->u.operand;
1145 int r3 = (++it)->u.operand;
1146 printLocationAndOp(out, exec, location, it, "get_by_val_with_this");
1147 out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
1148 break;
1149 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001150 case op_put_by_id: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001151 printPutByIdOp(out, exec, location, it, "put_by_id");
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001152 printPutByIdCacheStatus(out, location, stubInfos);
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +00001153 break;
1154 }
sbarati@apple.com23315d62016-05-09 20:17:23 +00001155 case op_put_by_id_with_this: {
1156 int r0 = (++it)->u.operand;
1157 int r1 = (++it)->u.operand;
1158 int id0 = (++it)->u.operand;
1159 int r2 = (++it)->u.operand;
1160 printLocationAndOp(out, exec, location, it, "put_by_id_with_this");
1161 out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data(), registerName(r2).data());
1162 break;
1163 }
1164 case op_put_by_val_with_this: {
1165 int r0 = (++it)->u.operand;
1166 int r1 = (++it)->u.operand;
1167 int r2 = (++it)->u.operand;
1168 int r3 = (++it)->u.operand;
1169 printLocationAndOp(out, exec, location, it, "put_by_val_with_this");
1170 out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
1171 break;
1172 }
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001173 case op_put_getter_by_id: {
1174 int r0 = (++it)->u.operand;
1175 int id0 = (++it)->u.operand;
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001176 int n0 = (++it)->u.operand;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001177 int r1 = (++it)->u.operand;
1178 printLocationAndOp(out, exec, location, it, "put_getter_by_id");
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001179 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 +00001180 break;
1181 }
1182 case op_put_setter_by_id: {
1183 int r0 = (++it)->u.operand;
1184 int id0 = (++it)->u.operand;
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001185 int n0 = (++it)->u.operand;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +00001186 int r1 = (++it)->u.operand;
1187 printLocationAndOp(out, exec, location, it, "put_setter_by_id");
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001188 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 +00001189 break;
1190 }
utatane.tea@gmail.com059a71f2015-11-02 18:32:55 +00001191 case op_put_getter_setter_by_id: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001192 int r0 = (++it)->u.operand;
1193 int id0 = (++it)->u.operand;
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001194 int n0 = (++it)->u.operand;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001195 int r1 = (++it)->u.operand;
barraclough@apple.com09a55682012-01-30 18:28:39 +00001196 int r2 = (++it)->u.operand;
utatane.tea@gmail.com059a71f2015-11-02 18:32:55 +00001197 printLocationAndOp(out, exec, location, it, "put_getter_setter_by_id");
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +00001198 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 +00001199 break;
1200 }
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +00001201 case op_put_getter_by_val: {
1202 int r0 = (++it)->u.operand;
1203 int r1 = (++it)->u.operand;
1204 int n0 = (++it)->u.operand;
1205 int r2 = (++it)->u.operand;
1206 printLocationAndOp(out, exec, location, it, "put_getter_by_val");
1207 out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
1208 break;
1209 }
1210 case op_put_setter_by_val: {
1211 int r0 = (++it)->u.operand;
1212 int r1 = (++it)->u.operand;
1213 int n0 = (++it)->u.operand;
1214 int r2 = (++it)->u.operand;
1215 printLocationAndOp(out, exec, location, it, "put_setter_by_val");
1216 out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
1217 break;
1218 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001219 case op_del_by_id: {
1220 int r0 = (++it)->u.operand;
1221 int r1 = (++it)->u.operand;
1222 int id0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001223 printLocationAndOp(out, exec, location, it, "del_by_id");
1224 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001225 break;
1226 }
1227 case op_get_by_val: {
1228 int r0 = (++it)->u.operand;
1229 int r1 = (++it)->u.operand;
1230 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001231 printLocationAndOp(out, exec, location, it, "get_by_val");
1232 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001233 dumpArrayProfiling(out, it, hasPrintedProfiling);
1234 dumpValueProfiling(out, it, hasPrintedProfiling);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001235 break;
1236 }
1237 case op_put_by_val: {
1238 int r0 = (++it)->u.operand;
1239 int r1 = (++it)->u.operand;
1240 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001241 printLocationAndOp(out, exec, location, it, "put_by_val");
1242 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001243 dumpArrayProfiling(out, it, hasPrintedProfiling);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001244 break;
1245 }
oliver@apple.come050d642013-10-19 00:09:28 +00001246 case op_put_by_val_direct: {
1247 int r0 = (++it)->u.operand;
1248 int r1 = (++it)->u.operand;
1249 int r2 = (++it)->u.operand;
1250 printLocationAndOp(out, exec, location, it, "put_by_val_direct");
1251 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
1252 dumpArrayProfiling(out, it, hasPrintedProfiling);
1253 break;
1254 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001255 case op_del_by_val: {
1256 int r0 = (++it)->u.operand;
1257 int r1 = (++it)->u.operand;
1258 int r2 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001259 printLocationAndOp(out, exec, location, it, "del_by_val");
1260 out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001261 break;
1262 }
1263 case op_put_by_index: {
1264 int r0 = (++it)->u.operand;
1265 unsigned n0 = (++it)->u.operand;
1266 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001267 printLocationAndOp(out, exec, location, it, "put_by_index");
1268 out.printf("%s, %u, %s", registerName(r0).data(), n0, registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001269 break;
1270 }
1271 case op_jmp: {
1272 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001273 printLocationAndOp(out, exec, location, it, "jmp");
1274 out.printf("%d(->%d)", offset, location + offset);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001275 break;
1276 }
1277 case op_jtrue: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001278 printConditionalJump(out, exec, begin, it, location, "jtrue");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001279 break;
1280 }
1281 case op_jfalse: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001282 printConditionalJump(out, exec, begin, it, location, "jfalse");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001283 break;
1284 }
cwzwarich@webkit.orgb8b30242008-10-22 21:06:30 +00001285 case op_jeq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001286 printConditionalJump(out, exec, begin, it, location, "jeq_null");
cwzwarich@webkit.orgb8b30242008-10-22 21:06:30 +00001287 break;
1288 }
1289 case op_jneq_null: {
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +00001290 printConditionalJump(out, exec, begin, it, location, "jneq_null");
cwzwarich@webkit.orgb8b30242008-10-22 21:06:30 +00001291 break;
1292 }
oliver@apple.com6c106002009-03-28 03:50:39 +00001293 case op_jneq_ptr: {
cwzwarich@webkit.org7b04fef2008-06-30 06:17:01 +00001294 int r0 = (++it)->u.operand;
fpizlo@apple.com4500e352012-10-17 21:39:11 +00001295 Special::Pointer pointer = (++it)->u.specialPointer;
cwzwarich@webkit.org7b04fef2008-06-30 06:17:01 +00001296 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001297 printLocationAndOp(out, exec, location, it, "jneq_ptr");
1298 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 +00001299 break;
1300 }
mjs@apple.coma46c49c2009-12-06 09:42:03 +00001301 case op_jless: {
1302 int r0 = (++it)->u.operand;
1303 int r1 = (++it)->u.operand;
1304 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001305 printLocationAndOp(out, exec, location, it, "jless");
1306 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
mjs@apple.coma46c49c2009-12-06 09:42:03 +00001307 break;
1308 }
oliver@apple.com5230bd32010-05-06 19:39:54 +00001309 case op_jlesseq: {
1310 int r0 = (++it)->u.operand;
1311 int r1 = (++it)->u.operand;
1312 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001313 printLocationAndOp(out, exec, location, it, "jlesseq");
1314 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
oliver@apple.com5230bd32010-05-06 19:39:54 +00001315 break;
1316 }
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001317 case op_jgreater: {
1318 int r0 = (++it)->u.operand;
1319 int r1 = (++it)->u.operand;
1320 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001321 printLocationAndOp(out, exec, location, it, "jgreater");
1322 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001323 break;
1324 }
1325 case op_jgreatereq: {
1326 int r0 = (++it)->u.operand;
1327 int r1 = (++it)->u.operand;
1328 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001329 printLocationAndOp(out, exec, location, it, "jgreatereq");
1330 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001331 break;
1332 }
1333 case op_jnless: {
1334 int r0 = (++it)->u.operand;
1335 int r1 = (++it)->u.operand;
1336 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001337 printLocationAndOp(out, exec, location, it, "jnless");
1338 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001339 break;
1340 }
1341 case op_jnlesseq: {
1342 int r0 = (++it)->u.operand;
1343 int r1 = (++it)->u.operand;
1344 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001345 printLocationAndOp(out, exec, location, it, "jnlesseq");
1346 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001347 break;
1348 }
1349 case op_jngreater: {
1350 int r0 = (++it)->u.operand;
1351 int r1 = (++it)->u.operand;
1352 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001353 printLocationAndOp(out, exec, location, it, "jngreater");
1354 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001355 break;
1356 }
1357 case op_jngreatereq: {
1358 int r0 = (++it)->u.operand;
1359 int r1 = (++it)->u.operand;
1360 int offset = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001361 printLocationAndOp(out, exec, location, it, "jngreatereq");
1362 out.printf("%s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), offset, location + offset);
barraclough@apple.com57b4bdb82011-07-04 19:26:05 +00001363 break;
1364 }
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001365 case op_loop_hint: {
msaboff@apple.comc5808642013-09-05 23:27:41 +00001366 printLocationAndOp(out, exec, location, it, "loop_hint");
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001367 break;
1368 }
sbarati@apple.com390337b2015-12-07 22:03:48 +00001369 case op_watchdog: {
1370 printLocationAndOp(out, exec, location, it, "watchdog");
1371 break;
1372 }
fpizlo@apple.com39303e02016-04-05 22:17:35 +00001373 case op_log_shadow_chicken_prologue: {
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00001374 int r0 = (++it)->u.operand;
fpizlo@apple.com39303e02016-04-05 22:17:35 +00001375 printLocationAndOp(out, exec, location, it, "log_shadow_chicken_prologue");
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00001376 out.printf("%s", registerName(r0).data());
fpizlo@apple.com39303e02016-04-05 22:17:35 +00001377 break;
1378 }
1379 case op_log_shadow_chicken_tail: {
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00001380 int r0 = (++it)->u.operand;
1381 int r1 = (++it)->u.operand;
fpizlo@apple.com39303e02016-04-05 22:17:35 +00001382 printLocationAndOp(out, exec, location, it, "log_shadow_chicken_tail");
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00001383 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
fpizlo@apple.com39303e02016-04-05 22:17:35 +00001384 break;
1385 }
oliver@apple.com8007f462008-07-24 00:49:46 +00001386 case op_switch_imm: {
1387 int tableIndex = (++it)->u.operand;
1388 int defaultTarget = (++it)->u.operand;
1389 int scrutineeRegister = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001390 printLocationAndOp(out, exec, location, it, "switch_imm");
1391 out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
oliver@apple.com8007f462008-07-24 00:49:46 +00001392 break;
1393 }
1394 case op_switch_char: {
1395 int tableIndex = (++it)->u.operand;
1396 int defaultTarget = (++it)->u.operand;
1397 int scrutineeRegister = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001398 printLocationAndOp(out, exec, location, it, "switch_char");
1399 out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
oliver@apple.com8007f462008-07-24 00:49:46 +00001400 break;
1401 }
1402 case op_switch_string: {
1403 int tableIndex = (++it)->u.operand;
1404 int defaultTarget = (++it)->u.operand;
1405 int scrutineeRegister = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001406 printLocationAndOp(out, exec, location, it, "switch_string");
1407 out.printf("%d, %d(->%d), %s", tableIndex, defaultTarget, location + defaultTarget, registerName(scrutineeRegister).data());
oliver@apple.com8007f462008-07-24 00:49:46 +00001408 break;
1409 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001410 case op_new_func: {
1411 int r0 = (++it)->u.operand;
msaboff@apple.comea77cd02014-11-14 01:07:48 +00001412 int r1 = (++it)->u.operand;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001413 int f0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001414 printLocationAndOp(out, exec, location, it, "new_func");
commit-queue@webkit.org9c3b1a52016-03-09 22:34:08 +00001415 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001416 break;
1417 }
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001418 case op_new_generator_func: {
1419 int r0 = (++it)->u.operand;
1420 int r1 = (++it)->u.operand;
1421 int f0 = (++it)->u.operand;
1422 printLocationAndOp(out, exec, location, it, "new_generator_func");
commit-queue@webkit.org9c3b1a52016-03-09 22:34:08 +00001423 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001424 break;
1425 }
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00001426 case op_new_arrow_func_exp: {
1427 int r0 = (++it)->u.operand;
1428 int r1 = (++it)->u.operand;
1429 int f0 = (++it)->u.operand;
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00001430 printLocationAndOp(out, exec, location, it, "op_new_arrow_func_exp");
commit-queue@webkit.org9c3b1a52016-03-09 22:34:08 +00001431 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00001432 break;
1433 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001434 case op_new_func_exp: {
1435 int r0 = (++it)->u.operand;
msaboff@apple.comea77cd02014-11-14 01:07:48 +00001436 int r1 = (++it)->u.operand;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001437 int f0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001438 printLocationAndOp(out, exec, location, it, "new_func_exp");
commit-queue@webkit.org9c3b1a52016-03-09 22:34:08 +00001439 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001440 break;
1441 }
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001442 case op_new_generator_func_exp: {
1443 int r0 = (++it)->u.operand;
1444 int r1 = (++it)->u.operand;
1445 int f0 = (++it)->u.operand;
1446 printLocationAndOp(out, exec, location, it, "new_generator_func_exp");
commit-queue@webkit.org9c3b1a52016-03-09 22:34:08 +00001447 out.printf("%s, %s, f%d", registerName(r0).data(), registerName(r1).data(), f0);
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001448 break;
1449 }
mark.lam@apple.com47c2f142016-03-16 18:16:32 +00001450 case op_set_function_name: {
1451 int funcReg = (++it)->u.operand;
1452 int nameReg = (++it)->u.operand;
1453 printLocationAndOp(out, exec, location, it, "set_function_name");
1454 out.printf("%s, %s", registerName(funcReg).data(), registerName(nameReg).data());
1455 break;
1456 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001457 case op_call: {
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001458 printCallOp(out, exec, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001459 break;
1460 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001461 case op_tail_call: {
1462 printCallOp(out, exec, location, it, "tail_call", DumpCaches, hasPrintedProfiling, callLinkInfos);
1463 break;
1464 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001465 case op_call_eval: {
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001466 printCallOp(out, exec, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001467 break;
1468 }
oliver@apple.com177c2b92014-03-28 01:10:25 +00001469
1470 case op_construct_varargs:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001471 case op_call_varargs:
1472 case op_tail_call_varargs: {
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001473 int result = (++it)->u.operand;
ggaren@apple.com539d1bb2011-11-14 19:21:40 +00001474 int callee = (++it)->u.operand;
1475 int thisValue = (++it)->u.operand;
1476 int arguments = (++it)->u.operand;
1477 int firstFreeRegister = (++it)->u.operand;
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001478 int varArgOffset = (++it)->u.operand;
oliver@apple.comdc48dc32013-07-25 04:01:42 +00001479 ++it;
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00001480 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 +00001481 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 +00001482 dumpValueProfiling(out, it, hasPrintedProfiling);
oliver@apple.com65e286e2009-04-08 23:08:28 +00001483 break;
1484 }
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001485
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001486 case op_ret: {
1487 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001488 printLocationOpAndRegisterOperand(out, exec, location, it, "ret", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001489 break;
1490 }
1491 case op_construct: {
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001492 printCallOp(out, exec, location, it, "construct", DumpCaches, hasPrintedProfiling, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001493 break;
1494 }
barraclough@apple.com14dc4e12009-05-07 00:06:07 +00001495 case op_strcat: {
1496 int r0 = (++it)->u.operand;
1497 int r1 = (++it)->u.operand;
1498 int count = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001499 printLocationAndOp(out, exec, location, it, "strcat");
1500 out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), count);
barraclough@apple.com14dc4e12009-05-07 00:06:07 +00001501 break;
1502 }
1503 case op_to_primitive: {
1504 int r0 = (++it)->u.operand;
1505 int r1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001506 printLocationAndOp(out, exec, location, it, "to_primitive");
1507 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
barraclough@apple.com14dc4e12009-05-07 00:06:07 +00001508 break;
1509 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001510 case op_get_enumerable_length: {
1511 int dst = it[1].u.operand;
1512 int base = it[2].u.operand;
1513 printLocationAndOp(out, exec, location, it, "op_get_enumerable_length");
1514 out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
1515 it += OPCODE_LENGTH(op_get_enumerable_length) - 1;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001516 break;
1517 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001518 case op_has_indexed_property: {
1519 int dst = it[1].u.operand;
xan@webkit.orgb469f502010-10-13 15:39:37 +00001520 int base = it[2].u.operand;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001521 int propertyName = it[3].u.operand;
1522 ArrayProfile* arrayProfile = it[4].u.arrayProfile;
1523 printLocationAndOp(out, exec, location, it, "op_has_indexed_property");
1524 out.printf("%s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), arrayProfile);
1525 it += OPCODE_LENGTH(op_has_indexed_property) - 1;
1526 break;
1527 }
1528 case op_has_structure_property: {
1529 int dst = it[1].u.operand;
1530 int base = it[2].u.operand;
1531 int propertyName = it[3].u.operand;
1532 int enumerator = it[4].u.operand;
1533 printLocationAndOp(out, exec, location, it, "op_has_structure_property");
1534 out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(enumerator).data());
1535 it += OPCODE_LENGTH(op_has_structure_property) - 1;
1536 break;
1537 }
1538 case op_has_generic_property: {
1539 int dst = it[1].u.operand;
1540 int base = it[2].u.operand;
1541 int propertyName = it[3].u.operand;
1542 printLocationAndOp(out, exec, location, it, "op_has_generic_property");
1543 out.printf("%s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data());
1544 it += OPCODE_LENGTH(op_has_generic_property) - 1;
1545 break;
1546 }
1547 case op_get_direct_pname: {
1548 int dst = it[1].u.operand;
1549 int base = it[2].u.operand;
1550 int propertyName = it[3].u.operand;
1551 int index = it[4].u.operand;
1552 int enumerator = it[5].u.operand;
1553 ValueProfile* profile = it[6].u.profile;
1554 printLocationAndOp(out, exec, location, it, "op_get_direct_pname");
1555 out.printf("%s, %s, %s, %s, %s, %p", registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(index).data(), registerName(enumerator).data(), profile);
1556 it += OPCODE_LENGTH(op_get_direct_pname) - 1;
1557 break;
1558
1559 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00001560 case op_get_property_enumerator: {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001561 int dst = it[1].u.operand;
1562 int base = it[2].u.operand;
msaboff@apple.comb644c252015-03-24 10:05:21 +00001563 printLocationAndOp(out, exec, location, it, "op_get_property_enumerator");
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001564 out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
msaboff@apple.comb644c252015-03-24 10:05:21 +00001565 it += OPCODE_LENGTH(op_get_property_enumerator) - 1;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001566 break;
1567 }
msaboff@apple.comb644c252015-03-24 10:05:21 +00001568 case op_enumerator_structure_pname: {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001569 int dst = it[1].u.operand;
1570 int enumerator = it[2].u.operand;
1571 int index = it[3].u.operand;
msaboff@apple.comb644c252015-03-24 10:05:21 +00001572 printLocationAndOp(out, exec, location, it, "op_enumerator_structure_pname");
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001573 out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
msaboff@apple.comb644c252015-03-24 10:05:21 +00001574 it += OPCODE_LENGTH(op_enumerator_structure_pname) - 1;
1575 break;
1576 }
1577 case op_enumerator_generic_pname: {
1578 int dst = it[1].u.operand;
1579 int enumerator = it[2].u.operand;
1580 int index = it[3].u.operand;
1581 printLocationAndOp(out, exec, location, it, "op_enumerator_generic_pname");
1582 out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
1583 it += OPCODE_LENGTH(op_enumerator_generic_pname) - 1;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001584 break;
1585 }
1586 case op_to_index_string: {
1587 int dst = it[1].u.operand;
1588 int index = it[2].u.operand;
1589 printLocationAndOp(out, exec, location, it, "op_to_index_string");
1590 out.printf("%s, %s", registerName(dst).data(), registerName(index).data());
1591 it += OPCODE_LENGTH(op_to_index_string) - 1;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001592 break;
1593 }
ggaren@apple.com170d6f22012-09-02 21:27:23 +00001594 case op_push_with_scope: {
msaboff@apple.comc5b95392014-10-31 21:27:10 +00001595 int dst = (++it)->u.operand;
1596 int newScope = (++it)->u.operand;
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00001597 int currentScope = (++it)->u.operand;
msaboff@apple.comc5b95392014-10-31 21:27:10 +00001598 printLocationAndOp(out, exec, location, it, "push_with_scope");
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00001599 out.printf("%s, %s, %s", registerName(dst).data(), registerName(newScope).data(), registerName(currentScope).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001600 break;
1601 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001602 case op_get_parent_scope: {
1603 int dst = (++it)->u.operand;
1604 int parentScope = (++it)->u.operand;
1605 printLocationAndOp(out, exec, location, it, "get_parent_scope");
1606 out.printf("%s, %s", registerName(dst).data(), registerName(parentScope).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001607 break;
1608 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001609 case op_create_lexical_environment: {
1610 int dst = (++it)->u.operand;
1611 int scope = (++it)->u.operand;
1612 int symbolTable = (++it)->u.operand;
1613 int initialValue = (++it)->u.operand;
1614 printLocationAndOp(out, exec, location, it, "create_lexical_environment");
1615 out.printf("%s, %s, %s, %s",
1616 registerName(dst).data(), registerName(scope).data(), registerName(symbolTable).data(), registerName(initialValue).data());
1617 break;
1618 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001619 case op_catch: {
1620 int r0 = (++it)->u.operand;
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00001621 int r1 = (++it)->u.operand;
1622 printLocationAndOp(out, exec, location, it, "catch");
1623 out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001624 break;
1625 }
1626 case op_throw: {
1627 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001628 printLocationOpAndRegisterOperand(out, exec, location, it, "throw", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001629 break;
1630 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001631 case op_throw_static_error: {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001632 int k0 = (++it)->u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001633 int k1 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001634 printLocationAndOp(out, exec, location, it, "throw_static_error");
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00001635 out.printf("%s, %s", constantName(k0).data(), k1 ? "true" : "false");
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001636 break;
1637 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001638 case op_debug: {
1639 int debugHookID = (++it)->u.operand;
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001640 int hasBreakpointFlag = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001641 printLocationAndOp(out, exec, location, it, "debug");
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +00001642 out.printf("%s, %d", debugHookName(debugHookID), hasBreakpointFlag);
1643 break;
1644 }
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001645 case op_save: {
1646 int generator = (++it)->u.operand;
1647 unsigned liveCalleeLocalsIndex = (++it)->u.unsignedValue;
1648 int offset = (++it)->u.operand;
1649 const FastBitVector& liveness = m_rareData->m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex];
1650 printLocationAndOp(out, exec, location, it, "save");
1651 out.printf("%s, ", registerName(generator).data());
1652 liveness.dump(out);
1653 out.printf("(@live%1u), %d(->%d)", liveCalleeLocalsIndex, offset, location + offset);
1654 break;
1655 }
1656 case op_resume: {
1657 int generator = (++it)->u.operand;
1658 unsigned liveCalleeLocalsIndex = (++it)->u.unsignedValue;
1659 const FastBitVector& liveness = m_rareData->m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex];
1660 printLocationAndOp(out, exec, location, it, "resume");
1661 out.printf("%s, ", registerName(generator).data());
1662 liveness.dump(out);
1663 out.printf("(@live%1u)", liveCalleeLocalsIndex);
1664 break;
1665 }
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +00001666 case op_assert: {
1667 int condition = (++it)->u.operand;
1668 int line = (++it)->u.operand;
1669 printLocationAndOp(out, exec, location, it, "assert");
1670 out.printf("%s, %d", registerName(condition).data(), line);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001671 break;
1672 }
1673 case op_end: {
1674 int r0 = (++it)->u.operand;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001675 printLocationOpAndRegisterOperand(out, exec, location, it, "end", r0);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001676 break;
1677 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001678 case op_resolve_scope: {
1679 int r0 = (++it)->u.operand;
msaboff@apple.com44641f02014-11-03 17:56:29 +00001680 int scope = (++it)->u.operand;
oliver@apple.com58c86752013-07-25 04:02:40 +00001681 int id0 = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001682 ResolveType resolveType = static_cast<ResolveType>((++it)->u.operand);
mark.lam@apple.com65a636f2014-02-01 01:24:39 +00001683 int depth = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001684 void* pointer = (++it)->u.pointer;
msaboff@apple.comc5808642013-09-05 23:27:41 +00001685 printLocationAndOp(out, exec, location, it, "resolve_scope");
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001686 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 +00001687 break;
1688 }
1689 case op_get_from_scope: {
1690 int r0 = (++it)->u.operand;
1691 int r1 = (++it)->u.operand;
1692 int id0 = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001693 GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
oliver@apple.com58c86752013-07-25 04:02:40 +00001694 ++it; // Structure
mark.lam@apple.com65a636f2014-02-01 01:24:39 +00001695 int operand = (++it)->u.operand; // Operand
msaboff@apple.comc5808642013-09-05 23:27:41 +00001696 printLocationAndOp(out, exec, location, it, "get_from_scope");
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001697 out.print(registerName(r0), ", ", registerName(r1));
1698 if (static_cast<unsigned>(id0) == UINT_MAX)
1699 out.print(", anonymous");
1700 else
1701 out.print(", ", idName(id0, identifier(id0)));
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001702 out.print(", ", getPutInfo.operand(), "<", resolveModeName(getPutInfo.resolveMode()), "|", resolveTypeName(getPutInfo.resolveType()), "|", initializationModeName(getPutInfo.initializationMode()), ">, ", operand);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001703 dumpValueProfiling(out, it, hasPrintedProfiling);
oliver@apple.com58c86752013-07-25 04:02:40 +00001704 break;
1705 }
1706 case op_put_to_scope: {
1707 int r0 = (++it)->u.operand;
1708 int id0 = (++it)->u.operand;
1709 int r1 = (++it)->u.operand;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001710 GetPutInfo getPutInfo = GetPutInfo((++it)->u.operand);
oliver@apple.com58c86752013-07-25 04:02:40 +00001711 ++it; // Structure
mark.lam@apple.com65a636f2014-02-01 01:24:39 +00001712 int operand = (++it)->u.operand; // Operand
msaboff@apple.comc5808642013-09-05 23:27:41 +00001713 printLocationAndOp(out, exec, location, it, "put_to_scope");
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001714 out.print(registerName(r0));
1715 if (static_cast<unsigned>(id0) == UINT_MAX)
1716 out.print(", anonymous");
1717 else
1718 out.print(", ", idName(id0, identifier(id0)));
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001719 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 +00001720 break;
1721 }
1722 case op_get_from_arguments: {
1723 int r0 = (++it)->u.operand;
1724 int r1 = (++it)->u.operand;
1725 int offset = (++it)->u.operand;
1726 printLocationAndOp(out, exec, location, it, "get_from_arguments");
1727 out.printf("%s, %s, %d", registerName(r0).data(), registerName(r1).data(), offset);
1728 dumpValueProfiling(out, it, hasPrintedProfiling);
1729 break;
1730 }
1731 case op_put_to_arguments: {
1732 int r0 = (++it)->u.operand;
1733 int offset = (++it)->u.operand;
1734 int r1 = (++it)->u.operand;
1735 printLocationAndOp(out, exec, location, it, "put_to_arguments");
1736 out.printf("%s, %d, %s", registerName(r0).data(), offset, registerName(r1).data());
oliver@apple.com58c86752013-07-25 04:02:40 +00001737 break;
1738 }
commit-queue@webkit.orge13567f2012-09-01 17:36:51 +00001739 default:
oliver@apple.com903b0c02013-01-24 01:40:37 +00001740 RELEASE_ASSERT_NOT_REACHED();
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001741 }
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001742
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001743 dumpRareCaseProfile(out, "rare case: ", rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling);
mark.lam@apple.combad59ea2015-12-18 22:03:30 +00001744 dumpResultProfile(out, resultProfileForBytecodeOffset(location), hasPrintedProfiling);
fpizlo@apple.comca3a85b2012-12-17 07:16:18 +00001745
fpizlo@apple.com105ea9b2013-02-17 05:36:48 +00001746#if ENABLE(DFG_JIT)
oliver@apple.com02b179b2013-07-25 03:58:20 +00001747 Vector<DFG::FrequentExitSite> exitSites = exitProfile().exitSitesFor(location);
fpizlo@apple.com105ea9b2013-02-17 05:36:48 +00001748 if (!exitSites.isEmpty()) {
1749 out.print(" !! frequent exits: ");
1750 CommaPrinter comma;
1751 for (unsigned i = 0; i < exitSites.size(); ++i)
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00001752 out.print(comma, exitSites[i].kind(), " ", exitSites[i].jitType());
fpizlo@apple.com105ea9b2013-02-17 05:36:48 +00001753 }
1754#else // ENABLE(DFG_JIT)
1755 UNUSED_PARAM(location);
1756#endif // ENABLE(DFG_JIT)
1757 out.print("\n");
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001758}
1759
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001760void CodeBlock::dumpBytecode(
1761 PrintStream& out, unsigned bytecodeOffset,
1762 const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
fpizlo@apple.com1949f322012-11-22 00:46:57 +00001763{
1764 ExecState* exec = m_globalObject->globalExec();
1765 const Instruction* it = instructions().begin() + bytecodeOffset;
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001766 dumpBytecode(out, exec, instructions().begin(), it, stubInfos, callLinkInfos);
fpizlo@apple.com1949f322012-11-22 00:46:57 +00001767}
1768
weinig@apple.com67940d52008-12-09 00:14:58 +00001769#define FOR_EACH_MEMBER_VECTOR(macro) \
1770 macro(instructions) \
weinig@apple.com67940d52008-12-09 00:14:58 +00001771 macro(callLinkInfos) \
1772 macro(linkedCallerList) \
1773 macro(identifiers) \
1774 macro(functionExpressions) \
weinig@apple.com93675542009-01-09 18:47:37 +00001775 macro(constantRegisters)
weinig@apple.com4557e842008-12-09 01:06:14 +00001776
1777#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
weinig@apple.com67940d52008-12-09 00:14:58 +00001778 macro(regexps) \
1779 macro(functions) \
weinig@apple.com67940d52008-12-09 00:14:58 +00001780 macro(exceptionHandlers) \
oliver@apple.coma14cea52013-07-25 04:03:23 +00001781 macro(switchJumpTables) \
weinig@apple.comc7b19892008-12-18 00:00:01 +00001782 macro(stringSwitchJumpTables) \
barraclough@apple.com87dbd5e2010-11-19 02:35:25 +00001783 macro(evalCodeCache) \
weinig@apple.comaf0231a2009-01-08 01:46:14 +00001784 macro(expressionInfo) \
1785 macro(lineInfo) \
barraclough@apple.com87dbd5e2010-11-19 02:35:25 +00001786 macro(callReturnIndexVector)
weinig@apple.comaf0231a2009-01-08 01:46:14 +00001787
weinig@apple.comff037a02008-12-10 20:05:53 +00001788template<typename T>
1789static size_t sizeInBytes(const Vector<T>& vector)
1790{
1791 return vector.capacity() * sizeof(T);
1792}
1793
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001794namespace {
1795
1796class PutToScopeFireDetail : public FireDetail {
1797public:
1798 PutToScopeFireDetail(CodeBlock* codeBlock, const Identifier& ident)
1799 : m_codeBlock(codeBlock)
1800 , m_ident(ident)
1801 {
1802 }
1803
darin@apple.com11ff47c2016-03-04 16:47:55 +00001804 void dump(PrintStream& out) const override
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001805 {
1806 out.print("Linking put_to_scope in ", FunctionExecutableDump(jsCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())), " for ", m_ident);
1807 }
1808
1809private:
1810 CodeBlock* m_codeBlock;
1811 const Identifier& m_ident;
1812};
1813
1814} // anonymous namespace
1815
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001816CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock& other)
1817 : JSCell(*vm, structure)
1818 , m_globalObject(other.m_globalObject)
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001819 , m_numCalleeLocals(other.m_numCalleeLocals)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001820 , m_numVars(other.m_numVars)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00001821 , m_shouldAlwaysBeInlined(true)
akling@apple.comce2ec582016-01-29 20:37:52 +00001822#if ENABLE(JIT)
1823 , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
1824#endif
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001825 , m_didFailFTLCompilation(false)
msaboff@apple.com95894332014-01-29 19:18:54 +00001826 , m_hasBeenCompiledWithFTL(false)
akling@apple.comce2ec582016-01-29 20:37:52 +00001827 , m_isConstructor(other.m_isConstructor)
1828 , m_isStrictMode(other.m_isStrictMode)
akling@apple.comce2ec582016-01-29 20:37:52 +00001829 , m_codeType(other.m_codeType)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001830 , m_unlinkedCode(*other.m_vm, this, other.m_unlinkedCode.get())
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +00001831 , m_hasDebuggerStatement(false)
mark.lam@apple.com9c304882014-01-24 19:07:31 +00001832 , m_steppingMode(SteppingModeDisabled)
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001833 , m_numBreakpoints(0)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001834 , m_ownerExecutable(*other.m_vm, this, other.m_ownerExecutable.get())
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001835 , m_vm(other.m_vm)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001836 , m_instructions(other.m_instructions)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001837 , m_thisRegister(other.m_thisRegister)
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +00001838 , m_scopeRegister(other.m_scopeRegister)
akling@apple.comce2ec582016-01-29 20:37:52 +00001839 , m_hash(other.m_hash)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001840 , m_source(other.m_source)
1841 , m_sourceOffset(other.m_sourceOffset)
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001842 , m_firstLineColumnOffset(other.m_firstLineColumnOffset)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001843 , m_constantRegisters(other.m_constantRegisters)
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00001844 , m_constantsSourceCodeRepresentation(other.m_constantsSourceCodeRepresentation)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001845 , m_functionDecls(other.m_functionDecls)
1846 , m_functionExprs(other.m_functionExprs)
fpizlo@apple.com39c94a42012-07-10 09:18:47 +00001847 , m_osrExitCounter(0)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001848 , m_optimizationDelayCounter(0)
1849 , m_reoptimizationRetryCounter(0)
ggaren@apple.com05483852015-09-17 00:28:34 +00001850 , m_creationTime(std::chrono::steady_clock::now())
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001851{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001852 m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
mark.lam@apple.com5d1b2b62015-03-13 18:02:40 +00001853
akling@apple.comce2ec582016-01-29 20:37:52 +00001854 ASSERT(heap()->isDeferred());
msaboff@apple.com2f145bc2015-01-23 19:52:25 +00001855 ASSERT(m_scopeRegister.isLocal());
1856
fpizlo@apple.comc4d54962012-01-10 22:08:47 +00001857 setNumParameters(other.numParameters());
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001858}
1859
sbarati@apple.com3a9165f2016-05-24 22:28:20 +00001860struct AbstractResolveKey {
1861 AbstractResolveKey()
1862 : m_impl(nullptr)
1863 { }
1864 AbstractResolveKey(size_t depth, const Identifier& ident, GetOrPut getOrPut, ResolveType resolveType, InitializationMode initializationMode)
1865 : m_depth(depth)
1866 , m_impl(ident.impl())
1867 , m_getOrPut(getOrPut)
1868 , m_resolveType(resolveType)
1869 , m_initializationMode(initializationMode)
1870 { }
1871
1872
1873 bool operator==(const AbstractResolveKey& other) const
1874 {
1875 return m_impl == other.m_impl
1876 && m_depth == other.m_depth
1877 && m_getOrPut == other.m_getOrPut
1878 && m_resolveType == other.m_resolveType
1879 && m_initializationMode == other.m_initializationMode;
1880 }
1881
1882 bool isNull() const { return !m_impl; }
1883
1884 size_t m_depth;
1885 UniquedStringImpl* m_impl;
1886 GetOrPut m_getOrPut;
1887 ResolveType m_resolveType;
1888 InitializationMode m_initializationMode;
1889};
1890
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001891void CodeBlock::finishCreation(VM& vm, CopyParsedBlockTag, CodeBlock& other)
1892{
1893 Base::finishCreation(vm);
1894
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001895 optimizeAfterWarmUp();
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00001896 jitAfterWarmUp();
commit-queue@webkit.org3e0a1a02012-06-19 06:07:28 +00001897
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001898 if (other.m_rareData) {
1899 createRareDataIfNecessary();
1900
1901 m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001902 m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers;
oliver@apple.coma14cea52013-07-25 04:03:23 +00001903 m_rareData->m_switchJumpTables = other.m_rareData->m_switchJumpTables;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001904 m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001905 m_rareData->m_liveCalleeLocalsAtYield = other.m_rareData->m_liveCalleeLocalsAtYield;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001906 }
fpizlo@apple.com195d7b82013-09-03 16:39:29 +00001907
akling@apple.comce2ec582016-01-29 20:37:52 +00001908 heap()->m_codeBlocks.add(this);
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +00001909}
1910
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001911CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
1912 JSScope* scope, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
1913 : JSCell(*vm, structure)
1914 , m_globalObject(scope->globalObject()->vm(), this, scope->globalObject())
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00001915 , m_numCalleeLocals(unlinkedCodeBlock->m_numCalleeLocals)
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001916 , m_numVars(unlinkedCodeBlock->m_numVars)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00001917 , m_shouldAlwaysBeInlined(true)
akling@apple.comce2ec582016-01-29 20:37:52 +00001918#if ENABLE(JIT)
1919 , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
1920#endif
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001921 , m_didFailFTLCompilation(false)
msaboff@apple.com95894332014-01-29 19:18:54 +00001922 , m_hasBeenCompiledWithFTL(false)
akling@apple.comce2ec582016-01-29 20:37:52 +00001923 , m_isConstructor(unlinkedCodeBlock->isConstructor())
1924 , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
akling@apple.comce2ec582016-01-29 20:37:52 +00001925 , m_codeType(unlinkedCodeBlock->codeType())
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001926 , m_unlinkedCode(m_globalObject->vm(), this, unlinkedCodeBlock)
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +00001927 , m_hasDebuggerStatement(false)
mark.lam@apple.com9c304882014-01-24 19:07:31 +00001928 , m_steppingMode(SteppingModeDisabled)
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001929 , m_numBreakpoints(0)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001930 , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001931 , m_vm(unlinkedCodeBlock->vm())
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001932 , m_thisRegister(unlinkedCodeBlock->thisRegister())
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +00001933 , m_scopeRegister(unlinkedCodeBlock->scopeRegister())
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00001934 , m_source(sourceProvider)
1935 , m_sourceOffset(sourceOffset)
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001936 , m_firstLineColumnOffset(firstLineColumnOffset)
fpizlo@apple.com39c94a42012-07-10 09:18:47 +00001937 , m_osrExitCounter(0)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00001938 , m_optimizationDelayCounter(0)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00001939 , m_reoptimizationRetryCounter(0)
ggaren@apple.com05483852015-09-17 00:28:34 +00001940 , m_creationTime(std::chrono::steady_clock::now())
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00001941{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001942 m_visitWeaklyHasBeenCalled.store(false, std::memory_order_relaxed);
mark.lam@apple.com5d1b2b62015-03-13 18:02:40 +00001943
akling@apple.comce2ec582016-01-29 20:37:52 +00001944 ASSERT(heap()->isDeferred());
msaboff@apple.com2f145bc2015-01-23 19:52:25 +00001945 ASSERT(m_scopeRegister.isLocal());
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001946
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00001947 ASSERT(m_source);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001948 setNumParameters(unlinkedCodeBlock->numParameters());
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001949}
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001950
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001951void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
1952 JSScope* scope)
1953{
1954 Base::finishCreation(vm);
1955
1956 if (vm.typeProfiler() || vm.controlFlowProfiler())
1957 vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001958
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00001959 setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
oliver@apple.com75f804e2013-03-07 00:25:20 +00001960 if (unlinkedCodeBlock->usesGlobalObject())
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001961 m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00001962
1963 for (unsigned i = 0; i < LinkTimeConstantCount; i++) {
1964 LinkTimeConstant type = static_cast<LinkTimeConstant>(i);
1965 if (unsigned registerIndex = unlinkedCodeBlock->registerIndexForLinkTimeConstant(type))
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001966 m_constantRegisters[registerIndex].set(*m_vm, this, m_globalObject->jsCellForLinkTimeConstant(type));
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00001967 }
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00001968
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00001969 // We already have the cloned symbol table for the module environment since we need to instantiate
1970 // the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
1971 if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(unlinkedCodeBlock)) {
1972 SymbolTable* clonedSymbolTable = jsCast<ModuleProgramExecutable*>(ownerExecutable)->moduleEnvironmentSymbolTable();
1973 if (m_vm->typeProfiler()) {
1974 ConcurrentJITLocker locker(clonedSymbolTable->m_lock);
1975 clonedSymbolTable->prepareForTypeProfiling(locker);
1976 }
1977 replaceConstant(unlinkedModuleProgramCodeBlock->moduleEnvironmentSymbolTableConstantRegisterOffset(), clonedSymbolTable);
1978 }
1979
sbarati@apple.com2877c4a2016-03-31 00:47:15 +00001980 bool shouldUpdateFunctionHasExecutedCache = vm.typeProfiler() || vm.controlFlowProfiler();
akling@apple.comce2ec582016-01-29 20:37:52 +00001981 m_functionDecls = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionDecls());
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001982 for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
1983 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
sbarati@apple.com2877c4a2016-03-31 00:47:15 +00001984 if (shouldUpdateFunctionHasExecutedCache)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001985 vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
1986 m_functionDecls[i].set(*m_vm, this, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001987 }
1988
akling@apple.comce2ec582016-01-29 20:37:52 +00001989 m_functionExprs = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionExprs());
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001990 for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
1991 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
sbarati@apple.com2877c4a2016-03-31 00:47:15 +00001992 if (shouldUpdateFunctionHasExecutedCache)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001993 vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
1994 m_functionExprs[i].set(*m_vm, this, unlinkedExecutable->link(*m_vm, ownerExecutable->source()));
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001995 }
1996
1997 if (unlinkedCodeBlock->hasRareData()) {
1998 createRareDataIfNecessary();
1999 if (size_t count = unlinkedCodeBlock->constantBufferCount()) {
2000 m_rareData->m_constantBuffers.grow(count);
2001 for (size_t i = 0; i < count; i++) {
2002 const UnlinkedCodeBlock::ConstantBuffer& buffer = unlinkedCodeBlock->constantBuffer(i);
2003 m_rareData->m_constantBuffers[i] = buffer;
2004 }
2005 }
2006 if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) {
akling@apple.comb2ad1692014-01-18 23:09:48 +00002007 m_rareData->m_exceptionHandlers.resizeToFit(count);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002008 for (size_t i = 0; i < count; i++) {
mark.lam@apple.com4585ce92015-05-30 00:19:01 +00002009 const UnlinkedHandlerInfo& unlinkedHandler = unlinkedCodeBlock->exceptionHandler(i);
2010 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
mark.lam@apple.com3280e072015-06-01 17:57:18 +00002011#if ENABLE(JIT)
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002012 handler.initialize(unlinkedHandler, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(op_catch))));
mark.lam@apple.com3280e072015-06-01 17:57:18 +00002013#else
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002014 handler.initialize(unlinkedHandler);
mark.lam@apple.com3280e072015-06-01 17:57:18 +00002015#endif
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002016 }
2017 }
2018
2019 if (size_t count = unlinkedCodeBlock->numberOfStringSwitchJumpTables()) {
2020 m_rareData->m_stringSwitchJumpTables.grow(count);
2021 for (size_t i = 0; i < count; i++) {
2022 UnlinkedStringJumpTable::StringOffsetTable::iterator ptr = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.begin();
2023 UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end();
2024 for (; ptr != end; ++ptr) {
2025 OffsetLocation offset;
2026 offset.branchOffset = ptr->value;
2027 m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset);
2028 }
2029 }
2030 }
2031
oliver@apple.coma14cea52013-07-25 04:03:23 +00002032 if (size_t count = unlinkedCodeBlock->numberOfSwitchJumpTables()) {
2033 m_rareData->m_switchJumpTables.grow(count);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002034 for (size_t i = 0; i < count; i++) {
oliver@apple.coma14cea52013-07-25 04:03:23 +00002035 UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->switchJumpTable(i);
2036 SimpleJumpTable& destTable = m_rareData->m_switchJumpTables[i];
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002037 destTable.branchOffsets = sourceTable.branchOffsets;
2038 destTable.min = sourceTable.min;
2039 }
2040 }
2041 }
2042
2043 // Allocate metadata buffers for the bytecode
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002044 if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos())
akling@apple.comce2ec582016-01-29 20:37:52 +00002045 m_llintCallLinkInfos = RefCountedArray<LLIntCallLinkInfo>(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002046 if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
2047 m_arrayProfiles.grow(size);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002048 if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles())
akling@apple.comce2ec582016-01-29 20:37:52 +00002049 m_arrayAllocationProfiles = RefCountedArray<ArrayAllocationProfile>(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002050 if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
akling@apple.comce2ec582016-01-29 20:37:52 +00002051 m_valueProfiles = RefCountedArray<ValueProfile>(size);
ggaren@apple.comc862eac2013-01-29 05:48:01 +00002052 if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
akling@apple.comce2ec582016-01-29 20:37:52 +00002053 m_objectAllocationProfiles = RefCountedArray<ObjectAllocationProfile>(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002054
msaboff@apple.com02085462015-09-10 17:47:16 +00002055#if ENABLE(JIT)
2056 setCalleeSaveRegisters(RegisterSet::llintBaselineCalleeSaveRegisters());
2057#endif
2058
sbarati@apple.com3a9165f2016-05-24 22:28:20 +00002059 AbstractResolveKey lastResolveKey;
2060 ResolveOp lastCachedOp;
2061 auto cachedAbstractResolve = [&] (size_t localScopeDepth, const Identifier& ident, GetOrPut getOrPut, ResolveType resolveType, InitializationMode initializationMode) -> const ResolveOp& {
2062 AbstractResolveKey key(localScopeDepth, ident, getOrPut, resolveType, initializationMode);
2063 if (key == lastResolveKey) {
2064 ASSERT(!lastResolveKey.isNull());
2065 return lastCachedOp;
2066 }
2067 lastCachedOp = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, getOrPut, resolveType, initializationMode);
2068 lastResolveKey = key;
2069 return lastCachedOp;
2070 };
2071
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002072 // Copy and translate the UnlinkedInstructions
akling@apple.com8427aaf2014-01-27 05:45:30 +00002073 unsigned instructionCount = unlinkedCodeBlock->instructions().count();
2074 UnlinkedInstructionStream::Reader instructionReader(unlinkedCodeBlock->instructions());
2075
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002076 // Bookkeep the strongly referenced module environments.
2077 HashSet<JSModuleEnvironment*> stronglyReferencedModuleEnvironments;
2078
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002079 // Bookkeep the merge point bytecode offsets.
2080 Vector<size_t> mergePointBytecodeOffsets;
2081
akling@apple.comf10f7a12015-10-10 21:14:56 +00002082 RefCountedArray<Instruction> instructions(instructionCount);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002083
akling@apple.com8427aaf2014-01-27 05:45:30 +00002084 for (unsigned i = 0; !instructionReader.atEnd(); ) {
2085 const UnlinkedInstruction* pc = instructionReader.next();
2086
2087 unsigned opLength = opcodeLength(pc[0].u.opcode);
2088
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002089 instructions[i] = vm.interpreter->getOpcode(pc[0].u.opcode);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002090 for (size_t j = 1; j < opLength; ++j) {
2091 if (sizeof(int32_t) != sizeof(intptr_t))
2092 instructions[i + j].u.pointer = 0;
akling@apple.com8427aaf2014-01-27 05:45:30 +00002093 instructions[i + j].u.operand = pc[j].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002094 }
akling@apple.com8427aaf2014-01-27 05:45:30 +00002095 switch (pc[0].u.opcode) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002096 case op_has_indexed_property: {
2097 int arrayProfileIndex = pc[opLength - 1].u.operand;
2098 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
2099
2100 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
2101 break;
2102 }
msaboff@apple.com74aef1f2014-02-01 15:30:41 +00002103 case op_call_varargs:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00002104 case op_tail_call_varargs:
oliver@apple.com177c2b92014-03-28 01:10:25 +00002105 case op_construct_varargs:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002106 case op_get_by_val: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002107 int arrayProfileIndex = pc[opLength - 2].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002108 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
2109
2110 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
joepeck@webkit.org899544a2014-01-28 04:04:45 +00002111 FALLTHROUGH;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002112 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002113 case op_get_direct_pname:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002114 case op_get_by_id:
2115 case op_get_from_arguments: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002116 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002117 ASSERT(profile->m_bytecodeOffset == -1);
2118 profile->m_bytecodeOffset = i;
2119 instructions[i + opLength - 1] = profile;
2120 break;
2121 }
2122 case op_put_by_val: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002123 int arrayProfileIndex = pc[opLength - 1].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002124 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
2125 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
2126 break;
2127 }
oliver@apple.come050d642013-10-19 00:09:28 +00002128 case op_put_by_val_direct: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002129 int arrayProfileIndex = pc[opLength - 1].u.operand;
oliver@apple.come050d642013-10-19 00:09:28 +00002130 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
2131 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
2132 break;
2133 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002134
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002135 case op_new_array:
2136 case op_new_array_buffer:
2137 case op_new_array_with_size: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002138 int arrayAllocationProfileIndex = pc[opLength - 1].u.operand;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002139 instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
2140 break;
2141 }
ggaren@apple.comc862eac2013-01-29 05:48:01 +00002142 case op_new_object: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002143 int objectAllocationProfileIndex = pc[opLength - 1].u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +00002144 ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex];
akling@apple.com8427aaf2014-01-27 05:45:30 +00002145 int inferredInlineCapacity = pc[opLength - 2].u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +00002146
2147 instructions[i + opLength - 1] = objectAllocationProfile;
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002148 objectAllocationProfile->initialize(vm,
2149 this, m_globalObject->objectPrototype(), inferredInlineCapacity);
ggaren@apple.comc862eac2013-01-29 05:48:01 +00002150 break;
2151 }
2152
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002153 case op_call:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00002154 case op_tail_call:
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002155 case op_call_eval: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002156 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00002157 ASSERT(profile->m_bytecodeOffset == -1);
2158 profile->m_bytecodeOffset = i;
2159 instructions[i + opLength - 1] = profile;
akling@apple.com8427aaf2014-01-27 05:45:30 +00002160 int arrayProfileIndex = pc[opLength - 2].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002161 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00002162 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
akling@apple.com8427aaf2014-01-27 05:45:30 +00002163 instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
fpizlo@apple.com0ed51fc2012-11-09 01:27:25 +00002164 break;
2165 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00002166 case op_construct: {
akling@apple.com8427aaf2014-01-27 05:45:30 +00002167 instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
akling@apple.com8427aaf2014-01-27 05:45:30 +00002168 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00002169 ASSERT(profile->m_bytecodeOffset == -1);
2170 profile->m_bytecodeOffset = i;
2171 instructions[i + opLength - 1] = profile;
fpizlo@apple.com0ed51fc2012-11-09 01:27:25 +00002172 break;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00002173 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002174 case op_get_array_length:
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002175 CRASH();
2176
oliver@apple.com58c86752013-07-25 04:02:40 +00002177 case op_resolve_scope: {
msaboff@apple.com44641f02014-11-03 17:56:29 +00002178 const Identifier& ident = identifier(pc[3].u.operand);
2179 ResolveType type = static_cast<ResolveType>(pc[4].u.operand);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +00002180 RELEASE_ASSERT(type != LocalClosureVar);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002181 int localScopeDepth = pc[5].u.operand;
oliver@apple.com58c86752013-07-25 04:02:40 +00002182
sbarati@apple.com3a9165f2016-05-24 22:28:20 +00002183 const ResolveOp& op = cachedAbstractResolve(localScopeDepth, ident, Get, type, InitializationMode::NotInitialization);
msaboff@apple.com44641f02014-11-03 17:56:29 +00002184 instructions[i + 4].u.operand = op.type;
2185 instructions[i + 5].u.operand = op.depth;
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002186 if (op.lexicalEnvironment) {
2187 if (op.type == ModuleVar) {
2188 // Keep the linked module environment strongly referenced.
2189 if (stronglyReferencedModuleEnvironments.add(jsCast<JSModuleEnvironment*>(op.lexicalEnvironment)).isNewEntry)
2190 addConstant(op.lexicalEnvironment);
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002191 instructions[i + 6].u.jsCell.set(vm, this, op.lexicalEnvironment);
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002192 } else
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002193 instructions[i + 6].u.symbolTable.set(vm, this, op.lexicalEnvironment->symbolTable());
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002194 } else if (JSScope* constantScope = JSScope::constantScopeForCodeBlock(op.type, this))
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002195 instructions[i + 6].u.jsCell.set(vm, this, constantScope);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002196 else
2197 instructions[i + 6].u.pointer = nullptr;
oliver@apple.com58c86752013-07-25 04:02:40 +00002198 break;
2199 }
2200
2201 case op_get_from_scope: {
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002202 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
oliver@apple.com58c86752013-07-25 04:02:40 +00002203 ASSERT(profile->m_bytecodeOffset == -1);
2204 profile->m_bytecodeOffset = i;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002205 instructions[i + opLength - 1] = profile;
oliver@apple.com58c86752013-07-25 04:02:40 +00002206
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002207 // get_from_scope dst, scope, id, GetPutInfo, Structure, Operand
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002208
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002209 int localScopeDepth = pc[5].u.operand;
2210 instructions[i + 5].u.pointer = nullptr;
2211
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002212 GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand);
sbarati@apple.come67fd782016-04-19 01:38:30 +00002213 ASSERT(!isInitialization(getPutInfo.initializationMode()));
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002214 if (getPutInfo.resolveType() == LocalClosureVar) {
2215 instructions[i + 4] = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand();
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002216 break;
2217 }
2218
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002219 const Identifier& ident = identifier(pc[3].u.operand);
sbarati@apple.com3a9165f2016-05-24 22:28:20 +00002220 const ResolveOp& op = cachedAbstractResolve(localScopeDepth, ident, Get, getPutInfo.resolveType(), InitializationMode::NotInitialization);
oliver@apple.com58c86752013-07-25 04:02:40 +00002221
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002222 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002223 if (op.type == ModuleVar)
2224 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand();
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002225 if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
fpizlo@apple.com1a724092013-11-28 07:10:10 +00002226 instructions[i + 5].u.watchpointSet = op.watchpointSet;
2227 else if (op.structure)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002228 instructions[i + 5].u.structure.set(vm, this, op.structure);
oliver@apple.com58c86752013-07-25 04:02:40 +00002229 instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
2230 break;
2231 }
2232
2233 case op_put_to_scope: {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002234 // put_to_scope scope, id, value, GetPutInfo, Structure, Operand
2235 GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand);
2236 if (getPutInfo.resolveType() == LocalClosureVar) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002237 // Only do watching if the property we're putting to is not anonymous.
2238 if (static_cast<unsigned>(pc[2].u.operand) != UINT_MAX) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002239 int symbolTableIndex = pc[5].u.operand;
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002240 SymbolTable* symbolTable = jsCast<SymbolTable*>(getConstant(symbolTableIndex));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002241 const Identifier& ident = identifier(pc[2].u.operand);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002242 ConcurrentJITLocker locker(symbolTable->m_lock);
2243 auto iter = symbolTable->find(locker, ident.impl());
sbarati@apple.com2877c4a2016-03-31 00:47:15 +00002244 ASSERT(iter != symbolTable->end(locker));
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00002245 iter->value.prepareToWatch();
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002246 instructions[i + 5].u.watchpointSet = iter->value.watchpointSet();
2247 } else
2248 instructions[i + 5].u.watchpointSet = nullptr;
2249 break;
2250 }
2251
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002252 const Identifier& ident = identifier(pc[2].u.operand);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002253 int localScopeDepth = pc[5].u.operand;
2254 instructions[i + 5].u.pointer = nullptr;
sbarati@apple.com3a9165f2016-05-24 22:28:20 +00002255 const ResolveOp& op = cachedAbstractResolve(localScopeDepth, ident, Put, getPutInfo.resolveType(), getPutInfo.initializationMode());
oliver@apple.com58c86752013-07-25 04:02:40 +00002256
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002257 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
2258 if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
fpizlo@apple.com40f7cbf2013-11-18 23:19:53 +00002259 instructions[i + 5].u.watchpointSet = op.watchpointSet;
fpizlo@apple.com88fedde2013-12-04 19:29:19 +00002260 else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) {
2261 if (op.watchpointSet)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002262 op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident));
fpizlo@apple.com88fedde2013-12-04 19:29:19 +00002263 } else if (op.structure)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002264 instructions[i + 5].u.structure.set(vm, this, op.structure);
oliver@apple.com58c86752013-07-25 04:02:40 +00002265 instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002266
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002267 break;
2268 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002269
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002270 case op_profile_type: {
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002271 RELEASE_ASSERT(vm.typeProfiler());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002272 // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002273 size_t instructionOffset = i + opLength - 1;
2274 unsigned divotStart, divotEnd;
mark.lam@apple.comca860af2014-10-06 22:17:09 +00002275 GlobalVariableID globalVariableID = 0;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002276 RefPtr<TypeSet> globalTypeSet;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002277 bool shouldAnalyze = m_unlinkedCode->typeProfilerExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002278 VirtualRegister profileRegister(pc[1].u.operand);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002279 ProfileTypeBytecodeFlag flag = static_cast<ProfileTypeBytecodeFlag>(pc[3].u.operand);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002280 SymbolTable* symbolTable = nullptr;
2281
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002282 switch (flag) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002283 case ProfileTypeBytecodeClosureVar: {
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002284 const Identifier& ident = identifier(pc[4].u.operand);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002285 int localScopeDepth = pc[2].u.operand;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002286 ResolveType type = static_cast<ResolveType>(pc[5].u.operand);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002287 // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
2288 // we're abstractly "read"ing from a JSScope.
sbarati@apple.com3a9165f2016-05-24 22:28:20 +00002289 const ResolveOp& op = cachedAbstractResolve(localScopeDepth, ident, Get, type, InitializationMode::NotInitialization);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002290
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002291 if (op.type == ClosureVar || op.type == ModuleVar)
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +00002292 symbolTable = op.lexicalEnvironment->symbolTable();
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002293 else if (op.type == GlobalVar)
2294 symbolTable = m_globalObject.get()->symbolTable();
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +00002295
2296 UniquedStringImpl* impl = (op.type == ModuleVar) ? op.importedName.get() : ident.impl();
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002297 if (symbolTable) {
2298 ConcurrentJITLocker locker(symbolTable->m_lock);
2299 // 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 +00002300 symbolTable->prepareForTypeProfiling(locker);
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002301 globalVariableID = symbolTable->uniqueIDForVariable(locker, impl, vm);
2302 globalTypeSet = symbolTable->globalTypeSetForVariable(locker, impl, vm);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002303 } else
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002304 globalVariableID = TypeProfilerNoGlobalIDExists;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002305
2306 break;
2307 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002308 case ProfileTypeBytecodeLocallyResolved: {
2309 int symbolTableIndex = pc[2].u.operand;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002310 SymbolTable* symbolTable = jsCast<SymbolTable*>(getConstant(symbolTableIndex));
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002311 const Identifier& ident = identifier(pc[4].u.operand);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002312 ConcurrentJITLocker locker(symbolTable->m_lock);
2313 // If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002314 globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), vm);
2315 globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), vm);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002316
2317 break;
2318 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002319 case ProfileTypeBytecodeDoesNotHaveGlobalID:
2320 case ProfileTypeBytecodeFunctionArgument: {
2321 globalVariableID = TypeProfilerNoGlobalIDExists;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002322 break;
2323 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002324 case ProfileTypeBytecodeFunctionReturnStatement: {
commit-queue@webkit.orgf6bd2fb2014-08-26 02:17:58 +00002325 RELEASE_ASSERT(ownerExecutable->isFunctionExecutable());
2326 globalTypeSet = jsCast<FunctionExecutable*>(ownerExecutable)->returnStatementTypeSet();
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002327 globalVariableID = TypeProfilerReturnStatement;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002328 if (!shouldAnalyze) {
commit-queue@webkit.org9653c662014-08-26 04:36:42 +00002329 // Because a return statement can be added implicitly to return undefined at the end of a function,
2330 // and these nodes don't emit expression ranges because they aren't in the actual source text of
2331 // the user's program, give the type profiler some range to identify these return statements.
commit-queue@webkit.orgf1d9ed82015-08-17 22:57:23 +00002332 // Currently, the text offset that is used as identification is "f" in the function keyword
commit-queue@webkit.org9653c662014-08-26 04:36:42 +00002333 // and is stored on TypeLocation's m_divotForFunctionOffsetIfReturnStatement member variable.
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002334 divotStart = divotEnd = ownerExecutable->typeProfilingStartOffset();
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002335 shouldAnalyze = true;
2336 }
2337 break;
2338 }
2339 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002340
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002341 std::pair<TypeLocation*, bool> locationPair = vm.typeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID,
2342 ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, &vm);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002343 TypeLocation* location = locationPair.first;
2344 bool isNewLocation = locationPair.second;
2345
commit-queue@webkit.org9653c662014-08-26 04:36:42 +00002346 if (flag == ProfileTypeBytecodeFunctionReturnStatement)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002347 location->m_divotForFunctionOffsetIfReturnStatement = ownerExecutable->typeProfilingStartOffset();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002348
2349 if (shouldAnalyze && isNewLocation)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002350 vm.typeProfiler()->insertNewLocation(location);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002351
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002352 instructions[i + 2].u.location = location;
2353 break;
2354 }
2355
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +00002356 case op_debug: {
2357 if (pc[1].u.index == DidReachBreakpoint)
2358 m_hasDebuggerStatement = true;
2359 break;
2360 }
2361
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002362 case op_save: {
2363 unsigned liveCalleeLocalsIndex = pc[2].u.index;
2364 int offset = pc[3].u.operand;
2365 if (liveCalleeLocalsIndex >= mergePointBytecodeOffsets.size())
2366 mergePointBytecodeOffsets.resize(liveCalleeLocalsIndex + 1);
2367 mergePointBytecodeOffsets[liveCalleeLocalsIndex] = i + offset;
2368 break;
2369 }
2370
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002371 default:
2372 break;
2373 }
2374 i += opLength;
2375 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002376
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002377 if (vm.controlFlowProfiler())
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002378 insertBasicBlockBoundariesForControlFlowProfiler(instructions);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002379
aestes@apple.com13aae082016-01-02 08:03:08 +00002380 m_instructions = WTFMove(instructions);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00002381
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002382 // Perform bytecode liveness analysis to determine which locals are live and should be resumed when executing op_resume.
2383 if (unlinkedCodeBlock->parseMode() == SourceParseMode::GeneratorBodyMode) {
2384 if (size_t count = mergePointBytecodeOffsets.size()) {
2385 createRareDataIfNecessary();
2386 BytecodeLivenessAnalysis liveness(this);
2387 m_rareData->m_liveCalleeLocalsAtYield.grow(count);
2388 size_t liveCalleeLocalsIndex = 0;
2389 for (size_t bytecodeOffset : mergePointBytecodeOffsets) {
2390 m_rareData->m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex] = liveness.getLivenessInfoAtBytecodeOffset(bytecodeOffset);
2391 ++liveCalleeLocalsIndex;
2392 }
2393 }
2394 }
2395
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002396 // Set optimization thresholds only after m_instructions is initialized, since these
2397 // rely on the instruction count (and are in theory permitted to also inspect the
2398 // instruction stream to more accurate assess the cost of tier-up).
2399 optimizeAfterWarmUp();
2400 jitAfterWarmUp();
2401
oliver@apple.com9e1c8092013-07-25 04:03:16 +00002402 // If the concurrent thread will want the code block's hash, then compute it here
2403 // synchronously.
msaboff@apple.com95894332014-01-29 19:18:54 +00002404 if (Options::alwaysComputeHash())
oliver@apple.com9e1c8092013-07-25 04:03:16 +00002405 hash();
2406
msaboff@apple.com77adfde2012-11-29 03:16:11 +00002407 if (Options::dumpGeneratedBytecodes())
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00002408 dumpBytecode();
msaboff@apple.com95894332014-01-29 19:18:54 +00002409
akling@apple.comce2ec582016-01-29 20:37:52 +00002410 heap()->m_codeBlocks.add(this);
2411 heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +00002412}
2413
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002414#if ENABLE(WEBASSEMBLY)
ossy@webkit.orgda31b4c2015-10-19 16:20:08 +00002415CodeBlock::CodeBlock(VM* vm, Structure* structure, WebAssemblyExecutable* ownerExecutable, JSGlobalObject* globalObject)
2416 : JSCell(*vm, structure)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002417 , m_globalObject(globalObject->vm(), this, globalObject)
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002418 , m_numCalleeLocals(0)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002419 , m_numVars(0)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002420 , m_shouldAlwaysBeInlined(false)
akling@apple.comce2ec582016-01-29 20:37:52 +00002421#if ENABLE(JIT)
2422 , m_capabilityLevelState(DFG::CannotCompile)
2423#endif
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002424 , m_didFailFTLCompilation(false)
2425 , m_hasBeenCompiledWithFTL(false)
akling@apple.comce2ec582016-01-29 20:37:52 +00002426 , m_isConstructor(false)
2427 , m_isStrictMode(false)
akling@apple.comce2ec582016-01-29 20:37:52 +00002428 , m_codeType(FunctionCode)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002429 , m_hasDebuggerStatement(false)
2430 , m_steppingMode(SteppingModeDisabled)
2431 , m_numBreakpoints(0)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002432 , m_ownerExecutable(m_globalObject->vm(), this, ownerExecutable)
ossy@webkit.orgda31b4c2015-10-19 16:20:08 +00002433 , m_vm(vm)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002434 , m_osrExitCounter(0)
2435 , m_optimizationDelayCounter(0)
2436 , m_reoptimizationRetryCounter(0)
ggaren@apple.com05483852015-09-17 00:28:34 +00002437 , m_creationTime(std::chrono::steady_clock::now())
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002438{
akling@apple.comce2ec582016-01-29 20:37:52 +00002439 ASSERT(heap()->isDeferred());
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002440}
2441
2442void CodeBlock::finishCreation(VM& vm, WebAssemblyExecutable*, JSGlobalObject*)
2443{
2444 Base::finishCreation(vm);
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002445
akling@apple.comce2ec582016-01-29 20:37:52 +00002446 heap()->m_codeBlocks.add(this);
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002447}
2448#endif
2449
weinig@apple.com3412bb42008-09-01 21:22:54 +00002450CodeBlock::~CodeBlock()
2451{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00002452 if (m_vm->m_perBytecodeProfiler)
2453 m_vm->m_perBytecodeProfiler->notifyDestruction(this);
fpizlo@apple.com4a81fa42012-12-05 01:26:13 +00002454
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +00002455#if ENABLE(VERBOSE_VALUE_PROFILE)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002456 dumpValueProfiles();
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +00002457#endif
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002458
fpizlo@apple.coma4749642011-09-07 02:05:02 +00002459 // We may be destroyed before any CodeBlocks that refer to us are destroyed.
2460 // Consider that two CodeBlocks become unreachable at the same time. There
2461 // is no guarantee about the order in which the CodeBlocks are destroyed.
2462 // So, if we don't remove incoming calls, and get destroyed before the
2463 // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's
2464 // destructor will try to remove nodes from our (no longer valid) linked list.
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002465 unlinkIncomingCalls();
fpizlo@apple.com594887a2011-09-06 09:23:55 +00002466
2467 // Note that our outgoing calls will be removed from other CodeBlocks'
2468 // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
2469 // destructors.
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +00002470
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002471#if ENABLE(JIT)
sbarati@apple.com9aacac42015-10-08 19:37:28 +00002472 for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
2473 StructureStubInfo* stub = *iter;
2474 stub->aboutToDie();
2475 stub->deref();
2476 }
oliver@apple.com942e37d2010-07-07 01:35:56 +00002477#endif // ENABLE(JIT)
weinig@apple.com3412bb42008-09-01 21:22:54 +00002478}
2479
sbarati@apple.com93c4d332016-04-12 22:42:06 +00002480void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
2481{
2482 ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
2483 size_t count = constants.size();
2484 m_constantRegisters.resizeToFit(count);
2485 bool hasTypeProfiler = !!m_vm->typeProfiler();
2486 for (size_t i = 0; i < count; i++) {
2487 JSValue constant = constants[i].get();
2488
2489 if (!constant.isEmpty()) {
2490 if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(constant)) {
2491 if (hasTypeProfiler) {
2492 ConcurrentJITLocker locker(symbolTable->m_lock);
2493 symbolTable->prepareForTypeProfiling(locker);
2494 }
2495 constant = symbolTable->cloneScopePart(*m_vm);
2496 }
2497 }
2498
2499 m_constantRegisters[i].set(*m_vm, this, constant);
2500 }
2501
2502 m_constantsSourceCodeRepresentation = constantsSourceCodeRepresentation;
2503}
2504
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002505void CodeBlock::setAlternative(VM& vm, CodeBlock* alternative)
2506{
2507 m_alternative.set(vm, this, alternative);
2508}
2509
fpizlo@apple.comc4d54962012-01-10 22:08:47 +00002510void CodeBlock::setNumParameters(int newValue)
2511{
2512 m_numParameters = newValue;
2513
akling@apple.comce2ec582016-01-29 20:37:52 +00002514 m_argumentValueProfiles = RefCountedArray<ValueProfile>(newValue);
fpizlo@apple.comc4d54962012-01-10 22:08:47 +00002515}
2516
oliver@apple.com433d02f2011-04-21 23:08:15 +00002517void EvalCodeCache::visitAggregate(SlotVisitor& visitor)
oliver@apple.comba10bec2011-03-08 23:17:32 +00002518{
2519 EvalCacheMap::iterator end = m_cacheMap.end();
2520 for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
benjamin@webkit.orgee554052012-10-07 23:12:07 +00002521 visitor.append(&ptr->value);
oliver@apple.comba10bec2011-03-08 23:17:32 +00002522}
2523
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002524CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
2525{
2526#if ENABLE(FTL_JIT)
2527 if (jitType() != JITCode::DFGJIT)
2528 return 0;
2529 DFG::JITCode* jitCode = m_jitCode->dfg();
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002530 return jitCode->osrEntryBlock();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002531#else // ENABLE(FTL_JIT)
2532 return 0;
2533#endif // ENABLE(FTL_JIT)
2534}
2535
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002536void CodeBlock::visitWeakly(SlotVisitor& visitor)
ggaren@apple.com51be9a22015-09-09 22:00:58 +00002537{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002538 bool setByMe = m_visitWeaklyHasBeenCalled.compareExchangeStrong(false, true);
ggaren@apple.com156eb592015-09-09 22:06:49 +00002539 if (!setByMe)
2540 return;
2541
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002542 if (Heap::isMarked(this))
ggaren@apple.com7567c162015-10-07 23:10:20 +00002543 return;
ggaren@apple.com893cf142015-10-09 17:54:16 +00002544
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002545 if (shouldVisitStrongly()) {
2546 visitor.appendUnbarrieredReadOnlyPointer(this);
2547 return;
fpizlo@apple.com7c084e02013-09-04 05:48:06 +00002548 }
2549
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002550 // There are two things that may use unconditional finalizers: inline cache clearing
2551 // and jettisoning. The probability of us wanting to do at least one of those things
2552 // is probably quite close to 1. So we add one no matter what and when it runs, it
2553 // figures out whether it has any work to do.
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002554 visitor.addUnconditionalFinalizer(&m_unconditionalFinalizer);
2555
ggaren@apple.com05483852015-09-17 00:28:34 +00002556 if (!JITCode::isOptimizingJIT(jitType()))
2557 return;
2558
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002559 // If we jettison ourselves we'll install our alternative, so make sure that it
2560 // survives GC even if we don't.
2561 visitor.append(&m_alternative);
2562
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +00002563 // There are two things that we use weak reference harvesters for: DFG fixpoint for
2564 // jettisoning, and trying to find structures that would be live based on some
2565 // inline cache. So it makes sense to register them regardless.
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002566 visitor.addWeakReferenceHarvester(&m_weakReferenceHarvester);
mhahnenberg@apple.com7d223bb2014-04-02 23:50:25 +00002567
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002568#if ENABLE(DFG_JIT)
2569 // We get here if we're live in the sense that our owner executable is live,
2570 // but we're not yet live for sure in another sense: we may yet decide that this
2571 // code block should be jettisoned based on its outgoing weak references being
2572 // stale. Set a flag to indicate that we're still assuming that we're dead, and
2573 // perform one round of determining if we're live. The GC may determine, based on
2574 // either us marking additional objects, or by other objects being marked for
2575 // other reasons, that this iteration should run again; it will notify us of this
2576 // decision by calling harvestWeakReferences().
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002577
2578 m_allTransitionsHaveBeenMarked = false;
ggaren@apple.com893cf142015-10-09 17:54:16 +00002579 propagateTransitions(visitor);
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002580
2581 m_jitCode->dfgCommon()->livenessHasBeenProved = false;
oliver@apple.coma1524712013-07-25 04:01:56 +00002582 determineLiveness(visitor);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002583#endif // ENABLE(DFG_JIT)
2584}
2585
commit-queue@webkit.org00eb52f2016-03-01 02:07:12 +00002586size_t CodeBlock::estimatedSize(JSCell* cell)
2587{
2588 CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
2589 size_t extraMemoryAllocated = thisObject->m_instructions.size() * sizeof(Instruction);
2590 if (thisObject->m_jitCode)
2591 extraMemoryAllocated += thisObject->m_jitCode->size();
2592 return Base::estimatedSize(cell) + extraMemoryAllocated;
2593}
2594
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002595void CodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
2596{
2597 CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
2598 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
2599 JSCell::visitChildren(thisObject, visitor);
2600 thisObject->visitChildren(visitor);
2601}
2602
2603void CodeBlock::visitChildren(SlotVisitor& visitor)
2604{
2605 // There are two things that may use unconditional finalizers: inline cache clearing
2606 // and jettisoning. The probability of us wanting to do at least one of those things
2607 // is probably quite close to 1. So we add one no matter what and when it runs, it
2608 // figures out whether it has any work to do.
2609 visitor.addUnconditionalFinalizer(&m_unconditionalFinalizer);
2610
2611 if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
2612 visitor.appendUnbarrieredReadOnlyPointer(otherBlock);
2613
2614 if (m_jitCode)
2615 visitor.reportExtraMemoryVisited(m_jitCode->size());
2616 if (m_instructions.size())
2617 visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
2618
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002619 stronglyVisitStrongReferences(visitor);
2620 stronglyVisitWeakReferences(visitor);
2621
2622 m_allTransitionsHaveBeenMarked = false;
2623 propagateTransitions(visitor);
2624}
2625
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002626bool CodeBlock::shouldVisitStrongly()
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002627{
ggaren@apple.com05483852015-09-17 00:28:34 +00002628 if (Options::forceCodeBlockLiveness())
2629 return true;
2630
2631 if (shouldJettisonDueToOldAge())
2632 return false;
2633
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002634 // Interpreter and Baseline JIT CodeBlocks don't need to be jettisoned when
2635 // their weak references go stale. So if a basline JIT CodeBlock gets
2636 // scanned, we can assume that this means that it's live.
2637 if (!JITCode::isOptimizingJIT(jitType()))
2638 return true;
2639
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002640 return false;
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002641}
2642
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002643bool CodeBlock::shouldJettisonDueToWeakReference()
2644{
ggaren@apple.com05483852015-09-17 00:28:34 +00002645 if (!JITCode::isOptimizingJIT(jitType()))
2646 return false;
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002647 return !Heap::isMarked(this);
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002648}
2649
2650bool CodeBlock::shouldJettisonDueToOldAge()
2651{
commit-queue@webkit.org10294542016-01-26 03:12:29 +00002652 return false;
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00002653}
2654
fpizlo@apple.com4adaa962014-08-06 05:55:39 +00002655#if ENABLE(DFG_JIT)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002656static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition)
2657{
2658 if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get()))
2659 return false;
2660
2661 if (!Heap::isMarked(transition.m_from.get()))
2662 return false;
2663
2664 return true;
2665}
fpizlo@apple.com4adaa962014-08-06 05:55:39 +00002666#endif // ENABLE(DFG_JIT)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002667
oliver@apple.coma1524712013-07-25 04:01:56 +00002668void CodeBlock::propagateTransitions(SlotVisitor& visitor)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002669{
2670 UNUSED_PARAM(visitor);
oliver@apple.coma1524712013-07-25 04:01:56 +00002671
2672 if (m_allTransitionsHaveBeenMarked)
2673 return;
2674
2675 bool allAreMarkedSoFar = true;
2676
oliver@apple.coma1524712013-07-25 04:01:56 +00002677 Interpreter* interpreter = m_vm->interpreter;
2678 if (jitType() == JITCode::InterpreterThunk) {
2679 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
oliver@apple.comc0a31d72013-07-25 04:03:36 +00002680 for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) {
oliver@apple.coma1524712013-07-25 04:01:56 +00002681 Instruction* instruction = &instructions()[propertyAccessInstructions[i]];
2682 switch (interpreter->getOpcodeID(instruction[0].u.opcode)) {
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002683 case op_put_by_id: {
2684 StructureID oldStructureID = instruction[4].u.structureID;
2685 StructureID newStructureID = instruction[6].u.structureID;
2686 if (!oldStructureID || !newStructureID)
2687 break;
2688 Structure* oldStructure =
2689 m_vm->heap.structureIDTable().get(oldStructureID);
2690 Structure* newStructure =
2691 m_vm->heap.structureIDTable().get(newStructureID);
2692 if (Heap::isMarked(oldStructure))
2693 visitor.appendUnbarrieredReadOnlyPointer(newStructure);
oliver@apple.coma1524712013-07-25 04:01:56 +00002694 else
2695 allAreMarkedSoFar = false;
2696 break;
2697 }
2698 default:
2699 break;
2700 }
2701 }
2702 }
oliver@apple.coma1524712013-07-25 04:01:56 +00002703
2704#if ENABLE(JIT)
2705 if (JITCode::isJIT(jitType())) {
fpizlo@apple.comdd39b9e2016-05-04 02:23:28 +00002706 for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter)
2707 allAreMarkedSoFar &= (*iter)->propagateTransitions(visitor);
oliver@apple.coma1524712013-07-25 04:01:56 +00002708 }
2709#endif // ENABLE(JIT)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002710
2711#if ENABLE(DFG_JIT)
oliver@apple.coma1524712013-07-25 04:01:56 +00002712 if (JITCode::isOptimizingJIT(jitType())) {
2713 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
fpizlo@apple.comdd39b9e2016-05-04 02:23:28 +00002714 for (auto& weakReference : dfgCommon->weakStructureReferences)
2715 allAreMarkedSoFar &= weakReference->markIfCheap(visitor);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002716
oliver@apple.com02b179b2013-07-25 03:58:20 +00002717 for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002718 if (shouldMarkTransition(dfgCommon->transitions[i])) {
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002719 // If the following three things are live, then the target of the
2720 // transition is also live:
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002721 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002722 // - This code block. We know it's live already because otherwise
2723 // we wouldn't be scanning ourselves.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002724 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002725 // - The code origin of the transition. Transitions may arise from
2726 // code that was inlined. They are not relevant if the user's
2727 // object that is required for the inlinee to run is no longer
2728 // live.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002729 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002730 // - The source of the transition. The transition checks if some
2731 // heap location holds the source, and if so, stores the target.
2732 // Hence the source must be live for the transition to be live.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002733 //
2734 // We also short-circuit the liveness if the structure is harmless
2735 // to mark (i.e. its global object and prototype are both already
2736 // live).
2737
oliver@apple.com02b179b2013-07-25 03:58:20 +00002738 visitor.append(&dfgCommon->transitions[i].m_to);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002739 } else
2740 allAreMarkedSoFar = false;
2741 }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002742 }
oliver@apple.coma1524712013-07-25 04:01:56 +00002743#endif // ENABLE(DFG_JIT)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002744
oliver@apple.coma1524712013-07-25 04:01:56 +00002745 if (allAreMarkedSoFar)
2746 m_allTransitionsHaveBeenMarked = true;
2747}
2748
2749void CodeBlock::determineLiveness(SlotVisitor& visitor)
2750{
2751 UNUSED_PARAM(visitor);
2752
oliver@apple.coma1524712013-07-25 04:01:56 +00002753#if ENABLE(DFG_JIT)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002754 // Check if we have any remaining work to do.
oliver@apple.coma1524712013-07-25 04:01:56 +00002755 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
oliver@apple.com02b179b2013-07-25 03:58:20 +00002756 if (dfgCommon->livenessHasBeenProved)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002757 return;
2758
2759 // Now check all of our weak references. If all of them are live, then we
2760 // have proved liveness and so we scan our strong references. If at end of
2761 // GC we still have not proved liveness, then this code block is toast.
2762 bool allAreLiveSoFar = true;
oliver@apple.com02b179b2013-07-25 03:58:20 +00002763 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
2764 if (!Heap::isMarked(dfgCommon->weakReferences[i].get())) {
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002765 allAreLiveSoFar = false;
2766 break;
2767 }
2768 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002769 if (allAreLiveSoFar) {
2770 for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) {
2771 if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) {
2772 allAreLiveSoFar = false;
2773 break;
2774 }
2775 }
2776 }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002777
2778 // If some weak references are dead, then this fixpoint iteration was
2779 // unsuccessful.
2780 if (!allAreLiveSoFar)
2781 return;
2782
2783 // All weak references are live. Record this information so we don't
2784 // come back here again, and scan the strong references.
oliver@apple.com02b179b2013-07-25 03:58:20 +00002785 dfgCommon->livenessHasBeenProved = true;
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002786 visitor.appendUnbarrieredReadOnlyPointer(this);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002787#endif // ENABLE(DFG_JIT)
2788}
2789
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002790void CodeBlock::WeakReferenceHarvester::visitWeakReferences(SlotVisitor& visitor)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002791{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002792 CodeBlock* codeBlock =
2793 bitwise_cast<CodeBlock*>(
2794 bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_weakReferenceHarvester));
2795
2796 codeBlock->propagateTransitions(visitor);
2797 codeBlock->determineLiveness(visitor);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002798}
2799
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002800void CodeBlock::finalizeLLIntInlineCaches()
fpizlo@apple.comcf716122012-07-13 06:41:18 +00002801{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002802#if ENABLE(WEBASSEMBLY)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002803 if (m_ownerExecutable->isWebAssemblyExecutable())
2804 return;
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002805#endif
oliver@apple.comc909f5f2012-10-18 23:37:40 +00002806
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002807 Interpreter* interpreter = m_vm->interpreter;
2808 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
2809 for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
2810 Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
2811 switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) {
keith_miller@apple.com8350adf2016-05-24 23:49:57 +00002812 case op_get_by_id:
keith_miller@apple.com785c6512016-05-27 18:36:30 +00002813 case op_get_by_id_proto_load:
2814 case op_get_by_id_unset: {
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002815 StructureID oldStructureID = curInstruction[4].u.structureID;
2816 if (!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID)))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002817 break;
2818 if (Options::verboseOSR())
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002819 dataLogF("Clearing LLInt property access.\n");
keith_miller@apple.com8350adf2016-05-24 23:49:57 +00002820 clearLLIntGetByIdCache(curInstruction);
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002821 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002822 }
2823 case op_put_by_id: {
2824 StructureID oldStructureID = curInstruction[4].u.structureID;
2825 StructureID newStructureID = curInstruction[6].u.structureID;
2826 StructureChain* chain = curInstruction[7].u.structureChain.get();
2827 if ((!oldStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(oldStructureID))) &&
2828 (!newStructureID || Heap::isMarked(m_vm->heap.structureIDTable().get(newStructureID))) &&
2829 (!chain || Heap::isMarked(chain)))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002830 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002831 if (Options::verboseOSR())
2832 dataLogF("Clearing LLInt put transition.\n");
2833 curInstruction[4].u.structureID = 0;
2834 curInstruction[5].u.operand = 0;
2835 curInstruction[6].u.structureID = 0;
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002836 curInstruction[7].u.structureChain.clear();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002837 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00002838 }
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002839 case op_get_array_length:
2840 break;
2841 case op_to_this:
2842 if (!curInstruction[2].u.structure || Heap::isMarked(curInstruction[2].u.structure.get()))
2843 break;
2844 if (Options::verboseOSR())
2845 dataLogF("Clearing LLInt to_this with structure %p.\n", curInstruction[2].u.structure.get());
2846 curInstruction[2].u.structure.clear();
2847 curInstruction[3].u.toThisStatus = merge(
2848 curInstruction[3].u.toThisStatus, ToThisClearedByGC);
2849 break;
2850 case op_create_this: {
2851 auto& cacheWriteBarrier = curInstruction[4].u.jsCell;
2852 if (!cacheWriteBarrier || cacheWriteBarrier.unvalidatedGet() == JSCell::seenMultipleCalleeObjects())
2853 break;
2854 JSCell* cachedFunction = cacheWriteBarrier.get();
2855 if (Heap::isMarked(cachedFunction))
2856 break;
2857 if (Options::verboseOSR())
2858 dataLogF("Clearing LLInt create_this with cached callee %p.\n", cachedFunction);
2859 cacheWriteBarrier.clear();
2860 break;
2861 }
2862 case op_resolve_scope: {
2863 // Right now this isn't strictly necessary. Any symbol tables that this will refer to
2864 // are for outer functions, and we refer to those functions strongly, and they refer
2865 // to the symbol table strongly. But it's nice to be on the safe side.
2866 WriteBarrierBase<SymbolTable>& symbolTable = curInstruction[6].u.symbolTable;
2867 if (!symbolTable || Heap::isMarked(symbolTable.get()))
2868 break;
2869 if (Options::verboseOSR())
2870 dataLogF("Clearing dead symbolTable %p.\n", symbolTable.get());
2871 symbolTable.clear();
2872 break;
2873 }
2874 case op_get_from_scope:
2875 case op_put_to_scope: {
2876 GetPutInfo getPutInfo = GetPutInfo(curInstruction[4].u.operand);
2877 if (getPutInfo.resolveType() == GlobalVar || getPutInfo.resolveType() == GlobalVarWithVarInjectionChecks
2878 || getPutInfo.resolveType() == LocalClosureVar || getPutInfo.resolveType() == GlobalLexicalVar || getPutInfo.resolveType() == GlobalLexicalVarWithVarInjectionChecks)
2879 continue;
2880 WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;
2881 if (!structure || Heap::isMarked(structure.get()))
2882 break;
2883 if (Options::verboseOSR())
2884 dataLogF("Clearing scope access with structure %p.\n", structure.get());
2885 structure.clear();
2886 break;
2887 }
2888 default:
2889 OpcodeID opcodeID = interpreter->getOpcodeID(curInstruction[0].u.opcode);
2890 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 +00002891 }
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00002892 }
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00002893
keith_miller@apple.com8350adf2016-05-24 23:49:57 +00002894 // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set
2895 // then cleared the cache without GCing in between.
2896 m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
2897 return !Heap::isMarked(pair.key);
2898 });
2899
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002900 for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
2901 if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
2902 if (Options::verboseOSR())
2903 dataLog("Clearing LLInt call from ", *this, "\n");
2904 m_llintCallLinkInfos[i].unlink();
fpizlo@apple.com1e89af32012-11-19 02:55:14 +00002905 }
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002906 if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
2907 m_llintCallLinkInfos[i].lastSeenCallee.clear();
2908 }
2909}
2910
2911void CodeBlock::finalizeBaselineJITInlineCaches()
2912{
ggaren@apple.com95bf67e2015-09-11 17:35:59 +00002913#if ENABLE(JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002914 for (auto iter = callLinkInfosBegin(); !!iter; ++iter)
2915 (*iter)->visitWeak(*vm());
2916
2917 for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
2918 StructureStubInfo& stubInfo = **iter;
2919 stubInfo.visitWeakReferences(this);
2920 }
ggaren@apple.com95bf67e2015-09-11 17:35:59 +00002921#endif
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002922}
2923
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002924void CodeBlock::UnconditionalFinalizer::finalizeUnconditionally()
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002925{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002926 CodeBlock* codeBlock = bitwise_cast<CodeBlock*>(
2927 bitwise_cast<char*>(this) - OBJECT_OFFSETOF(CodeBlock, m_unconditionalFinalizer));
2928
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002929#if ENABLE(DFG_JIT)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002930 if (codeBlock->shouldJettisonDueToWeakReference()) {
2931 codeBlock->jettison(Profiler::JettisonDueToWeakReference);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002932 return;
2933 }
2934#endif // ENABLE(DFG_JIT)
oliver@apple.comc909f5f2012-10-18 23:37:40 +00002935
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002936 if (codeBlock->shouldJettisonDueToOldAge()) {
2937 codeBlock->jettison(Profiler::JettisonDueToOldAge);
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002938 return;
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002939 }
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002940
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002941 if (JITCode::couldBeInterpreted(codeBlock->jitType()))
2942 codeBlock->finalizeLLIntInlineCaches();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00002943
2944#if ENABLE(JIT)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002945 if (!!codeBlock->jitCode())
2946 codeBlock->finalizeBaselineJITInlineCaches();
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002947#endif
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00002948}
2949
msaboff@apple.com95894332014-01-29 19:18:54 +00002950void CodeBlock::getStubInfoMap(const ConcurrentJITLocker&, StubInfoMap& result)
2951{
2952#if ENABLE(JIT)
2953 toHashMap(m_stubInfos, getStructureStubInfoCodeOrigin, result);
2954#else
2955 UNUSED_PARAM(result);
2956#endif
2957}
2958
2959void CodeBlock::getStubInfoMap(StubInfoMap& result)
2960{
2961 ConcurrentJITLocker locker(m_lock);
2962 getStubInfoMap(locker, result);
2963}
2964
fpizlo@apple.comba262b22014-03-23 04:34:38 +00002965void CodeBlock::getCallLinkInfoMap(const ConcurrentJITLocker&, CallLinkInfoMap& result)
2966{
2967#if ENABLE(JIT)
2968 toHashMap(m_callLinkInfos, getCallLinkInfoCodeOrigin, result);
2969#else
2970 UNUSED_PARAM(result);
2971#endif
2972}
2973
2974void CodeBlock::getCallLinkInfoMap(CallLinkInfoMap& result)
2975{
2976 ConcurrentJITLocker locker(m_lock);
2977 getCallLinkInfoMap(locker, result);
2978}
2979
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002980void CodeBlock::getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result)
2981{
2982#if ENABLE(JIT)
2983 for (auto* byValInfo : m_byValInfos)
2984 result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo);
2985#else
2986 UNUSED_PARAM(result);
2987#endif
2988}
2989
2990void CodeBlock::getByValInfoMap(ByValInfoMap& result)
2991{
2992 ConcurrentJITLocker locker(m_lock);
2993 getByValInfoMap(locker, result);
2994}
2995
fpizlo@apple.comcf716122012-07-13 06:41:18 +00002996#if ENABLE(JIT)
fpizlo@apple.comb26b5242015-09-10 19:49:36 +00002997StructureStubInfo* CodeBlock::addStubInfo(AccessType accessType)
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00002998{
2999 ConcurrentJITLocker locker(m_lock);
fpizlo@apple.comb26b5242015-09-10 19:49:36 +00003000 return m_stubInfos.add(accessType);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00003001}
3002
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00003003StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
3004{
3005 for (StructureStubInfo* stubInfo : m_stubInfos) {
3006 if (stubInfo->codeOrigin == codeOrigin)
3007 return stubInfo;
3008 }
3009 return nullptr;
3010}
3011
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00003012ByValInfo* CodeBlock::addByValInfo()
3013{
3014 ConcurrentJITLocker locker(m_lock);
3015 return m_byValInfos.add();
3016}
3017
fpizlo@apple.comba262b22014-03-23 04:34:38 +00003018CallLinkInfo* CodeBlock::addCallLinkInfo()
3019{
3020 ConcurrentJITLocker locker(m_lock);
3021 return m_callLinkInfos.add();
3022}
3023
fpizlo@apple.comf7100b62014-03-24 17:29:51 +00003024CallLinkInfo* CodeBlock::getCallLinkInfoForBytecodeIndex(unsigned index)
3025{
3026 for (auto iter = m_callLinkInfos.begin(); !!iter; ++iter) {
msaboff@apple.com203a56e2015-06-24 22:37:30 +00003027 if ((*iter)->codeOrigin() == CodeOrigin(index))
fpizlo@apple.comf7100b62014-03-24 17:29:51 +00003028 return *iter;
3029 }
3030 return nullptr;
3031}
fpizlo@apple.comcf716122012-07-13 06:41:18 +00003032#endif
3033
ggaren@apple.com156eb592015-09-09 22:06:49 +00003034void CodeBlock::visitOSRExitTargets(SlotVisitor& visitor)
3035{
ggaren@apple.com05483852015-09-17 00:28:34 +00003036 // We strongly visit OSR exits targets because we don't want to deal with
3037 // the complexity of generating an exit target CodeBlock on demand and
3038 // guaranteeing that it matches the details of the CodeBlock we compiled
3039 // the OSR exit against.
ggaren@apple.com156eb592015-09-09 22:06:49 +00003040
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003041 visitor.append(&m_alternative);
ggaren@apple.com156eb592015-09-09 22:06:49 +00003042
ggaren@apple.com6520f0c2015-09-09 22:26:16 +00003043#if ENABLE(DFG_JIT)
ggaren@apple.com156eb592015-09-09 22:06:49 +00003044 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
3045 if (dfgCommon->inlineCallFrames) {
ggaren@apple.com05483852015-09-17 00:28:34 +00003046 for (auto* inlineCallFrame : *dfgCommon->inlineCallFrames) {
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003047 ASSERT(inlineCallFrame->baselineCodeBlock);
3048 visitor.append(&inlineCallFrame->baselineCodeBlock);
ggaren@apple.com05483852015-09-17 00:28:34 +00003049 }
ggaren@apple.com156eb592015-09-09 22:06:49 +00003050 }
ggaren@apple.com6520f0c2015-09-09 22:26:16 +00003051#endif
ggaren@apple.com156eb592015-09-09 22:06:49 +00003052}
3053
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00003054void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
3055{
oliver@apple.com433d02f2011-04-21 23:08:15 +00003056 visitor.append(&m_globalObject);
3057 visitor.append(&m_ownerExecutable);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00003058 visitor.append(&m_unlinkedCode);
3059 if (m_rareData)
oliver@apple.com433d02f2011-04-21 23:08:15 +00003060 m_rareData->m_evalCodeCache.visitAggregate(visitor);
3061 visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
barraclough@apple.com306bb122009-08-18 05:34:52 +00003062 for (size_t i = 0; i < m_functionExprs.size(); ++i)
oliver@apple.com433d02f2011-04-21 23:08:15 +00003063 visitor.append(&m_functionExprs[i]);
barraclough@apple.com306bb122009-08-18 05:34:52 +00003064 for (size_t i = 0; i < m_functionDecls.size(); ++i)
oliver@apple.com433d02f2011-04-21 23:08:15 +00003065 visitor.append(&m_functionDecls[i]);
ggaren@apple.comc862eac2013-01-29 05:48:01 +00003066 for (unsigned i = 0; i < m_objectAllocationProfiles.size(); ++i)
3067 m_objectAllocationProfiles[i].visitAggregate(visitor);
fpizlo@apple.comd13163d2011-09-03 05:14:04 +00003068
ggaren@apple.com156eb592015-09-09 22:06:49 +00003069#if ENABLE(DFG_JIT)
3070 if (JITCode::isOptimizingJIT(jitType()))
3071 visitOSRExitTargets(visitor);
3072#endif
3073
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003074 updateAllPredictions();
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00003075}
3076
3077void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor)
3078{
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00003079 UNUSED_PARAM(visitor);
3080
3081#if ENABLE(DFG_JIT)
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00003082 if (!JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00003083 return;
oliver@apple.com02b179b2013-07-25 03:58:20 +00003084
3085 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00003086
oliver@apple.com02b179b2013-07-25 03:58:20 +00003087 for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
3088 if (!!dfgCommon->transitions[i].m_codeOrigin)
3089 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.
3090 visitor.append(&dfgCommon->transitions[i].m_from);
3091 visitor.append(&dfgCommon->transitions[i].m_to);
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00003092 }
3093
oliver@apple.com02b179b2013-07-25 03:58:20 +00003094 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i)
3095 visitor.append(&dfgCommon->weakReferences[i]);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003096
3097 for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i)
3098 visitor.append(&dfgCommon->weakStructureReferences[i]);
ggaren@apple.com51be9a22015-09-09 22:00:58 +00003099
3100 dfgCommon->livenessHasBeenProved = true;
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00003101#endif
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00003102}
3103
fpizlo@apple.com501e6062013-11-01 22:10:52 +00003104CodeBlock* CodeBlock::baselineAlternative()
3105{
3106#if ENABLE(JIT)
3107 CodeBlock* result = this;
3108 while (result->alternative())
3109 result = result->alternative();
3110 RELEASE_ASSERT(result);
3111 RELEASE_ASSERT(JITCode::isBaselineCode(result->jitType()) || result->jitType() == JITCode::None);
3112 return result;
3113#else
3114 return this;
3115#endif
3116}
3117
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003118CodeBlock* CodeBlock::baselineVersion()
3119{
fpizlo@apple.com501e6062013-11-01 22:10:52 +00003120#if ENABLE(JIT)
fpizlo@apple.com669223d2013-09-01 02:02:47 +00003121 if (JITCode::isBaselineCode(jitType()))
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003122 return this;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003123 CodeBlock* result = replacement();
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00003124 if (!result) {
3125 // This can happen if we're creating the original CodeBlock for an executable.
3126 // Assume that we're the baseline CodeBlock.
fpizlo@apple.com501e6062013-11-01 22:10:52 +00003127 RELEASE_ASSERT(jitType() == JITCode::None);
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00003128 return this;
3129 }
fpizlo@apple.com501e6062013-11-01 22:10:52 +00003130 result = result->baselineAlternative();
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003131 return result;
3132#else
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00003133 return this;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003134#endif
3135}
3136
3137#if ENABLE(JIT)
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003138bool CodeBlock::hasOptimizedReplacement(JITCode::JITType typeToReplace)
3139{
3140 return JITCode::isHigherTier(replacement()->jitType(), typeToReplace);
3141}
3142
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003143bool CodeBlock::hasOptimizedReplacement()
3144{
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003145 return hasOptimizedReplacement(jitType());
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003146}
3147#endif
3148
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003149HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler requiredHandler)
mrowe@apple.comf88a4632008-09-07 05:44:58 +00003150{
oliver@apple.com49a2c142013-04-04 21:25:26 +00003151 RELEASE_ASSERT(bytecodeOffset < instructions().size());
sbarati@apple.com36c13402015-09-18 23:37:42 +00003152 return handlerForIndex(bytecodeOffset, requiredHandler);
3153}
weinig@apple.com06885cf2008-12-17 21:25:40 +00003154
sbarati@apple.com36c13402015-09-18 23:37:42 +00003155HandlerInfo* CodeBlock::handlerForIndex(unsigned index, RequiredHandler requiredHandler)
3156{
weinig@apple.com4557e842008-12-09 01:06:14 +00003157 if (!m_rareData)
3158 return 0;
mrowe@apple.comf88a4632008-09-07 05:44:58 +00003159
weinig@apple.com18064e72008-12-10 00:26:13 +00003160 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
3161 for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
mark.lam@apple.com4585ce92015-05-30 00:19:01 +00003162 HandlerInfo& handler = exceptionHandlers[i];
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003163 if ((requiredHandler == RequiredHandler::CatchHandler) && !handler.isCatchHandler())
3164 continue;
3165
weinig@apple.com18064e72008-12-10 00:26:13 +00003166 // Handlers are ordered innermost first, so the first handler we encounter
3167 // that contains the source address is the correct handler to use.
sbarati@apple.com36c13402015-09-18 23:37:42 +00003168 // This index used is either the BytecodeOffset or a CallSiteIndex.
3169 if (handler.start <= index && handler.end > index)
mark.lam@apple.com4585ce92015-05-30 00:19:01 +00003170 return &handler;
mrowe@apple.comf88a4632008-09-07 05:44:58 +00003171 }
3172
3173 return 0;
3174}
3175
sbarati@apple.com9aacac42015-10-08 19:37:28 +00003176CallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite)
3177{
3178#if ENABLE(DFG_JIT)
sbarati@apple.com5bebda72015-11-10 07:48:54 +00003179 RELEASE_ASSERT(JITCode::isOptimizingJIT(jitType()));
sbarati@apple.com9aacac42015-10-08 19:37:28 +00003180 RELEASE_ASSERT(canGetCodeOrigin(originalCallSite));
3181 ASSERT(!!handlerForIndex(originalCallSite.bits()));
3182 CodeOrigin originalOrigin = codeOrigin(originalCallSite);
sbarati@apple.com2697fe72015-10-12 20:37:05 +00003183 return m_jitCode->dfgCommon()->addUniqueCallSiteIndex(originalOrigin);
sbarati@apple.com9aacac42015-10-08 19:37:28 +00003184#else
3185 // We never create new on-the-fly exception handling
3186 // call sites outside the DFG/FTL inline caches.
sbarati@apple.com9bf79cf2015-10-08 20:24:25 +00003187 UNUSED_PARAM(originalCallSite);
sbarati@apple.com9aacac42015-10-08 19:37:28 +00003188 RELEASE_ASSERT_NOT_REACHED();
mark.lam@apple.comceb2fc22015-10-14 16:23:16 +00003189 return CallSiteIndex(0u);
sbarati@apple.com9aacac42015-10-08 19:37:28 +00003190#endif
3191}
3192
3193void CodeBlock::removeExceptionHandlerForCallSite(CallSiteIndex callSiteIndex)
3194{
3195 RELEASE_ASSERT(m_rareData);
3196 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
3197 unsigned index = callSiteIndex.bits();
3198 for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
3199 HandlerInfo& handler = exceptionHandlers[i];
3200 if (handler.start <= index && handler.end > index) {
3201 exceptionHandlers.remove(i);
3202 return;
3203 }
3204 }
3205
3206 RELEASE_ASSERT_NOT_REACHED();
3207}
3208
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00003209unsigned CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00003210{
oliver@apple.com903b0c02013-01-24 01:40:37 +00003211 RELEASE_ASSERT(bytecodeOffset < instructions().size());
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003212 return ownerScriptExecutable()->firstLine() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00003213}
3214
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00003215unsigned CodeBlock::columnNumberForBytecodeOffset(unsigned bytecodeOffset)
oliver@apple.com90b88ae2008-07-19 01:44:24 +00003216{
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00003217 int divot;
3218 int startOffset;
3219 int endOffset;
3220 unsigned line;
3221 unsigned column;
3222 expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
3223 return column;
3224}
3225
3226void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
3227{
3228 m_unlinkedCode->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00003229 divot += m_sourceOffset;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00003230 column += line ? 1 : firstLineColumnOffset();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003231 line += ownerScriptExecutable()->firstLine();
oliver@apple.com90b88ae2008-07-19 01:44:24 +00003232}
3233
mark.lam@apple.com945b1392014-01-23 07:39:58 +00003234bool CodeBlock::hasOpDebugForLineAndColumn(unsigned line, unsigned column)
3235{
3236 Interpreter* interpreter = vm()->interpreter;
3237 const Instruction* begin = instructions().begin();
3238 const Instruction* end = instructions().end();
3239 for (const Instruction* it = begin; it != end;) {
3240 OpcodeID opcodeID = interpreter->getOpcodeID(it->u.opcode);
3241 if (opcodeID == op_debug) {
3242 unsigned bytecodeOffset = it - begin;
3243 int unused;
3244 unsigned opDebugLine;
3245 unsigned opDebugColumn;
3246 expressionRangeForBytecodeOffset(bytecodeOffset, unused, unused, unused, opDebugLine, opDebugColumn);
3247 if (line == opDebugLine && (column == Breakpoint::unspecifiedColumn || column == opDebugColumn))
3248 return true;
3249 }
3250 it += opcodeLengths[opcodeID];
3251 }
3252 return false;
3253}
3254
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00003255void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
weinig@apple.com9d9d25d2008-12-05 20:27:58 +00003256{
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00003257 m_rareCaseProfiles.shrinkToFit();
mark.lam@apple.combad59ea2015-12-18 22:03:30 +00003258 m_resultProfiles.shrinkToFit();
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00003259
3260 if (shrinkMode == EarlyShrink) {
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00003261 m_constantRegisters.shrinkToFit();
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00003262 m_constantsSourceCodeRepresentation.shrinkToFit();
oliver@apple.com9b7647b2013-07-25 04:03:00 +00003263
3264 if (m_rareData) {
oliver@apple.coma14cea52013-07-25 04:03:23 +00003265 m_rareData->m_switchJumpTables.shrinkToFit();
oliver@apple.com9b7647b2013-07-25 04:03:00 +00003266 m_rareData->m_stringSwitchJumpTables.shrinkToFit();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003267 m_rareData->m_liveCalleeLocalsAtYield.shrinkToFit();
oliver@apple.com9b7647b2013-07-25 04:03:00 +00003268 }
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00003269 } // else don't shrink these, because we would have already pointed pointers into these tables.
weinig@apple.com9d9d25d2008-12-05 20:27:58 +00003270}
3271
oliver@apple.com1db480d2011-06-28 01:32:01 +00003272#if ENABLE(JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003273void CodeBlock::linkIncomingCall(ExecState* callerFrame, CallLinkInfo* incoming)
3274{
3275 noticeIncomingCall(callerFrame);
3276 m_incomingCalls.push(incoming);
3277}
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003278
3279void CodeBlock::linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode* incoming)
3280{
3281 noticeIncomingCall(callerFrame);
3282 m_incomingPolymorphicCalls.push(incoming);
3283}
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00003284#endif // ENABLE(JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003285
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003286void CodeBlock::unlinkIncomingCalls()
3287{
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00003288 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
3289 m_incomingLLIntCalls.begin()->unlink();
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00003290#if ENABLE(JIT)
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003291 while (m_incomingCalls.begin() != m_incomingCalls.end())
fpizlo@apple.com7a797262015-09-03 21:11:59 +00003292 m_incomingCalls.begin()->unlink(*vm());
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003293 while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
fpizlo@apple.com7a797262015-09-03 21:11:59 +00003294 m_incomingPolymorphicCalls.begin()->unlink(*vm());
commit-queue@webkit.orgea1f9022013-08-29 16:41:07 +00003295#endif // ENABLE(JIT)
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00003296}
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00003297
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003298void CodeBlock::linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo* incoming)
3299{
3300 noticeIncomingCall(callerFrame);
3301 m_incomingLLIntCalls.push(incoming);
3302}
commit-queue@webkit.orgf76b9d52012-08-20 23:48:00 +00003303
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003304CodeBlock* CodeBlock::newReplacement()
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00003305{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003306 return ownerScriptExecutable()->newReplacementCodeBlockFor(specializationKind());
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00003307}
3308
fpizlo@apple.comaf478bb2011-09-06 23:36:51 +00003309#if ENABLE(JIT)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003310CodeBlock* CodeBlock::replacement()
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003311{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003312 const ClassInfo* classInfo = this->classInfo();
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003313
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003314 if (classInfo == FunctionCodeBlock::info())
3315 return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003316
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003317 if (classInfo == EvalCodeBlock::info())
3318 return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock();
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003319
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003320 if (classInfo == ProgramCodeBlock::info())
3321 return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock();
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003322
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003323 if (classInfo == ModuleProgramCodeBlock::info())
3324 return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003325
3326#if ENABLE(WEBASSEMBLY)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003327 if (classInfo == WebAssemblyCodeBlock::info())
3328 return nullptr;
3329#endif
3330
3331 RELEASE_ASSERT_NOT_REACHED();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003332 return nullptr;
3333}
3334
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003335DFG::CapabilityLevel CodeBlock::computeCapabilityLevel()
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003336{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003337 const ClassInfo* classInfo = this->classInfo();
3338
3339 if (classInfo == FunctionCodeBlock::info()) {
3340 if (m_isConstructor)
3341 return DFG::functionForConstructCapabilityLevel(this);
3342 return DFG::functionForCallCapabilityLevel(this);
3343 }
3344
3345 if (classInfo == EvalCodeBlock::info())
3346 return DFG::evalCapabilityLevel(this);
3347
3348 if (classInfo == ProgramCodeBlock::info())
3349 return DFG::programCapabilityLevel(this);
3350
3351 if (classInfo == ModuleProgramCodeBlock::info())
3352 return DFG::programCapabilityLevel(this);
3353
3354#if ENABLE(WEBASSEMBLY)
3355 if (classInfo == WebAssemblyCodeBlock::info())
3356 return DFG::CannotCompile;
3357#endif
3358
3359 RELEASE_ASSERT_NOT_REACHED();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003360 return DFG::CannotCompile;
3361}
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003362
3363#endif // ENABLE(JIT)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003364
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003365void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003366{
ggaren@apple.com05483852015-09-17 00:28:34 +00003367#if !ENABLE(DFG_JIT)
3368 UNUSED_PARAM(mode);
3369 UNUSED_PARAM(detail);
3370#endif
fpizlo@apple.com4a528d02016-05-11 00:08:50 +00003371
3372 CODEBLOCK_LOG_EVENT(this, "jettison", ("due to ", reason, ", counting = ", mode == CountReoptimization, ", detail = ", pointerDump(detail)));
ggaren@apple.com05483852015-09-17 00:28:34 +00003373
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00003374 RELEASE_ASSERT(reason != Profiler::NotJettisoned);
3375
fpizlo@apple.com580c6f02013-10-30 20:22:40 +00003376#if ENABLE(DFG_JIT)
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00003377 if (DFG::shouldDumpDisassembly()) {
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003378 dataLog("Jettisoning ", *this);
3379 if (mode == CountReoptimization)
3380 dataLog(" and counting reoptimization");
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003381 dataLog(" due to ", reason);
3382 if (detail)
3383 dataLog(", ", *detail);
3384 dataLog(".\n");
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003385 }
3386
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003387 if (reason == Profiler::JettisonDueToWeakReference) {
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00003388 if (DFG::shouldDumpDisassembly()) {
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003389 dataLog(*this, " will be jettisoned because of the following dead references:\n");
3390 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
3391 for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
3392 DFG::WeakReferenceTransition& transition = dfgCommon->transitions[i];
3393 JSCell* origin = transition.m_codeOrigin.get();
3394 JSCell* from = transition.m_from.get();
3395 JSCell* to = transition.m_to.get();
3396 if ((!origin || Heap::isMarked(origin)) && Heap::isMarked(from))
3397 continue;
3398 dataLog(" Transition under ", RawPointer(origin), ", ", RawPointer(from), " -> ", RawPointer(to), ".\n");
3399 }
3400 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
3401 JSCell* weak = dfgCommon->weakReferences[i].get();
3402 if (Heap::isMarked(weak))
3403 continue;
3404 dataLog(" Weak reference ", RawPointer(weak), ".\n");
3405 }
3406 }
3407 }
ggaren@apple.com05483852015-09-17 00:28:34 +00003408#endif // ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003409
akling@apple.comce2ec582016-01-29 20:37:52 +00003410 DeferGCForAWhile deferGC(*heap());
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00003411
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003412 // We want to accomplish two things here:
3413 // 1) Make sure that if this CodeBlock is on the stack right now, then if we return to it
3414 // we should OSR exit at the top of the next bytecode instruction after the return.
3415 // 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 +00003416
ggaren@apple.com05483852015-09-17 00:28:34 +00003417#if ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003418 if (reason != Profiler::JettisonDueToOldAge) {
ggaren@apple.com05483852015-09-17 00:28:34 +00003419 if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get())
3420 compilation->setJettisonReason(reason, detail);
3421
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003422 // This accomplishes (1), and does its own book-keeping about whether it has already happened.
3423 if (!jitCode()->dfgCommon()->invalidate()) {
3424 // We've already been invalidated.
3425 RELEASE_ASSERT(this != replacement());
3426 return;
3427 }
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003428 }
3429
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00003430 if (DFG::shouldDumpDisassembly())
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003431 dataLog(" Did invalidate ", *this, "\n");
3432
3433 // Count the reoptimization if that's what the user wanted.
3434 if (mode == CountReoptimization) {
fpizlo@apple.com78e1b2b2013-11-03 00:32:23 +00003435 // FIXME: Maybe this should call alternative().
3436 // https://bugs.webkit.org/show_bug.cgi?id=123677
3437 baselineAlternative()->countReoptimization();
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00003438 if (DFG::shouldDumpDisassembly())
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003439 dataLog(" Did count reoptimization for ", *this, "\n");
3440 }
3441
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003442 if (this != replacement()) {
3443 // This means that we were never the entrypoint. This can happen for OSR entry code
3444 // blocks.
3445 return;
3446 }
ggaren@apple.com05483852015-09-17 00:28:34 +00003447
3448 if (alternative())
3449 alternative()->optimizeAfterWarmUp();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003450
3451 if (reason != Profiler::JettisonDueToOldAge)
3452 tallyFrequentExitSites();
ggaren@apple.com05483852015-09-17 00:28:34 +00003453#endif // ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00003454
ggaren@apple.com05483852015-09-17 00:28:34 +00003455 // This accomplishes (2).
3456 ownerScriptExecutable()->installCode(
3457 m_globalObject->vm(), alternative(), codeType(), specializationKind());
3458
3459#if ENABLE(DFG_JIT)
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00003460 if (DFG::shouldDumpDisassembly())
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00003461 dataLog(" Did install baseline version of ", *this, "\n");
fpizlo@apple.com580c6f02013-10-30 20:22:40 +00003462#endif // ENABLE(DFG_JIT)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00003463}
fpizlo@apple.com594887a2011-09-06 09:23:55 +00003464
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00003465JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin)
3466{
3467 if (!codeOrigin.inlineCallFrame)
3468 return globalObject();
ggaren@apple.com81def5f2015-10-09 23:10:16 +00003469 return codeOrigin.inlineCallFrame->baselineCodeBlock->globalObject();
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00003470}
3471
msaboff@apple.com4d563e42014-08-16 01:45:40 +00003472class RecursionCheckFunctor {
3473public:
3474 RecursionCheckFunctor(CallFrame* startCallFrame, CodeBlock* codeBlock, unsigned depthToCheck)
3475 : m_startCallFrame(startCallFrame)
3476 , m_codeBlock(codeBlock)
3477 , m_depthToCheck(depthToCheck)
3478 , m_foundStartCallFrame(false)
3479 , m_didRecurse(false)
3480 { }
3481
fpizlo@apple.com39303e02016-04-05 22:17:35 +00003482 StackVisitor::Status operator()(StackVisitor& visitor) const
msaboff@apple.com4d563e42014-08-16 01:45:40 +00003483 {
3484 CallFrame* currentCallFrame = visitor->callFrame();
3485
3486 if (currentCallFrame == m_startCallFrame)
3487 m_foundStartCallFrame = true;
3488
3489 if (m_foundStartCallFrame) {
3490 if (visitor->callFrame()->codeBlock() == m_codeBlock) {
3491 m_didRecurse = true;
3492 return StackVisitor::Done;
3493 }
3494
3495 if (!m_depthToCheck--)
3496 return StackVisitor::Done;
3497 }
3498
3499 return StackVisitor::Continue;
3500 }
3501
3502 bool didRecurse() const { return m_didRecurse; }
3503
3504private:
3505 CallFrame* m_startCallFrame;
3506 CodeBlock* m_codeBlock;
fpizlo@apple.com39303e02016-04-05 22:17:35 +00003507 mutable unsigned m_depthToCheck;
3508 mutable bool m_foundStartCallFrame;
3509 mutable bool m_didRecurse;
msaboff@apple.com4d563e42014-08-16 01:45:40 +00003510};
3511
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003512void CodeBlock::noticeIncomingCall(ExecState* callerFrame)
3513{
3514 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
3515
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003516 if (Options::verboseCallLink())
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003517 dataLog("Noticing call link from ", pointerDump(callerCodeBlock), " to ", *this, "\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003518
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003519#if ENABLE(DFG_JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003520 if (!m_shouldAlwaysBeInlined)
3521 return;
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003522
3523 if (!callerCodeBlock) {
3524 m_shouldAlwaysBeInlined = false;
3525 if (Options::verboseCallLink())
3526 dataLog(" Clearing SABI because caller is native.\n");
3527 return;
3528 }
oliver@apple.com58c86752013-07-25 04:02:40 +00003529
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003530 if (!hasBaselineJITProfiling())
3531 return;
oliver@apple.com58c86752013-07-25 04:02:40 +00003532
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003533 if (!DFG::mightInlineFunction(this))
3534 return;
oliver@apple.com58c86752013-07-25 04:02:40 +00003535
akling@apple.comce2ec582016-01-29 20:37:52 +00003536 if (!canInline(capabilityLevelState()))
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003537 return;
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003538
3539 if (!DFG::isSmallEnoughToInlineCodeInto(callerCodeBlock)) {
3540 m_shouldAlwaysBeInlined = false;
3541 if (Options::verboseCallLink())
3542 dataLog(" Clearing SABI because caller is too large.\n");
3543 return;
3544 }
oliver@apple.com58c86752013-07-25 04:02:40 +00003545
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003546 if (callerCodeBlock->jitType() == JITCode::InterpreterThunk) {
3547 // If the caller is still in the interpreter, then we can't expect inlining to
3548 // happen anytime soon. Assume it's profitable to optimize it separately. This
3549 // ensures that a function is SABI only if it is called no more frequently than
3550 // any of its callers.
3551 m_shouldAlwaysBeInlined = false;
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003552 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003553 dataLog(" Clearing SABI because caller is in LLInt.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003554 return;
3555 }
3556
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003557 if (JITCode::isOptimizingJIT(callerCodeBlock->jitType())) {
3558 m_shouldAlwaysBeInlined = false;
3559 if (Options::verboseCallLink())
3560 dataLog(" Clearing SABI bcause caller was already optimized.\n");
3561 return;
3562 }
3563
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003564 if (callerCodeBlock->codeType() != FunctionCode) {
3565 // If the caller is either eval or global code, assume that that won't be
3566 // optimized anytime soon. For eval code this is particularly true since we
3567 // delay eval optimization by a *lot*.
3568 m_shouldAlwaysBeInlined = false;
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003569 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003570 dataLog(" Clearing SABI because caller is not a function.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003571 return;
3572 }
msaboff@apple.com4d563e42014-08-16 01:45:40 +00003573
3574 // Recursive calls won't be inlined.
3575 RecursionCheckFunctor functor(callerFrame, this, Options::maximumInliningDepth());
3576 vm()->topCallFrame->iterate(functor);
3577
3578 if (functor.didRecurse()) {
3579 if (Options::verboseCallLink())
3580 dataLog(" Clearing SABI because recursion was detected.\n");
3581 m_shouldAlwaysBeInlined = false;
3582 return;
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003583 }
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003584
akling@apple.comce2ec582016-01-29 20:37:52 +00003585 if (callerCodeBlock->capabilityLevelState() == DFG::CapabilityLevelNotSet) {
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00003586 dataLog("In call from ", *callerCodeBlock, " ", callerFrame->codeOrigin(), " to ", *this, ": caller's DFG capability level is not set.\n");
3587 CRASH();
3588 }
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003589
akling@apple.comce2ec582016-01-29 20:37:52 +00003590 if (canCompile(callerCodeBlock->capabilityLevelState()))
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003591 return;
3592
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00003593 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00003594 dataLog(" Clearing SABI because the caller is not a DFG candidate.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003595
3596 m_shouldAlwaysBeInlined = false;
oliver@apple.com58c86752013-07-25 04:02:40 +00003597#endif
oliver@apple.comd2cdd312013-07-25 04:01:00 +00003598}
3599
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003600unsigned CodeBlock::reoptimizationRetryCounter() const
3601{
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00003602#if ENABLE(JIT)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003603 ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax());
3604 return m_reoptimizationRetryCounter;
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00003605#else
3606 return 0;
3607#endif // ENABLE(JIT)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003608}
3609
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00003610#if ENABLE(JIT)
msaboff@apple.com02085462015-09-10 17:47:16 +00003611void CodeBlock::setCalleeSaveRegisters(RegisterSet calleeSaveRegisters)
3612{
3613 m_calleeSaveRegisters = std::make_unique<RegisterAtOffsetList>(calleeSaveRegisters);
3614}
3615
3616void CodeBlock::setCalleeSaveRegisters(std::unique_ptr<RegisterAtOffsetList> registerAtOffsetList)
3617{
aestes@apple.com13aae082016-01-02 08:03:08 +00003618 m_calleeSaveRegisters = WTFMove(registerAtOffsetList);
msaboff@apple.com02085462015-09-10 17:47:16 +00003619}
3620
3621static size_t roundCalleeSaveSpaceAsVirtualRegisters(size_t calleeSaveRegisters)
3622{
3623 static const unsigned cpuRegisterSize = sizeof(void*);
3624 return (WTF::roundUpToMultipleOf(sizeof(Register), calleeSaveRegisters * cpuRegisterSize) / sizeof(Register));
3625
3626}
3627
3628size_t CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()
3629{
3630 return roundCalleeSaveSpaceAsVirtualRegisters(numberOfLLIntBaselineCalleeSaveRegisters());
3631}
3632
3633size_t CodeBlock::calleeSaveSpaceAsVirtualRegisters()
3634{
3635 return roundCalleeSaveSpaceAsVirtualRegisters(m_calleeSaveRegisters->size());
3636}
3637
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003638void CodeBlock::countReoptimization()
3639{
3640 m_reoptimizationRetryCounter++;
3641 if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax())
3642 m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax();
3643}
3644
oliver@apple.com37172f82013-07-25 04:01:17 +00003645unsigned CodeBlock::numberOfDFGCompiles()
3646{
3647 ASSERT(JITCode::isBaselineCode(jitType()));
msaboff@apple.com95894332014-01-29 19:18:54 +00003648 if (Options::testTheFTL()) {
3649 if (m_didFailFTLCompilation)
3650 return 1000000;
3651 return (m_hasBeenCompiledWithFTL ? 1 : 0) + m_reoptimizationRetryCounter;
3652 }
oliver@apple.com37172f82013-07-25 04:01:17 +00003653 return (JITCode::isOptimizingJIT(replacement()->jitType()) ? 1 : 0) + m_reoptimizationRetryCounter;
3654}
3655
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00003656int32_t CodeBlock::codeTypeThresholdMultiplier() const
3657{
3658 if (codeType() == EvalCode)
3659 return Options::evalThresholdMultiplier();
3660
3661 return 1;
3662}
3663
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003664double CodeBlock::optimizationThresholdScalingFactor()
3665{
ggaren@apple.comf0193982013-04-03 01:41:16 +00003666 // This expression arises from doing a least-squares fit of
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003667 //
3668 // F[x_] =: a * Sqrt[x + b] + Abs[c * x] + d
3669 //
3670 // against the data points:
3671 //
3672 // x F[x_]
3673 // 10 0.9 (smallest reasonable code block)
3674 // 200 1.0 (typical small-ish code block)
3675 // 320 1.2 (something I saw in 3d-cube that I wanted to optimize)
3676 // 1268 5.0 (something I saw in 3d-cube that I didn't want to optimize)
3677 // 4000 5.5 (random large size, used to cause the function to converge to a shallow curve of some sort)
3678 // 10000 6.0 (similar to above)
3679 //
ggaren@apple.comf0193982013-04-03 01:41:16 +00003680 // I achieve the minimization using the following Mathematica code:
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003681 //
3682 // MyFunctionTemplate[x_, a_, b_, c_, d_] := a*Sqrt[x + b] + Abs[c*x] + d
3683 //
3684 // samples = {{10, 0.9}, {200, 1}, {320, 1.2}, {1268, 5}, {4000, 5.5}, {10000, 6}}
3685 //
3686 // solution =
3687 // Minimize[Plus @@ ((MyFunctionTemplate[#[[1]], a, b, c, d] - #[[2]])^2 & /@ samples),
3688 // {a, b, c, d}][[2]]
3689 //
3690 // And the code below (to initialize a, b, c, d) is generated by:
3691 //
3692 // Print["const double " <> ToString[#[[1]]] <> " = " <>
3693 // If[#[[2]] < 0.00001, "0.0", ToString[#[[2]]]] <> ";"] & /@ solution
3694 //
3695 // We've long known the following to be true:
3696 // - Small code blocks are cheap to optimize and so we should do it sooner rather
3697 // than later.
3698 // - Large code blocks are expensive to optimize and so we should postpone doing so,
3699 // and sometimes have a large enough threshold that we never optimize them.
3700 // - The difference in cost is not totally linear because (a) just invoking the
3701 // DFG incurs some base cost and (b) for large code blocks there is enough slop
3702 // in the correlation between instruction count and the actual compilation cost
3703 // that for those large blocks, the instruction count should not have a strong
3704 // influence on our threshold.
3705 //
3706 // I knew the goals but I didn't know how to achieve them; so I picked an interesting
3707 // example where the heuristics were right (code block in 3d-cube with instruction
3708 // count 320, which got compiled early as it should have been) and one where they were
3709 // totally wrong (code block in 3d-cube with instruction count 1268, which was expensive
3710 // to compile and didn't run often enough to warrant compilation in my opinion), and
3711 // then threw in additional data points that represented my own guess of what our
3712 // heuristics should do for some round-numbered examples.
3713 //
3714 // The expression to which I decided to fit the data arose because I started with an
3715 // affine function, and then did two things: put the linear part in an Abs to ensure
3716 // that the fit didn't end up choosing a negative value of c (which would result in
3717 // the function turning over and going negative for large x) and I threw in a Sqrt
3718 // term because Sqrt represents my intution that the function should be more sensitive
3719 // to small changes in small values of x, but less sensitive when x gets large.
ggaren@apple.comf0193982013-04-03 01:41:16 +00003720
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003721 // Note that the current fit essentially eliminates the linear portion of the
3722 // expression (c == 0.0).
3723 const double a = 0.061504;
3724 const double b = 1.02406;
3725 const double c = 0.0;
3726 const double d = 0.825914;
3727
ggaren@apple.comf0193982013-04-03 01:41:16 +00003728 double instructionCount = this->instructionCount();
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003729
ggaren@apple.comf0193982013-04-03 01:41:16 +00003730 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 +00003731
ggaren@apple.comf0193982013-04-03 01:41:16 +00003732 double result = d + a * sqrt(instructionCount + b) + c * instructionCount;
fpizlo@apple.com3ce93232014-03-03 05:42:29 +00003733
3734 result *= codeTypeThresholdMultiplier();
3735
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003736 if (Options::verboseOSR()) {
3737 dataLog(
3738 *this, ": instruction count is ", instructionCount,
3739 ", scaling execution counter by ", result, " * ", codeTypeThresholdMultiplier(),
3740 "\n");
3741 }
fpizlo@apple.com3ce93232014-03-03 05:42:29 +00003742 return result;
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003743}
3744
3745static int32_t clipThreshold(double threshold)
3746{
3747 if (threshold < 1.0)
3748 return 1;
3749
3750 if (threshold > static_cast<double>(std::numeric_limits<int32_t>::max()))
3751 return std::numeric_limits<int32_t>::max();
3752
3753 return static_cast<int32_t>(threshold);
3754}
3755
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003756int32_t CodeBlock::adjustedCounterValue(int32_t desiredThreshold)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003757{
3758 return clipThreshold(
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003759 static_cast<double>(desiredThreshold) *
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003760 optimizationThresholdScalingFactor() *
3761 (1 << reoptimizationRetryCounter()));
3762}
3763
3764bool CodeBlock::checkIfOptimizationThresholdReached()
3765{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003766#if ENABLE(DFG_JIT)
msaboff@apple.com95894332014-01-29 19:18:54 +00003767 if (DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull()) {
fpizlo@apple.com6931c472013-08-29 23:45:26 +00003768 if (worklist->compilationState(DFG::CompilationKey(this, DFG::DFGMode))
3769 == DFG::Worklist::Compiled) {
3770 optimizeNextInvocation();
3771 return true;
3772 }
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003773 }
3774#endif
3775
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003776 return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
3777}
3778
3779void CodeBlock::optimizeNextInvocation()
3780{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003781 if (Options::verboseOSR())
3782 dataLog(*this, ": Optimizing next invocation.\n");
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003783 m_jitExecuteCounter.setNewThreshold(0, this);
3784}
3785
3786void CodeBlock::dontOptimizeAnytimeSoon()
3787{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003788 if (Options::verboseOSR())
3789 dataLog(*this, ": Not optimizing anytime soon.\n");
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003790 m_jitExecuteCounter.deferIndefinitely();
3791}
3792
3793void CodeBlock::optimizeAfterWarmUp()
3794{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003795 if (Options::verboseOSR())
3796 dataLog(*this, ": Optimizing after warm-up.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00003797#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003798 m_jitExecuteCounter.setNewThreshold(
3799 adjustedCounterValue(Options::thresholdForOptimizeAfterWarmUp()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00003800#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003801}
3802
3803void CodeBlock::optimizeAfterLongWarmUp()
3804{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003805 if (Options::verboseOSR())
3806 dataLog(*this, ": Optimizing after long warm-up.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00003807#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003808 m_jitExecuteCounter.setNewThreshold(
3809 adjustedCounterValue(Options::thresholdForOptimizeAfterLongWarmUp()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00003810#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003811}
3812
3813void CodeBlock::optimizeSoon()
3814{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003815 if (Options::verboseOSR())
3816 dataLog(*this, ": Optimizing soon.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00003817#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00003818 m_jitExecuteCounter.setNewThreshold(
3819 adjustedCounterValue(Options::thresholdForOptimizeSoon()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00003820#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003821}
3822
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003823void CodeBlock::forceOptimizationSlowPathConcurrently()
3824{
3825 if (Options::verboseOSR())
3826 dataLog(*this, ": Forcing slow path concurrently.\n");
3827 m_jitExecuteCounter.forceSlowPathConcurrently();
3828}
3829
oliver@apple.com58c86752013-07-25 04:02:40 +00003830#if ENABLE(DFG_JIT)
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003831void CodeBlock::setOptimizationThresholdBasedOnCompilationResult(CompilationResult result)
3832{
fpizlo@apple.come7a417d2014-05-08 21:51:03 +00003833 JITCode::JITType type = jitType();
3834 if (type != JITCode::BaselineJIT) {
3835 dataLog(*this, ": expected to have baseline code but have ", type, "\n");
3836 RELEASE_ASSERT_NOT_REACHED();
3837 }
3838
3839 CodeBlock* theReplacement = replacement();
3840 if ((result == CompilationSuccessful) != (theReplacement != this)) {
3841 dataLog(*this, ": we have result = ", result, " but ");
3842 if (theReplacement == this)
3843 dataLog("we are our own replacement.\n");
3844 else
3845 dataLog("our replacement is ", pointerDump(theReplacement), "\n");
3846 RELEASE_ASSERT_NOT_REACHED();
3847 }
3848
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003849 switch (result) {
3850 case CompilationSuccessful:
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00003851 RELEASE_ASSERT(JITCode::isOptimizingJIT(replacement()->jitType()));
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003852 optimizeNextInvocation();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003853 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003854 case CompilationFailed:
3855 dontOptimizeAnytimeSoon();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003856 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003857 case CompilationDeferred:
3858 // We'd like to do dontOptimizeAnytimeSoon() but we cannot because
3859 // forceOptimizationSlowPathConcurrently() is inherently racy. It won't
3860 // necessarily guarantee anything. So, we make sure that even if that
3861 // function ends up being a no-op, we still eventually retry and realize
3862 // that we have optimized code ready.
3863 optimizeAfterWarmUp();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003864 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003865 case CompilationInvalidated:
3866 // Retry with exponential backoff.
3867 countReoptimization();
3868 optimizeAfterWarmUp();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003869 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003870 }
fpizlo@apple.come7a417d2014-05-08 21:51:03 +00003871
3872 dataLog("Unrecognized result: ", static_cast<int>(result), "\n");
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00003873 RELEASE_ASSERT_NOT_REACHED();
oliver@apple.com284cc3d2013-07-25 04:00:33 +00003874}
3875
oliver@apple.com807e7e12013-07-25 20:22:45 +00003876#endif
3877
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003878uint32_t CodeBlock::adjustedExitCountThreshold(uint32_t desiredThreshold)
3879{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00003880 ASSERT(JITCode::isOptimizingJIT(jitType()));
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003881 // Compute this the lame way so we don't saturate. This is called infrequently
3882 // enough that this loop won't hurt us.
3883 unsigned result = desiredThreshold;
3884 for (unsigned n = baselineVersion()->reoptimizationRetryCounter(); n--;) {
3885 unsigned newResult = result << 1;
3886 if (newResult < result)
3887 return std::numeric_limits<uint32_t>::max();
3888 result = newResult;
3889 }
3890 return result;
3891}
3892
3893uint32_t CodeBlock::exitCountThresholdForReoptimization()
3894{
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00003895 return adjustedExitCountThreshold(Options::osrExitCountForReoptimization() * codeTypeThresholdMultiplier());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003896}
3897
3898uint32_t CodeBlock::exitCountThresholdForReoptimizationFromLoop()
3899{
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00003900 return adjustedExitCountThreshold(Options::osrExitCountForReoptimizationFromLoop() * codeTypeThresholdMultiplier());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00003901}
3902
3903bool CodeBlock::shouldReoptimizeNow()
3904{
3905 return osrExitCounter() >= exitCountThresholdForReoptimization();
3906}
3907
3908bool CodeBlock::shouldReoptimizeFromLoopNow()
3909{
3910 return osrExitCounter() >= exitCountThresholdForReoptimizationFromLoop();
3911}
3912#endif
3913
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00003914ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset)
3915{
3916 for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) {
3917 if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset)
3918 return &m_arrayProfiles[i];
3919 }
3920 return 0;
3921}
3922
3923ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset)
3924{
3925 ArrayProfile* result = getArrayProfile(bytecodeOffset);
3926 if (result)
3927 return result;
3928 return addArrayProfile(bytecodeOffset);
3929}
3930
fpizlo@apple.com8e470a22015-09-21 20:10:04 +00003931#if ENABLE(DFG_JIT)
3932Vector<CodeOrigin, 0, UnsafeVectorOverflow>& CodeBlock::codeOrigins()
3933{
3934 return m_jitCode->dfgCommon()->codeOrigins;
3935}
3936
3937size_t CodeBlock::numberOfDFGIdentifiers() const
3938{
3939 if (!JITCode::isOptimizingJIT(jitType()))
3940 return 0;
3941
3942 return m_jitCode->dfgCommon()->dfgIdentifiers.size();
3943}
3944
3945const Identifier& CodeBlock::identifier(int index) const
3946{
3947 size_t unlinkedIdentifiers = m_unlinkedCode->numberOfIdentifiers();
3948 if (static_cast<unsigned>(index) < unlinkedIdentifiers)
3949 return m_unlinkedCode->identifier(index);
3950 ASSERT(JITCode::isOptimizingJIT(jitType()));
3951 return m_jitCode->dfgCommon()->dfgIdentifiers[index - unlinkedIdentifiers];
3952}
3953#endif // ENABLE(DFG_JIT)
3954
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003955void CodeBlock::updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003956{
oliver@apple.comd2056662013-07-25 04:00:37 +00003957 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +00003958
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003959 numberOfLiveNonArgumentValueProfiles = 0;
3960 numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
3961 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
3962 ValueProfile* profile = getFromAllValueProfiles(i);
3963 unsigned numSamples = profile->totalNumberOfSamples();
3964 if (numSamples > ValueProfile::numberOfBuckets)
3965 numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
3966 numberOfSamplesInProfiles += numSamples;
3967 if (profile->m_bytecodeOffset < 0) {
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003968 profile->computeUpdatedPrediction(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003969 continue;
3970 }
3971 if (profile->numberOfSamples() || profile->m_prediction != SpecNone)
3972 numberOfLiveNonArgumentValueProfiles++;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003973 profile->computeUpdatedPrediction(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003974 }
3975
3976#if ENABLE(DFG_JIT)
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003977 m_lazyOperandValueProfiles.computeUpdatedPredictions(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003978#endif
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003979}
3980
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003981void CodeBlock::updateAllValueProfilePredictions()
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003982{
3983 unsigned ignoredValue1, ignoredValue2;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003984 updateAllPredictionsAndCountLiveness(ignoredValue1, ignoredValue2);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003985}
3986
oliver@apple.com58cdc332013-07-25 04:04:59 +00003987void CodeBlock::updateAllArrayPredictions()
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003988{
oliver@apple.comd2056662013-07-25 04:00:37 +00003989 ConcurrentJITLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +00003990
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00003991 for (unsigned i = m_arrayProfiles.size(); i--;)
oliver@apple.com58cdc332013-07-25 04:04:59 +00003992 m_arrayProfiles[i].computeUpdatedPrediction(locker, this);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00003993
3994 // Don't count these either, for similar reasons.
3995 for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
3996 m_arrayAllocationProfiles[i].updateIndexingType();
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00003997}
3998
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00003999void CodeBlock::updateAllPredictions()
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00004000{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00004001#if ENABLE(WEBASSEMBLY)
4002 if (m_ownerExecutable->isWebAssemblyExecutable())
4003 return;
4004#endif
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00004005 updateAllValueProfilePredictions();
oliver@apple.com58cdc332013-07-25 04:04:59 +00004006 updateAllArrayPredictions();
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00004007}
4008
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004009bool CodeBlock::shouldOptimizeNow()
4010{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00004011 if (Options::verboseOSR())
4012 dataLog("Considering optimizing ", *this, "...\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004013
commit-queue@webkit.orgfbda60c2012-07-03 19:19:22 +00004014 if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay())
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004015 return true;
4016
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00004017 updateAllArrayPredictions();
4018
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00004019 unsigned numberOfLiveNonArgumentValueProfiles;
4020 unsigned numberOfSamplesInProfiles;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00004021 updateAllPredictionsAndCountLiveness(numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004022
oliver@apple.com284cc3d2013-07-25 04:00:33 +00004023 if (Options::verboseOSR()) {
4024 dataLogF(
4025 "Profile hotness: %lf (%u / %u), %lf (%u / %u)\n",
4026 (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(),
4027 numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(),
4028 (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(),
4029 numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles());
4030 }
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004031
commit-queue@webkit.orgfbda60c2012-07-03 19:19:22 +00004032 if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate())
4033 && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate())
4034 && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay())
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004035 return true;
4036
fpizlo@apple.com4043e812011-11-06 11:54:59 +00004037 ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max());
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004038 m_optimizationDelayCounter++;
4039 optimizeAfterWarmUp();
4040 return false;
4041}
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004042
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00004043#if ENABLE(DFG_JIT)
4044void CodeBlock::tallyFrequentExitSites()
4045{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00004046 ASSERT(JITCode::isOptimizingJIT(jitType()));
4047 ASSERT(alternative()->jitType() == JITCode::BaselineJIT);
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00004048
4049 CodeBlock* profiledBlock = alternative();
4050
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00004051 switch (jitType()) {
oliver@apple.comea771492013-07-25 03:58:38 +00004052 case JITCode::DFGJIT: {
4053 DFG::JITCode* jitCode = m_jitCode->dfg();
4054 for (unsigned i = 0; i < jitCode->osrExit.size(); ++i) {
4055 DFG::OSRExit& exit = jitCode->osrExit[i];
benjamin@webkit.org6f63a8b2015-02-18 07:04:10 +00004056 exit.considerAddingAsFrequentExitSite(profiledBlock);
oliver@apple.comea771492013-07-25 03:58:38 +00004057 }
4058 break;
4059 }
oliver@apple.com0c1b13e2013-07-25 03:58:43 +00004060
4061#if ENABLE(FTL_JIT)
oliver@apple.comea771492013-07-25 03:58:38 +00004062 case JITCode::FTLJIT: {
4063 // There is no easy way to avoid duplicating this code since the FTL::JITCode::osrExit
4064 // vector contains a totally different type, that just so happens to behave like
4065 // DFG::JITCode::osrExit.
oliver@apple.comea771492013-07-25 03:58:38 +00004066 FTL::JITCode* jitCode = m_jitCode->ftl();
4067 for (unsigned i = 0; i < jitCode->osrExit.size(); ++i) {
4068 FTL::OSRExit& exit = jitCode->osrExit[i];
benjamin@webkit.org6f63a8b2015-02-18 07:04:10 +00004069 exit.considerAddingAsFrequentExitSite(profiledBlock);
oliver@apple.comea771492013-07-25 03:58:38 +00004070 }
oliver@apple.comea771492013-07-25 03:58:38 +00004071 break;
oliver@apple.com0c1b13e2013-07-25 03:58:43 +00004072 }
4073#endif
oliver@apple.comea771492013-07-25 03:58:38 +00004074
4075 default:
4076 RELEASE_ASSERT_NOT_REACHED();
4077 break;
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00004078 }
4079}
4080#endif // ENABLE(DFG_JIT)
4081
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004082#if ENABLE(VERBOSE_VALUE_PROFILE)
4083void CodeBlock::dumpValueProfiles()
4084{
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00004085 dataLog("ValueProfile for ", *this, ":\n");
fpizlo@apple.com086d2af2011-12-21 02:29:15 +00004086 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
4087 ValueProfile* profile = getFromAllValueProfiles(i);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004088 if (profile->m_bytecodeOffset < 0) {
4089 ASSERT(profile->m_bytecodeOffset == -1);
fpizlo@apple.com01902c82012-11-22 04:23:36 +00004090 dataLogF(" arg = %u: ", i);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004091 } else
fpizlo@apple.com01902c82012-11-22 04:23:36 +00004092 dataLogF(" bc = %d: ", profile->m_bytecodeOffset);
fpizlo@apple.com62336162012-06-07 01:35:59 +00004093 if (!profile->numberOfSamples() && profile->m_prediction == SpecNone) {
fpizlo@apple.com01902c82012-11-22 04:23:36 +00004094 dataLogF("<empty>\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004095 continue;
4096 }
fpizlo@apple.comd095b242012-02-12 03:21:32 +00004097 profile->dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +00004098 dataLogF("\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004099 }
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00004100 dataLog("RareCaseProfile for ", *this, ":\n");
barraclough@apple.come32d4ec2011-09-21 22:43:11 +00004101 for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) {
4102 RareCaseProfile* profile = rareCaseProfile(i);
fpizlo@apple.com01902c82012-11-22 04:23:36 +00004103 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
fpizlo@apple.com9b0b31e2011-09-19 22:27:38 +00004104 }
mark.lam@apple.combad59ea2015-12-18 22:03:30 +00004105 dataLog("ResultProfile for ", *this, ":\n");
4106 for (unsigned i = 0; i < numberOfResultProfiles(); ++i) {
4107 const ResultProfile& profile = *resultProfile(i);
4108 dataLog(" bc = ", profile.bytecodeOffset(), ": ", profile, "\n");
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00004109 }
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004110}
fpizlo@apple.com8618e4b2012-07-03 01:27:16 +00004111#endif // ENABLE(VERBOSE_VALUE_PROFILE)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00004112
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00004113unsigned CodeBlock::frameRegisterCount()
4114{
4115 switch (jitType()) {
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00004116 case JITCode::InterpreterThunk:
4117 return LLInt::frameRegisterCountFor(this);
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00004118
4119#if ENABLE(JIT)
4120 case JITCode::BaselineJIT:
4121 return JIT::frameRegisterCountFor(this);
4122#endif // ENABLE(JIT)
4123
4124#if ENABLE(DFG_JIT)
4125 case JITCode::DFGJIT:
4126 case JITCode::FTLJIT:
4127 return jitCode()->dfgCommon()->frameRegisterCount;
4128#endif // ENABLE(DFG_JIT)
4129
4130 default:
4131 RELEASE_ASSERT_NOT_REACHED();
4132 return 0;
4133 }
4134}
4135
msaboff@apple.com95894332014-01-29 19:18:54 +00004136int CodeBlock::stackPointerOffset()
4137{
4138 return virtualRegisterForLocal(frameRegisterCount() - 1).offset();
4139}
4140
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00004141size_t CodeBlock::predictedMachineCodeSize()
4142{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00004143 // This will be called from CodeBlock::CodeBlock before either m_vm or the
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00004144 // instructions have been initialized. It's OK to return 0 because what will really
4145 // matter is the recomputation of this value when the slow path is triggered.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00004146 if (!m_vm)
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00004147 return 0;
4148
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00004149 if (!m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT)
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00004150 return 0; // It's as good of a prediction as we'll get.
4151
4152 // Be conservative: return a size that will be an overestimation 84% of the time.
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00004153 double multiplier = m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.mean() +
4154 m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.standardDeviation();
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00004155
4156 // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing
4157 // here is OK, since this whole method is just a heuristic.
4158 if (multiplier < 0 || multiplier > 1000)
4159 return 0;
4160
4161 double doubleResult = multiplier * m_instructions.size();
4162
4163 // Be even more paranoid: silently reject values that won't fit into a size_t. If
4164 // the function is so huge that we can't even fit it into virtual memory then we
4165 // should probably have some other guards in place to prevent us from even getting
4166 // to this point.
4167 if (doubleResult > std::numeric_limits<size_t>::max())
4168 return 0;
4169
4170 return static_cast<size_t>(doubleResult);
4171}
4172
fpizlo@apple.comc828f142011-10-25 21:56:31 +00004173bool CodeBlock::usesOpcode(OpcodeID opcodeID)
4174{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00004175 Interpreter* interpreter = vm()->interpreter;
fpizlo@apple.comc828f142011-10-25 21:56:31 +00004176 Instruction* instructionsBegin = instructions().begin();
4177 unsigned instructionCount = instructions().size();
4178
4179 for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
4180 switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
4181#define DEFINE_OP(curOpcode, length) \
4182 case curOpcode: \
4183 if (curOpcode == opcodeID) \
4184 return true; \
4185 bytecodeOffset += length; \
4186 break;
4187 FOR_EACH_OPCODE_ID(DEFINE_OP)
4188#undef DEFINE_OP
4189 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00004190 RELEASE_ASSERT_NOT_REACHED();
fpizlo@apple.comc828f142011-10-25 21:56:31 +00004191 break;
4192 }
4193 }
4194
4195 return false;
4196}
fpizlo@apple.comc828f142011-10-25 21:56:31 +00004197
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00004198String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
oliver@apple.coma08210b2012-07-18 23:26:06 +00004199{
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00004200 for (unsigned i = 0; i < m_constantRegisters.size(); i++) {
4201 if (m_constantRegisters[i].get().isEmpty())
4202 continue;
4203 if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(m_constantRegisters[i].get())) {
4204 ConcurrentJITLocker locker(symbolTable->m_lock);
4205 auto end = symbolTable->end(locker);
4206 for (auto ptr = symbolTable->begin(locker); ptr != end; ++ptr) {
4207 if (ptr->value.varOffset() == VarOffset(virtualRegister)) {
4208 // FIXME: This won't work from the compilation thread.
4209 // https://bugs.webkit.org/show_bug.cgi?id=115300
4210 return ptr->key.get();
4211 }
4212 }
oliver@apple.comf72e22e2013-07-25 03:59:04 +00004213 }
oliver@apple.coma08210b2012-07-18 23:26:06 +00004214 }
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00004215 if (virtualRegister == thisRegister())
benjamin@webkit.org762e2c62012-09-04 21:19:25 +00004216 return ASCIILiteral("this");
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00004217 if (virtualRegister.isArgument())
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00004218 return String::format("arguments[%3d]", virtualRegister.toArgument());
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00004219
oliver@apple.coma08210b2012-07-18 23:26:06 +00004220 return "";
4221}
4222
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00004223ValueProfile* CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset)
4224{
4225 ValueProfile* result = binarySearch<ValueProfile, int>(
4226 m_valueProfiles, m_valueProfiles.size(), bytecodeOffset,
4227 getValueProfileBytecodeOffset<ValueProfile>);
4228 ASSERT(result->m_bytecodeOffset != -1);
4229 ASSERT(instructions()[bytecodeOffset + opcodeLength(
4230 m_vm->interpreter->getOpcodeID(
4231 instructions()[bytecodeOffset].u.opcode)) - 1].u.profile == result);
4232 return result;
4233}
4234
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00004235void CodeBlock::validate()
4236{
4237 BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
4238
4239 FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(0);
4240
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00004241 if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeLocals)) {
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00004242 beginValidationDidFail();
4243 dataLog(" Wrong number of bits in result!\n");
4244 dataLog(" Result: ", liveAtHead, "\n");
4245 dataLog(" Bit count: ", liveAtHead.numBits(), "\n");
4246 endValidationDidFail();
4247 }
4248
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00004249 for (unsigned i = m_numCalleeLocals; i--;) {
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00004250 VirtualRegister reg = virtualRegisterForLocal(i);
4251
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004252 if (liveAtHead.get(i)) {
4253 beginValidationDidFail();
4254 dataLog(" Variable ", reg, " is expected to be dead.\n");
4255 dataLog(" Result: ", liveAtHead, "\n");
4256 endValidationDidFail();
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00004257 }
4258 }
4259}
4260
4261void CodeBlock::beginValidationDidFail()
4262{
4263 dataLog("Validation failure in ", *this, ":\n");
4264 dataLog("\n");
4265}
4266
4267void CodeBlock::endValidationDidFail()
4268{
4269 dataLog("\n");
4270 dumpBytecode();
4271 dataLog("\n");
4272 dataLog("Validation failure.\n");
4273 RELEASE_ASSERT_NOT_REACHED();
4274}
4275
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00004276void CodeBlock::addBreakpoint(unsigned numBreakpoints)
4277{
4278 m_numBreakpoints += numBreakpoints;
4279 ASSERT(m_numBreakpoints);
mark.lam@apple.com51ccaab2014-02-01 20:29:23 +00004280 if (JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00004281 jettison(Profiler::JettisonDueToDebuggerBreakpoint);
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00004282}
4283
4284void CodeBlock::setSteppingMode(CodeBlock::SteppingMode mode)
4285{
4286 m_steppingMode = mode;
mark.lam@apple.com51ccaab2014-02-01 20:29:23 +00004287 if (mode == SteppingModeEnabled && JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00004288 jettison(Profiler::JettisonDueToDebuggerStepping);
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00004289}
4290
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00004291RareCaseProfile* CodeBlock::rareCaseProfileForBytecodeOffset(int bytecodeOffset)
4292{
4293 return tryBinarySearch<RareCaseProfile, int>(
4294 m_rareCaseProfiles, m_rareCaseProfiles.size(), bytecodeOffset,
4295 getRareCaseProfileBytecodeOffset);
4296}
4297
mark.lam@apple.comff2c14a2015-09-24 18:38:35 +00004298unsigned CodeBlock::rareCaseProfileCountForBytecodeOffset(int bytecodeOffset)
4299{
4300 RareCaseProfile* profile = rareCaseProfileForBytecodeOffset(bytecodeOffset);
4301 if (profile)
4302 return profile->m_counter;
4303 return 0;
4304}
4305
mark.lam@apple.combad59ea2015-12-18 22:03:30 +00004306ResultProfile* CodeBlock::resultProfileForBytecodeOffset(int bytecodeOffset)
4307{
sbarati@apple.com900f8912016-04-12 18:38:16 +00004308 ConcurrentJITLocker locker(m_lock);
4309 return resultProfileForBytecodeOffset(locker, bytecodeOffset);
4310}
4311
4312ResultProfile* CodeBlock::resultProfileForBytecodeOffset(const ConcurrentJITLocker&, int bytecodeOffset)
4313{
akling@apple.comce2ec582016-01-29 20:37:52 +00004314 if (!m_bytecodeOffsetToResultProfileIndexMap)
4315 return nullptr;
4316 auto iterator = m_bytecodeOffsetToResultProfileIndexMap->find(bytecodeOffset);
4317 if (iterator == m_bytecodeOffsetToResultProfileIndexMap->end())
mark.lam@apple.comc1a72412016-01-05 23:08:58 +00004318 return nullptr;
4319 return &m_resultProfiles[iterator->value];
mark.lam@apple.combad59ea2015-12-18 22:03:30 +00004320}
4321
sbarati@apple.com900f8912016-04-12 18:38:16 +00004322
4323ResultProfile* CodeBlock::ensureResultProfile(int bytecodeOffset)
4324{
4325 ConcurrentJITLocker locker(m_lock);
4326 return ensureResultProfile(locker, bytecodeOffset);
4327}
4328
4329ResultProfile* CodeBlock::ensureResultProfile(const ConcurrentJITLocker& locker, int bytecodeOffset)
4330{
sbarati@apple.com900f8912016-04-12 18:38:16 +00004331 ResultProfile* profile = resultProfileForBytecodeOffset(locker, bytecodeOffset);
4332 if (!profile) {
4333 m_resultProfiles.append(ResultProfile(bytecodeOffset));
4334 profile = &m_resultProfiles.last();
4335 ASSERT(&m_resultProfiles.last() == &m_resultProfiles[m_resultProfiles.size() - 1]);
4336 if (!m_bytecodeOffsetToResultProfileIndexMap)
4337 m_bytecodeOffsetToResultProfileIndexMap = std::make_unique<BytecodeOffsetToResultProfileIndexMap>();
4338 m_bytecodeOffsetToResultProfileIndexMap->add(bytecodeOffset, m_resultProfiles.size() - 1);
4339 }
4340 return profile;
4341}
4342
mhahnenberg@apple.com0ef30c42014-05-02 21:21:04 +00004343#if ENABLE(JIT)
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00004344DFG::CapabilityLevel CodeBlock::capabilityLevel()
4345{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00004346 DFG::CapabilityLevel result = computeCapabilityLevel();
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00004347 m_capabilityLevelState = result;
4348 return result;
4349}
mhahnenberg@apple.com0ef30c42014-05-02 21:21:04 +00004350#endif
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00004351
akling@apple.comf10f7a12015-10-10 21:14:56 +00004352void CodeBlock::insertBasicBlockBoundariesForControlFlowProfiler(RefCountedArray<Instruction>& instructions)
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004353{
akling@apple.com7dc7b8b2016-03-07 18:24:26 +00004354 if (!unlinkedCodeBlock()->hasOpProfileControlFlowBytecodeOffsets())
4355 return;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004356 const Vector<size_t>& bytecodeOffsets = unlinkedCodeBlock()->opProfileControlFlowBytecodeOffsets();
4357 for (size_t i = 0, offsetsLength = bytecodeOffsets.size(); i < offsetsLength; i++) {
4358 // Because op_profile_control_flow is emitted at the beginning of every basic block, finding
4359 // the next op_profile_control_flow will give us the text range of a single basic block.
4360 size_t startIdx = bytecodeOffsets[i];
4361 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[startIdx].u.opcode) == op_profile_control_flow);
4362 int basicBlockStartOffset = instructions[startIdx + 1].u.operand;
4363 int basicBlockEndOffset;
4364 if (i + 1 < offsetsLength) {
4365 size_t endIdx = bytecodeOffsets[i + 1];
4366 RELEASE_ASSERT(vm()->interpreter->getOpcodeID(instructions[endIdx].u.opcode) == op_profile_control_flow);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00004367 basicBlockEndOffset = instructions[endIdx + 1].u.operand - 1;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004368 } else {
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00004369 basicBlockEndOffset = m_sourceOffset + ownerScriptExecutable()->source().length() - 1; // Offset before the closing brace.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004370 basicBlockStartOffset = std::min(basicBlockStartOffset, basicBlockEndOffset); // Some start offsets may be at the closing brace, ensure it is the offset before.
4371 }
4372
4373 // The following check allows for the same textual JavaScript basic block to have its bytecode emitted more
4374 // than once and still play nice with the control flow profiler. When basicBlockStartOffset is larger than
4375 // basicBlockEndOffset, it indicates that the bytecode generator has emitted code for the same AST node
4376 // more than once (for example: ForInNode, Finally blocks in TryNode, etc). Though these are different
4377 // basic blocks at the bytecode level, they are generated from the same textual basic block in the JavaScript
4378 // program. The condition:
4379 // (basicBlockEndOffset < basicBlockStartOffset)
4380 // is encountered when op_profile_control_flow lies across the boundary of these duplicated bytecode basic
4381 // blocks and the textual offset goes from the end of the duplicated block back to the beginning. These
4382 // ranges are dummy ranges and are ignored. The duplicated bytecode basic blocks point to the same
4383 // internal data structure, so if any of them execute, it will record the same textual basic block in the
4384 // JavaScript program as executing.
4385 // At the bytecode level, this situation looks like:
4386 // j: op_profile_control_flow (from j->k, we have basicBlockEndOffset < basicBlockStartOffset)
4387 // ...
4388 // 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).
4389 // ...
4390 // m: op_profile_control_flow
4391 if (basicBlockEndOffset < basicBlockStartOffset) {
4392 RELEASE_ASSERT(i + 1 < offsetsLength); // We should never encounter dummy blocks at the end of a CodeBlock.
4393 instructions[startIdx + 1].u.basicBlockLocation = vm()->controlFlowProfiler()->dummyBasicBlock();
4394 continue;
4395 }
4396
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00004397 BasicBlockLocation* basicBlockLocation = vm()->controlFlowProfiler()->getBasicBlockLocation(ownerScriptExecutable()->sourceID(), basicBlockStartOffset, basicBlockEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00004398
4399 // Find all functions that are enclosed within the range: [basicBlockStartOffset, basicBlockEndOffset]
4400 // and insert these functions' start/end offsets as gaps in the current BasicBlockLocation.
4401 // This is necessary because in the original source text of a JavaScript program,
4402 // function literals form new basic blocks boundaries, but they aren't represented
4403 // inside the CodeBlock's instruction stream.
4404 auto insertFunctionGaps = [basicBlockLocation, basicBlockStartOffset, basicBlockEndOffset] (const WriteBarrier<FunctionExecutable>& functionExecutable) {
4405 const UnlinkedFunctionExecutable* executable = functionExecutable->unlinkedExecutable();
4406 int functionStart = executable->typeProfilingStartOffset();
4407 int functionEnd = executable->typeProfilingEndOffset();
4408 if (functionStart >= basicBlockStartOffset && functionEnd <= basicBlockEndOffset)
4409 basicBlockLocation->insertGap(functionStart, functionEnd);
4410 };
4411
4412 for (const WriteBarrier<FunctionExecutable>& executable : m_functionDecls)
4413 insertFunctionGaps(executable);
4414 for (const WriteBarrier<FunctionExecutable>& executable : m_functionExprs)
4415 insertFunctionGaps(executable);
4416
4417 instructions[startIdx + 1].u.basicBlockLocation = basicBlockLocation;
4418 }
4419}
4420
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00004421#if ENABLE(JIT)
4422void CodeBlock::setPCToCodeOriginMap(std::unique_ptr<PCToCodeOriginMap>&& map)
4423{
4424 m_pcToCodeOriginMap = WTFMove(map);
4425}
4426
4427Optional<CodeOrigin> CodeBlock::findPC(void* pc)
4428{
4429 if (m_pcToCodeOriginMap) {
4430 if (Optional<CodeOrigin> codeOrigin = m_pcToCodeOriginMap->findPC(pc))
4431 return codeOrigin;
4432 }
4433
4434 for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
4435 StructureStubInfo* stub = *iter;
4436 if (stub->containsPC(pc))
4437 return Optional<CodeOrigin>(stub->codeOrigin);
4438 }
4439
4440 if (Optional<CodeOrigin> codeOrigin = m_jitCode->findPC(this, pc))
4441 return codeOrigin;
4442
4443 return Nullopt;
4444}
4445#endif // ENABLE(JIT)
4446
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00004447Optional<unsigned> CodeBlock::bytecodeOffsetFromCallSiteIndex(CallSiteIndex callSiteIndex)
4448{
4449 Optional<unsigned> bytecodeOffset;
4450 JITCode::JITType jitType = this->jitType();
4451 if (jitType == JITCode::InterpreterThunk || jitType == JITCode::BaselineJIT) {
4452#if USE(JSVALUE64)
4453 bytecodeOffset = callSiteIndex.bits();
4454#else
4455 Instruction* instruction = bitwise_cast<Instruction*>(callSiteIndex.bits());
4456 bytecodeOffset = instruction - instructions().begin();
4457#endif
4458 } else if (jitType == JITCode::DFGJIT || jitType == JITCode::FTLJIT) {
sbarati@apple.com977e0ca2016-05-17 00:29:40 +00004459#if ENABLE(DFG_JIT)
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00004460 RELEASE_ASSERT(canGetCodeOrigin(callSiteIndex));
4461 CodeOrigin origin = codeOrigin(callSiteIndex);
4462 bytecodeOffset = origin.bytecodeIndex;
sbarati@apple.com977e0ca2016-05-17 00:29:40 +00004463#else
4464 RELEASE_ASSERT_NOT_REACHED();
4465#endif
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00004466 }
4467
4468 return bytecodeOffset;
4469}
4470
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +00004471} // namespace JSC