blob: 17016e9e470438617fa60f5ccc9026ae29b554e6 [file] [log] [blame]
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001/*
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00002 * Copyright (C) 2008-2018 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
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +000033#include "ArithProfile.h"
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +000034#include "BasicBlockLocation.h"
utatane.tea@gmail.com7b6754e2017-03-01 08:15:45 +000035#include "BytecodeDumper.h"
barraclough@apple.comc2527d62010-08-11 19:52:41 +000036#include "BytecodeGenerator.h"
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +000037#include "BytecodeLivenessAnalysis.h"
keith_miller@apple.comc02f5d32018-05-22 18:04:31 +000038#include "BytecodeStructs.h"
fpizlo@apple.com0309686b2013-12-02 19:49:43 +000039#include "BytecodeUseDef.h"
fpizlo@apple.com806b5822013-01-08 01:23:38 +000040#include "CallLinkStatus.h"
fpizlo@apple.com7b231642016-10-11 23:52:02 +000041#include "CodeBlockSet.h"
fpizlo@apple.com452cb412011-09-08 21:38:04 +000042#include "DFGCapabilities.h"
fpizlo@apple.com1e89af32012-11-19 02:55:14 +000043#include "DFGCommon.h"
fpizlo@apple.com62b6af82013-08-29 18:25:36 +000044#include "DFGDriver.h"
fpizlo@apple.comb426f862014-02-10 02:51:13 +000045#include "DFGJITCode.h"
oliver@apple.com284cc3d2013-07-25 04:00:33 +000046#include "DFGWorklist.h"
barraclough@apple.comc2527d62010-08-11 19:52:41 +000047#include "Debugger.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000048#include "EvalCodeBlock.h"
jfbastien@apple.comc6594e52017-02-22 01:16:42 +000049#include "FullCodeOrigin.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000050#include "FunctionCodeBlock.h"
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +000051#include "FunctionExecutableDump.h"
saambarati1@gmail.com060e7512015-09-03 19:45:44 +000052#include "GetPutInfo.h"
ggaren@apple.com0dc469d2015-08-18 19:28:37 +000053#include "InlineCallFrame.h"
utatane.tea@gmail.com7b6754e2017-03-01 08:15:45 +000054#include "InterpreterInlines.h"
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +000055#include "IsoCellSetInlines.h"
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +000056#include "JIT.h"
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +000057#include "JITMathIC.h"
ticaiolima@gmail.comb9da09d2017-12-12 21:01:57 +000058#include "JSBigInt.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000059#include "JSCInlines.h"
oliver@apple.comd04e0a02014-02-01 01:37:59 +000060#include "JSCJSValue.h"
barraclough@apple.com3dc12332009-08-12 05:22:33 +000061#include "JSFunction.h"
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +000062#include "JSLexicalEnvironment.h"
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +000063#include "JSModuleEnvironment.h"
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +000064#include "JSSet.h"
65#include "JSString.h"
caitp@igalia.coma8b896c2018-02-13 18:10:30 +000066#include "JSTemplateObjectDescriptor.h"
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000067#include "LLIntData.h"
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +000068#include "LLIntEntrypoint.h"
commit-queue@webkit.org687ce622018-05-11 21:16:05 +000069#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h"
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000070#include "LowLevelInterpreter.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000071#include "ModuleProgramCodeBlock.h"
sbarati@apple.com3e349c82017-10-19 23:34:20 +000072#include "ObjectAllocationProfileInlines.h"
sbarati@apple.comd3d0c002016-01-30 01:11:05 +000073#include "PCToCodeOriginMap.h"
fpizlo@apple.comb26b5242015-09-10 19:49:36 +000074#include "PolymorphicAccess.h"
akling@apple.com5a0a87e2014-03-22 20:57:04 +000075#include "ProfilerDatabase.h"
ggaren@apple.coma7cd1392016-11-02 22:19:39 +000076#include "ProgramCodeBlock.h"
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +000077#include "ReduceWhitespace.h"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +000078#include "Repatch.h"
mark.lam@apple.coma4fe7ab2012-11-09 03:03:44 +000079#include "SlotVisitorInlines.h"
msaboff@apple.com4d563e42014-08-16 01:45:40 +000080#include "StackVisitor.h"
fpizlo@apple.comd5f99462016-04-11 19:31:04 +000081#include "StructureStubInfo.h"
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +000082#include "TypeLocationCache.h"
83#include "TypeProfiler.h"
akling@apple.com8427aaf2014-01-27 05:45:30 +000084#include "UnlinkedInstructionStream.h"
fpizlo@apple.com4a528d02016-05-11 00:08:50 +000085#include "VMInlines.h"
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +000086#include <wtf/BagToHashMap.h>
fpizlo@apple.com806b5822013-01-08 01:23:38 +000087#include <wtf/CommaPrinter.h>
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000088#include <wtf/SimpleStats.h>
fpizlo@apple.com9fe49132012-12-04 19:29:13 +000089#include <wtf/StringPrintStream.h>
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +000090#include <wtf/text/UniquedStringImpl.h>
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000091
msaboff@apple.com02085462015-09-10 17:47:16 +000092#if ENABLE(JIT)
93#include "RegisterAtOffsetList.h"
94#endif
95
commit-queue@webkit.org4ea48922011-07-06 00:56:49 +000096#if ENABLE(DFG_JIT)
97#include "DFGOperations.h"
98#endif
99
carlosgc@webkit.org13f6daf22013-07-30 06:42:00 +0000100#if ENABLE(FTL_JIT)
101#include "FTLJITCode.h"
102#endif
103
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000104namespace JSC {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000105
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000106const ClassInfo CodeBlock::s_info = {
utatane.tea@gmail.coma5544f12017-05-19 09:23:20 +0000107 "CodeBlock", nullptr, nullptr, nullptr,
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000108 CREATE_METHOD_TABLE(CodeBlock)
109};
110
oliver@apple.com02039462013-07-25 03:59:29 +0000111CString CodeBlock::inferredName() const
fpizlo@apple.com1a6da212012-12-10 18:38:15 +0000112{
113 switch (codeType()) {
114 case GlobalCode:
115 return "<global>";
116 case EvalCode:
117 return "<eval>";
118 case FunctionCode:
oliver@apple.com02039462013-07-25 03:59:29 +0000119 return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().utf8();
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +0000120 case ModuleCode:
121 return "<module>";
fpizlo@apple.com1a6da212012-12-10 18:38:15 +0000122 default:
123 CRASH();
oliver@apple.com02039462013-07-25 03:59:29 +0000124 return CString("", 0);
fpizlo@apple.com1a6da212012-12-10 18:38:15 +0000125 }
126}
127
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000128bool CodeBlock::hasHash() const
129{
130 return !!m_hash;
131}
132
133bool CodeBlock::isSafeToComputeHash() const
134{
135 return !isCompilationThread();
136}
137
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000138CodeBlockHash CodeBlock::hash() const
139{
oliver@apple.comacdde492013-07-25 04:02:57 +0000140 if (!m_hash) {
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000141 RELEASE_ASSERT(isSafeToComputeHash());
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000142 m_hash = CodeBlockHash(ownerScriptExecutable()->source(), specializationKind());
oliver@apple.comacdde492013-07-25 04:02:57 +0000143 }
144 return m_hash;
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000145}
146
oliver@apple.com02039462013-07-25 03:59:29 +0000147CString CodeBlock::sourceCodeForTools() const
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000148{
149 if (codeType() != FunctionCode)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000150 return ownerScriptExecutable()->source().toUTF8();
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000151
152 SourceProvider* provider = source();
153 FunctionExecutable* executable = jsCast<FunctionExecutable*>(ownerExecutable());
154 UnlinkedFunctionExecutable* unlinked = executable->unlinkedExecutable();
155 unsigned unlinkedStartOffset = unlinked->startOffset();
156 unsigned linkedStartOffset = executable->source().startOffset();
157 int delta = linkedStartOffset - unlinkedStartOffset;
mark.lam@apple.comfa35e782013-11-19 21:55:16 +0000158 unsigned rangeStart = delta + unlinked->unlinkedFunctionNameStart();
oliver@apple.com02039462013-07-25 03:59:29 +0000159 unsigned rangeEnd = delta + unlinked->startOffset() + unlinked->sourceLength();
160 return toCString(
161 "function ",
akling@apple.com73320982015-12-13 20:03:24 +0000162 provider->source().substring(rangeStart, rangeEnd - rangeStart).utf8());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000163}
164
oliver@apple.com02039462013-07-25 03:59:29 +0000165CString CodeBlock::sourceCodeOnOneLine() const
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000166{
167 return reduceWhitespace(sourceCodeForTools());
168}
169
fpizlo@apple.comf285f712014-03-13 01:50:41 +0000170CString CodeBlock::hashAsStringIfPossible() const
171{
172 if (hasHash() || isSafeToComputeHash())
173 return toCString(hash());
174 return "<no-hash>";
175}
176
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000177void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const
178{
fpizlo@apple.comf285f712014-03-13 01:50:41 +0000179 out.print(inferredName(), "#", hashAsStringIfPossible());
msaboff@apple.com95894332014-01-29 19:18:54 +0000180 out.print(":[", RawPointer(this), "->");
181 if (!!m_alternative)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000182 out.print(RawPointer(alternative()), "->");
msaboff@apple.com95894332014-01-29 19:18:54 +0000183 out.print(RawPointer(ownerExecutable()), ", ", jitType, codeType());
mhahnenberg@apple.com0c662a42013-08-02 21:50:56 +0000184
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000185 if (codeType() == FunctionCode)
186 out.print(specializationKind());
fpizlo@apple.com9df7fef2013-12-29 21:50:55 +0000187 out.print(", ", instructionCount());
oliver@apple.comb3e5acb2013-07-25 04:02:53 +0000188 if (this->jitType() == JITCode::BaselineJIT && m_shouldAlwaysBeInlined)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000189 out.print(" (ShouldAlwaysBeInlined)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000190 if (ownerScriptExecutable()->neverInline())
oliver@apple.com4e67ae52013-07-25 04:01:24 +0000191 out.print(" (NeverInline)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000192 if (ownerScriptExecutable()->neverOptimize())
mark.lam@apple.com49e71b92015-08-28 05:59:44 +0000193 out.print(" (NeverOptimize)");
keith_miller@apple.coma64964a2016-04-22 02:28:00 +0000194 else if (ownerScriptExecutable()->neverFTLOptimize())
195 out.print(" (NeverFTLOptimize)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000196 if (ownerScriptExecutable()->didTryToEnterInLoop())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000197 out.print(" (DidTryToEnterInLoop)");
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000198 if (ownerScriptExecutable()->isStrictMode())
fpizlo@apple.com018818d2013-09-13 23:18:19 +0000199 out.print(" (StrictMode)");
fpizlo@apple.com46050f72016-06-17 04:48:47 +0000200 if (m_didFailJITCompilation)
201 out.print(" (JITFail)");
msaboff@apple.com95894332014-01-29 19:18:54 +0000202 if (this->jitType() == JITCode::BaselineJIT && m_didFailFTLCompilation)
203 out.print(" (FTLFail)");
204 if (this->jitType() == JITCode::BaselineJIT && m_hasBeenCompiledWithFTL)
205 out.print(" (HadFTLReplacement)");
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000206 out.print("]");
207}
208
209void CodeBlock::dump(PrintStream& out) const
210{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +0000211 dumpAssumingJITType(out, jitType());
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000212}
213
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000214void CodeBlock::dumpSource()
215{
216 dumpSource(WTF::dataFile());
217}
218
219void CodeBlock::dumpSource(PrintStream& out)
220{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000221 ScriptExecutable* executable = ownerScriptExecutable();
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000222 if (executable->isFunctionExecutable()) {
223 FunctionExecutable* functionExecutable = reinterpret_cast<FunctionExecutable*>(executable);
akling@apple.com73320982015-12-13 20:03:24 +0000224 StringView source = functionExecutable->source().provider()->getRange(
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000225 functionExecutable->parametersStartOffset(),
226 functionExecutable->typeProfilingEndOffset() + 1); // Type profiling end offset is the character before the '}'.
227
228 out.print("function ", inferredName(), source);
229 return;
230 }
akling@apple.com73320982015-12-13 20:03:24 +0000231 out.print(executable->source().view());
mark.lam@apple.come7f88842015-04-02 22:46:52 +0000232}
233
234void CodeBlock::dumpBytecode()
235{
236 dumpBytecode(WTF::dataFile());
237}
238
fpizlo@apple.com1afcdf02012-12-02 08:00:14 +0000239void CodeBlock::dumpBytecode(PrintStream& out)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000240{
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000241 StubInfoMap stubInfos;
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000242 CallLinkInfoMap callLinkInfos;
msaboff@apple.com95894332014-01-29 19:18:54 +0000243 getStubInfoMap(stubInfos);
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000244 getCallLinkInfoMap(callLinkInfos);
utatane.tea@gmail.com7b6754e2017-03-01 08:15:45 +0000245 BytecodeDumper<CodeBlock>::dumpBlock(this, instructions(), out, stubInfos, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000246}
247
utatane.tea@gmail.com7b6754e2017-03-01 08:15:45 +0000248void CodeBlock::dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
fpizlo@apple.com21014282016-01-08 21:42:23 +0000249{
utatane.tea@gmail.com7b6754e2017-03-01 08:15:45 +0000250 BytecodeDumper<CodeBlock>::dumpBytecode(this, out, begin, it, stubInfos, callLinkInfos);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000251}
252
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000253void CodeBlock::dumpBytecode(
254 PrintStream& out, unsigned bytecodeOffset,
255 const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos)
fpizlo@apple.com1949f322012-11-22 00:46:57 +0000256{
mark.lam@apple.comd5b8e182018-03-21 18:23:30 +0000257 const Instruction* it = &instructions()[bytecodeOffset];
utatane.tea@gmail.com7b6754e2017-03-01 08:15:45 +0000258 dumpBytecode(out, instructions().begin(), it, stubInfos, callLinkInfos);
fpizlo@apple.com1949f322012-11-22 00:46:57 +0000259}
260
weinig@apple.com67940d52008-12-09 00:14:58 +0000261#define FOR_EACH_MEMBER_VECTOR(macro) \
262 macro(instructions) \
weinig@apple.com67940d52008-12-09 00:14:58 +0000263 macro(callLinkInfos) \
264 macro(linkedCallerList) \
265 macro(identifiers) \
266 macro(functionExpressions) \
weinig@apple.com93675542009-01-09 18:47:37 +0000267 macro(constantRegisters)
weinig@apple.com4557e842008-12-09 01:06:14 +0000268
weinig@apple.comff037a02008-12-10 20:05:53 +0000269template<typename T>
270static size_t sizeInBytes(const Vector<T>& vector)
271{
272 return vector.capacity() * sizeof(T);
273}
274
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000275namespace {
276
277class PutToScopeFireDetail : public FireDetail {
278public:
279 PutToScopeFireDetail(CodeBlock* codeBlock, const Identifier& ident)
280 : m_codeBlock(codeBlock)
281 , m_ident(ident)
282 {
283 }
284
darin@apple.com11ff47c2016-03-04 16:47:55 +0000285 void dump(PrintStream& out) const override
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000286 {
287 out.print("Linking put_to_scope in ", FunctionExecutableDump(jsCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())), " for ", m_ident);
288 }
289
290private:
291 CodeBlock* m_codeBlock;
292 const Identifier& m_ident;
293};
294
295} // anonymous namespace
296
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000297CodeBlock::CodeBlock(VM* vm, Structure* structure, CopyParsedBlockTag, CodeBlock& other)
298 : JSCell(*vm, structure)
299 , m_globalObject(other.m_globalObject)
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000300 , m_numCalleeLocals(other.m_numCalleeLocals)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000301 , m_numVars(other.m_numVars)
oliver@apple.comd2cdd312013-07-25 04:01:00 +0000302 , m_shouldAlwaysBeInlined(true)
akling@apple.comce2ec582016-01-29 20:37:52 +0000303#if ENABLE(JIT)
304 , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
305#endif
fpizlo@apple.com46050f72016-06-17 04:48:47 +0000306 , m_didFailJITCompilation(false)
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000307 , m_didFailFTLCompilation(false)
msaboff@apple.com95894332014-01-29 19:18:54 +0000308 , m_hasBeenCompiledWithFTL(false)
akling@apple.comce2ec582016-01-29 20:37:52 +0000309 , m_isConstructor(other.m_isConstructor)
310 , m_isStrictMode(other.m_isStrictMode)
akling@apple.comce2ec582016-01-29 20:37:52 +0000311 , m_codeType(other.m_codeType)
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000312 , m_unlinkedCode(*other.vm(), this, other.m_unlinkedCode.get())
utatane.tea@gmail.com37a7be32017-03-16 13:52:46 +0000313 , m_numberOfArgumentsToSkip(other.m_numberOfArgumentsToSkip)
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +0000314 , m_hasDebuggerStatement(false)
mark.lam@apple.com9c304882014-01-24 19:07:31 +0000315 , m_steppingMode(SteppingModeDisabled)
mark.lam@apple.com945b1392014-01-23 07:39:58 +0000316 , m_numBreakpoints(0)
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000317 , m_ownerExecutable(*other.vm(), this, other.m_ownerExecutable.get())
mark.lam@apple.come875b7e2018-01-08 22:59:10 +0000318 , m_poisonedVM(other.m_poisonedVM)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000319 , m_instructions(other.m_instructions)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000320 , m_thisRegister(other.m_thisRegister)
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +0000321 , m_scopeRegister(other.m_scopeRegister)
akling@apple.comce2ec582016-01-29 20:37:52 +0000322 , m_hash(other.m_hash)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000323 , m_source(other.m_source)
324 , m_sourceOffset(other.m_sourceOffset)
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000325 , m_firstLineColumnOffset(other.m_firstLineColumnOffset)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000326 , m_constantRegisters(other.m_constantRegisters)
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000327 , m_constantsSourceCodeRepresentation(other.m_constantsSourceCodeRepresentation)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000328 , m_functionDecls(other.m_functionDecls)
329 , m_functionExprs(other.m_functionExprs)
fpizlo@apple.com39c94a42012-07-10 09:18:47 +0000330 , m_osrExitCounter(0)
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000331 , m_optimizationDelayCounter(0)
332 , m_reoptimizationRetryCounter(0)
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +0000333 , m_creationTime(MonotonicTime::now())
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000334{
akling@apple.comce2ec582016-01-29 20:37:52 +0000335 ASSERT(heap()->isDeferred());
msaboff@apple.com2f145bc2015-01-23 19:52:25 +0000336 ASSERT(m_scopeRegister.isLocal());
337
fpizlo@apple.comc4d54962012-01-10 22:08:47 +0000338 setNumParameters(other.numParameters());
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000339
340 vm->heap.codeBlockSet().add(this);
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000341}
342
343void CodeBlock::finishCreation(VM& vm, CopyParsedBlockTag, CodeBlock& other)
344{
345 Base::finishCreation(vm);
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000346 finishCreationCommon(vm);
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000347
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000348 optimizeAfterWarmUp();
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000349 jitAfterWarmUp();
commit-queue@webkit.org3e0a1a02012-06-19 06:07:28 +0000350
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000351 if (other.m_rareData) {
352 createRareDataIfNecessary();
353
354 m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers;
oliver@apple.coma14cea52013-07-25 04:03:23 +0000355 m_rareData->m_switchJumpTables = other.m_rareData->m_switchJumpTables;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000356 m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables;
fpizlo@apple.comf5e1fe12011-11-10 21:59:39 +0000357 }
358}
359
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000360CodeBlock::CodeBlock(VM* vm, Structure* structure, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
utatane.tea@gmail.com2551c4b2017-02-15 17:09:22 +0000361 JSScope* scope, RefPtr<SourceProvider>&& sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000362 : JSCell(*vm, structure)
utatane.tea@gmail.comb860d692018-05-31 06:19:33 +0000363 , m_globalObject(*vm, this, scope->globalObject(*vm))
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000364 , m_numCalleeLocals(unlinkedCodeBlock->m_numCalleeLocals)
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000365 , m_numVars(unlinkedCodeBlock->m_numVars)
oliver@apple.comd2cdd312013-07-25 04:01:00 +0000366 , m_shouldAlwaysBeInlined(true)
akling@apple.comce2ec582016-01-29 20:37:52 +0000367#if ENABLE(JIT)
368 , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
369#endif
fpizlo@apple.com46050f72016-06-17 04:48:47 +0000370 , m_didFailJITCompilation(false)
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000371 , m_didFailFTLCompilation(false)
msaboff@apple.com95894332014-01-29 19:18:54 +0000372 , m_hasBeenCompiledWithFTL(false)
akling@apple.comce2ec582016-01-29 20:37:52 +0000373 , m_isConstructor(unlinkedCodeBlock->isConstructor())
374 , m_isStrictMode(unlinkedCodeBlock->isStrictMode())
akling@apple.comce2ec582016-01-29 20:37:52 +0000375 , m_codeType(unlinkedCodeBlock->codeType())
mark.lam@apple.com23e96242017-09-09 16:21:45 +0000376 , m_unlinkedCode(*vm, this, unlinkedCodeBlock)
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +0000377 , m_hasDebuggerStatement(false)
mark.lam@apple.com9c304882014-01-24 19:07:31 +0000378 , m_steppingMode(SteppingModeDisabled)
mark.lam@apple.com945b1392014-01-23 07:39:58 +0000379 , m_numBreakpoints(0)
mark.lam@apple.com23e96242017-09-09 16:21:45 +0000380 , m_ownerExecutable(*vm, this, ownerExecutable)
mark.lam@apple.come875b7e2018-01-08 22:59:10 +0000381 , m_poisonedVM(vm)
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000382 , m_thisRegister(unlinkedCodeBlock->thisRegister())
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +0000383 , m_scopeRegister(unlinkedCodeBlock->scopeRegister())
utatane.tea@gmail.com2551c4b2017-02-15 17:09:22 +0000384 , m_source(WTFMove(sourceProvider))
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +0000385 , m_sourceOffset(sourceOffset)
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000386 , m_firstLineColumnOffset(firstLineColumnOffset)
fpizlo@apple.com39c94a42012-07-10 09:18:47 +0000387 , m_osrExitCounter(0)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +0000388 , m_optimizationDelayCounter(0)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +0000389 , m_reoptimizationRetryCounter(0)
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +0000390 , m_creationTime(MonotonicTime::now())
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +0000391{
akling@apple.comce2ec582016-01-29 20:37:52 +0000392 ASSERT(heap()->isDeferred());
msaboff@apple.com2f145bc2015-01-23 19:52:25 +0000393 ASSERT(m_scopeRegister.isLocal());
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000394
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +0000395 ASSERT(m_source);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000396 setNumParameters(unlinkedCodeBlock->numParameters());
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000397
398 vm->heap.codeBlockSet().add(this);
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000399}
oliver@apple.comc909f5f2012-10-18 23:37:40 +0000400
sbarati@apple.com34906fa2017-10-28 01:03:22 +0000401// The main purpose of this function is to generate linked bytecode from unlinked bytecode. The process
402// of linking is taking an abstract representation of bytecode and tying it to a GlobalObject and scope
403// chain. For example, this process allows us to cache the depth of lexical environment reads that reach
404// outside of this CodeBlock's compilation unit. It also allows us to generate particular constants that
405// we can't generate during unlinked bytecode generation. This process is not allowed to generate control
406// flow or introduce new locals. The reason for this is we rely on liveness analysis to be the same for
407// all the CodeBlocks of an UnlinkedCodeBlock. We rely on this fact by caching the liveness analysis
408// inside UnlinkedCodeBlock.
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000409bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000410 JSScope* scope)
411{
412 Base::finishCreation(vm);
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000413 finishCreationCommon(vm);
sbarati@apple.com34906fa2017-10-28 01:03:22 +0000414
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000415 auto throwScope = DECLARE_THROW_SCOPE(vm);
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000416
417 if (vm.typeProfiler() || vm.controlFlowProfiler())
418 vm.functionHasExecutedCache()->removeUnexecutedRange(ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(), ownerExecutable->typeProfilingEndOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000419
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000420 setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation());
421 RETURN_IF_EXCEPTION(throwScope, false);
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000422
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000423 setConstantIdentifierSetRegisters(vm, unlinkedCodeBlock->constantIdentifierSets());
424 RETURN_IF_EXCEPTION(throwScope, false);
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000425
oliver@apple.com75f804e2013-03-07 00:25:20 +0000426 if (unlinkedCodeBlock->usesGlobalObject())
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000427 m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(vm, this, m_globalObject.get());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000428
429 for (unsigned i = 0; i < LinkTimeConstantCount; i++) {
430 LinkTimeConstant type = static_cast<LinkTimeConstant>(i);
431 if (unsigned registerIndex = unlinkedCodeBlock->registerIndexForLinkTimeConstant(type))
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000432 m_constantRegisters[registerIndex].set(vm, this, m_globalObject->jsCellForLinkTimeConstant(type));
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000433 }
saambarati1@gmail.com3321f092015-07-20 21:16:41 +0000434
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000435 // We already have the cloned symbol table for the module environment since we need to instantiate
436 // the module environments before linking the code block. We replace the stored symbol table with the already cloned one.
keith_miller@apple.com45da7602017-01-27 01:47:52 +0000437 if (UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock = jsDynamicCast<UnlinkedModuleProgramCodeBlock*>(vm, unlinkedCodeBlock)) {
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000438 SymbolTable* clonedSymbolTable = jsCast<ModuleProgramExecutable*>(ownerExecutable)->moduleEnvironmentSymbolTable();
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000439 if (vm.typeProfiler()) {
fpizlo@apple.com171d06f2016-11-15 23:21:50 +0000440 ConcurrentJSLocker locker(clonedSymbolTable->m_lock);
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000441 clonedSymbolTable->prepareForTypeProfiling(locker);
442 }
443 replaceConstant(unlinkedModuleProgramCodeBlock->moduleEnvironmentSymbolTableConstantRegisterOffset(), clonedSymbolTable);
444 }
445
sbarati@apple.com2877c4a2016-03-31 00:47:15 +0000446 bool shouldUpdateFunctionHasExecutedCache = vm.typeProfiler() || vm.controlFlowProfiler();
akling@apple.comce2ec582016-01-29 20:37:52 +0000447 m_functionDecls = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionDecls());
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000448 for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
449 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
sbarati@apple.com2877c4a2016-03-31 00:47:15 +0000450 if (shouldUpdateFunctionHasExecutedCache)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000451 vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000452 m_functionDecls[i].set(vm, this, unlinkedExecutable->link(vm, ownerExecutable->source()));
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000453 }
454
akling@apple.comce2ec582016-01-29 20:37:52 +0000455 m_functionExprs = RefCountedArray<WriteBarrier<FunctionExecutable>>(unlinkedCodeBlock->numberOfFunctionExprs());
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000456 for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
457 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
sbarati@apple.com2877c4a2016-03-31 00:47:15 +0000458 if (shouldUpdateFunctionHasExecutedCache)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000459 vm.functionHasExecutedCache()->insertUnexecutedRange(ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000460 m_functionExprs[i].set(vm, this, unlinkedExecutable->link(vm, ownerExecutable->source()));
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000461 }
462
463 if (unlinkedCodeBlock->hasRareData()) {
464 createRareDataIfNecessary();
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000465 if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) {
akling@apple.comb2ad1692014-01-18 23:09:48 +0000466 m_rareData->m_exceptionHandlers.resizeToFit(count);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000467 for (size_t i = 0; i < count; i++) {
mark.lam@apple.com4585ce92015-05-30 00:19:01 +0000468 const UnlinkedHandlerInfo& unlinkedHandler = unlinkedCodeBlock->exceptionHandler(i);
469 HandlerInfo& handler = m_rareData->m_exceptionHandlers[i];
mark.lam@apple.com3280e072015-06-01 17:57:18 +0000470#if ENABLE(JIT)
mark.lam@apple.comde0dba72018-04-18 03:31:09 +0000471 handler.initialize(unlinkedHandler, CodeLocationLabel<ExceptionHandlerPtrTag>(LLInt::getCodePtr<BytecodePtrTag>(op_catch).retagged<ExceptionHandlerPtrTag>()));
mark.lam@apple.com3280e072015-06-01 17:57:18 +0000472#else
saambarati1@gmail.come85426c2015-08-07 17:41:22 +0000473 handler.initialize(unlinkedHandler);
mark.lam@apple.com3280e072015-06-01 17:57:18 +0000474#endif
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000475 }
476 }
477
478 if (size_t count = unlinkedCodeBlock->numberOfStringSwitchJumpTables()) {
479 m_rareData->m_stringSwitchJumpTables.grow(count);
480 for (size_t i = 0; i < count; i++) {
481 UnlinkedStringJumpTable::StringOffsetTable::iterator ptr = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.begin();
482 UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end();
483 for (; ptr != end; ++ptr) {
484 OffsetLocation offset;
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +0000485 offset.branchOffset = ptr->value.branchOffset;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000486 m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset);
487 }
488 }
489 }
490
oliver@apple.coma14cea52013-07-25 04:03:23 +0000491 if (size_t count = unlinkedCodeBlock->numberOfSwitchJumpTables()) {
492 m_rareData->m_switchJumpTables.grow(count);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000493 for (size_t i = 0; i < count; i++) {
oliver@apple.coma14cea52013-07-25 04:03:23 +0000494 UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->switchJumpTable(i);
495 SimpleJumpTable& destTable = m_rareData->m_switchJumpTables[i];
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000496 destTable.branchOffsets = sourceTable.branchOffsets;
497 destTable.min = sourceTable.min;
498 }
499 }
500 }
501
502 // Allocate metadata buffers for the bytecode
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000503 if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos())
akling@apple.comce2ec582016-01-29 20:37:52 +0000504 m_llintCallLinkInfos = RefCountedArray<LLIntCallLinkInfo>(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000505 if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
506 m_arrayProfiles.grow(size);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000507 if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles())
akling@apple.comce2ec582016-01-29 20:37:52 +0000508 m_arrayAllocationProfiles = RefCountedArray<ArrayAllocationProfile>(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000509 if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
akling@apple.comce2ec582016-01-29 20:37:52 +0000510 m_valueProfiles = RefCountedArray<ValueProfile>(size);
sbarati@apple.comcc032872018-05-11 07:57:21 +0000511 if (!vm.canUseJIT())
512 RELEASE_ASSERT(!m_valueProfiles.size());
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000513 if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
akling@apple.comce2ec582016-01-29 20:37:52 +0000514 m_objectAllocationProfiles = RefCountedArray<ObjectAllocationProfile>(size);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000515
msaboff@apple.com02085462015-09-10 17:47:16 +0000516#if ENABLE(JIT)
517 setCalleeSaveRegisters(RegisterSet::llintBaselineCalleeSaveRegisters());
518#endif
519
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000520 // Copy and translate the UnlinkedInstructions
akling@apple.com8427aaf2014-01-27 05:45:30 +0000521 unsigned instructionCount = unlinkedCodeBlock->instructions().count();
522 UnlinkedInstructionStream::Reader instructionReader(unlinkedCodeBlock->instructions());
523
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000524 // Bookkeep the strongly referenced module environments.
525 HashSet<JSModuleEnvironment*> stronglyReferencedModuleEnvironments;
526
akling@apple.comf10f7a12015-10-10 21:14:56 +0000527 RefCountedArray<Instruction> instructions(instructionCount);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000528
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +0000529 unsigned valueProfileCount = 0;
530 auto linkValueProfile = [&](unsigned bytecodeOffset, unsigned opLength) {
sbarati@apple.comcc032872018-05-11 07:57:21 +0000531 if (!vm.canUseJIT()) {
532 ASSERT(vm.noJITValueProfileSingleton);
533 instructions[bytecodeOffset + opLength - 1] = vm.noJITValueProfileSingleton.get();
534 return;
535 }
536
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +0000537 unsigned valueProfileIndex = valueProfileCount++;
538 ValueProfile* profile = &m_valueProfiles[valueProfileIndex];
539 ASSERT(profile->m_bytecodeOffset == -1);
540 profile->m_bytecodeOffset = bytecodeOffset;
541 instructions[bytecodeOffset + opLength - 1] = profile;
542 };
543
akling@apple.com8427aaf2014-01-27 05:45:30 +0000544 for (unsigned i = 0; !instructionReader.atEnd(); ) {
545 const UnlinkedInstruction* pc = instructionReader.next();
546
547 unsigned opLength = opcodeLength(pc[0].u.opcode);
548
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +0000549 instructions[i] = Interpreter::getOpcode(pc[0].u.opcode);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000550 for (size_t j = 1; j < opLength; ++j) {
551 if (sizeof(int32_t) != sizeof(intptr_t))
552 instructions[i + j].u.pointer = 0;
akling@apple.com8427aaf2014-01-27 05:45:30 +0000553 instructions[i + j].u.operand = pc[j].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000554 }
akling@apple.com8427aaf2014-01-27 05:45:30 +0000555 switch (pc[0].u.opcode) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000556 case op_has_indexed_property: {
557 int arrayProfileIndex = pc[opLength - 1].u.operand;
558 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
559
560 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
561 break;
562 }
msaboff@apple.com74aef1f2014-02-01 15:30:41 +0000563 case op_call_varargs:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000564 case op_tail_call_varargs:
keith_miller@apple.come497e202016-06-13 21:05:36 +0000565 case op_tail_call_forward_arguments:
oliver@apple.com177c2b92014-03-28 01:10:25 +0000566 case op_construct_varargs:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000567 case op_get_by_val: {
akling@apple.com8427aaf2014-01-27 05:45:30 +0000568 int arrayProfileIndex = pc[opLength - 2].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000569 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
570
571 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
joepeck@webkit.org899544a2014-01-28 04:04:45 +0000572 FALLTHROUGH;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000573 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000574 case op_get_direct_pname:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000575 case op_get_by_id:
commit-queue@webkit.org076eda02016-09-01 22:08:22 +0000576 case op_get_by_id_with_this:
commit-queue@webkit.org0f030de2016-08-25 22:11:59 +0000577 case op_try_get_by_id:
utatane.tea@gmail.com0e0c28a2018-04-08 16:21:38 +0000578 case op_get_by_id_direct:
commit-queue@webkit.org076eda02016-09-01 22:08:22 +0000579 case op_get_by_val_with_this:
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +0000580 case op_get_from_arguments:
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +0000581 case op_to_number:
utatane.tea@gmail.com076aa232017-11-01 17:32:08 +0000582 case op_to_object:
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +0000583 case op_get_argument: {
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +0000584 linkValueProfile(i, opLength);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000585 break;
586 }
keith_miller@apple.com6fc2fb72017-02-09 00:02:20 +0000587
sbarati@apple.com7ccca612018-01-05 05:12:51 +0000588 case op_to_this: {
589 linkValueProfile(i, opLength);
590 break;
591 }
592
utatane.tea@gmail.com235f2b92018-05-22 04:54:31 +0000593 case op_in_by_val:
keith_miller@apple.com6fc2fb72017-02-09 00:02:20 +0000594 case op_put_by_val:
oliver@apple.come050d642013-10-19 00:09:28 +0000595 case op_put_by_val_direct: {
akling@apple.com8427aaf2014-01-27 05:45:30 +0000596 int arrayProfileIndex = pc[opLength - 1].u.operand;
oliver@apple.come050d642013-10-19 00:09:28 +0000597 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
598 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
599 break;
600 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000601
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000602 case op_new_array:
keith_miller@apple.comc02f5d32018-05-22 18:04:31 +0000603 case op_new_array_with_size:
604 case op_new_array_buffer: {
605 unsigned arrayAllocationProfileIndex;
606 IndexingType recommendedIndexingType;
607 std::tie(arrayAllocationProfileIndex, recommendedIndexingType) = UnlinkedCodeBlock::decompressArrayAllocationProfile(pc[opLength - 1].u.operand);
608
609 ArrayAllocationProfile* profile = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
610 if (pc[0].u.opcode == op_new_array_buffer)
611 profile->initializeIndexingMode(recommendedIndexingType);
612 instructions[i + opLength - 1] = profile;
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000613 break;
614 }
keith_miller@apple.comc02f5d32018-05-22 18:04:31 +0000615
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000616 case op_new_object: {
akling@apple.com8427aaf2014-01-27 05:45:30 +0000617 int objectAllocationProfileIndex = pc[opLength - 1].u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000618 ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex];
akling@apple.com8427aaf2014-01-27 05:45:30 +0000619 int inferredInlineCapacity = pc[opLength - 2].u.operand;
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000620
621 instructions[i + opLength - 1] = objectAllocationProfile;
sbarati@apple.com8ebc61d2017-10-04 01:53:18 +0000622 objectAllocationProfile->initializeProfile(vm,
bfulgham@apple.comb876c6d2017-02-10 01:39:13 +0000623 m_globalObject.get(), this, m_globalObject->objectPrototype(), inferredInlineCapacity);
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000624 break;
625 }
626
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000627 case op_call:
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000628 case op_tail_call:
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000629 case op_call_eval: {
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +0000630 linkValueProfile(i, opLength);
akling@apple.com8427aaf2014-01-27 05:45:30 +0000631 int arrayProfileIndex = pc[opLength - 2].u.operand;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000632 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000633 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
akling@apple.com8427aaf2014-01-27 05:45:30 +0000634 instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
fpizlo@apple.com0ed51fc2012-11-09 01:27:25 +0000635 break;
636 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000637 case op_construct: {
akling@apple.com8427aaf2014-01-27 05:45:30 +0000638 instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +0000639 linkValueProfile(i, opLength);
fpizlo@apple.com0ed51fc2012-11-09 01:27:25 +0000640 break;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000641 }
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000642 case op_get_array_length:
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000643 CRASH();
644
oliver@apple.com58c86752013-07-25 04:02:40 +0000645 case op_resolve_scope: {
msaboff@apple.com44641f02014-11-03 17:56:29 +0000646 const Identifier& ident = identifier(pc[3].u.operand);
647 ResolveType type = static_cast<ResolveType>(pc[4].u.operand);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000648 RELEASE_ASSERT(type != LocalClosureVar);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000649 int localScopeDepth = pc[5].u.operand;
oliver@apple.com58c86752013-07-25 04:02:40 +0000650
commit-queue@webkit.orgde7a90b2016-05-31 22:10:10 +0000651 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization);
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000652 RETURN_IF_EXCEPTION(throwScope, false);
653
msaboff@apple.com44641f02014-11-03 17:56:29 +0000654 instructions[i + 4].u.operand = op.type;
655 instructions[i + 5].u.operand = op.depth;
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000656 if (op.lexicalEnvironment) {
657 if (op.type == ModuleVar) {
658 // Keep the linked module environment strongly referenced.
659 if (stronglyReferencedModuleEnvironments.add(jsCast<JSModuleEnvironment*>(op.lexicalEnvironment)).isNewEntry)
660 addConstant(op.lexicalEnvironment);
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000661 instructions[i + 6].u.jsCell.set(vm, this, op.lexicalEnvironment);
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000662 } else
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000663 instructions[i + 6].u.symbolTable.set(vm, this, op.lexicalEnvironment->symbolTable());
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000664 } else if (JSScope* constantScope = JSScope::constantScopeForCodeBlock(op.type, this))
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000665 instructions[i + 6].u.jsCell.set(vm, this, constantScope);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000666 else
667 instructions[i + 6].u.pointer = nullptr;
oliver@apple.com58c86752013-07-25 04:02:40 +0000668 break;
669 }
670
671 case op_get_from_scope: {
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +0000672 linkValueProfile(i, opLength);
oliver@apple.com58c86752013-07-25 04:02:40 +0000673
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000674 // get_from_scope dst, scope, id, GetPutInfo, Structure, Operand
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000675
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000676 int localScopeDepth = pc[5].u.operand;
677 instructions[i + 5].u.pointer = nullptr;
678
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000679 GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand);
sbarati@apple.come67fd782016-04-19 01:38:30 +0000680 ASSERT(!isInitialization(getPutInfo.initializationMode()));
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000681 if (getPutInfo.resolveType() == LocalClosureVar) {
682 instructions[i + 4] = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand();
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000683 break;
684 }
685
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000686 const Identifier& ident = identifier(pc[3].u.operand);
commit-queue@webkit.orgde7a90b2016-05-31 22:10:10 +0000687 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, getPutInfo.resolveType(), InitializationMode::NotInitialization);
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000688 RETURN_IF_EXCEPTION(throwScope, false);
oliver@apple.com58c86752013-07-25 04:02:40 +0000689
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000690 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000691 if (op.type == ModuleVar)
692 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), ClosureVar, getPutInfo.initializationMode()).operand();
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000693 if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
fpizlo@apple.com1a724092013-11-28 07:10:10 +0000694 instructions[i + 5].u.watchpointSet = op.watchpointSet;
695 else if (op.structure)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000696 instructions[i + 5].u.structure.set(vm, this, op.structure);
mcatanzaro@igalia.com9e1bc292018-06-15 18:31:54 +0000697 instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
oliver@apple.com58c86752013-07-25 04:02:40 +0000698 break;
699 }
700
701 case op_put_to_scope: {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000702 // put_to_scope scope, id, value, GetPutInfo, Structure, Operand
703 GetPutInfo getPutInfo = GetPutInfo(pc[4].u.operand);
704 if (getPutInfo.resolveType() == LocalClosureVar) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000705 // Only do watching if the property we're putting to is not anonymous.
706 if (static_cast<unsigned>(pc[2].u.operand) != UINT_MAX) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000707 int symbolTableIndex = pc[5].u.operand;
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000708 SymbolTable* symbolTable = jsCast<SymbolTable*>(getConstant(symbolTableIndex));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000709 const Identifier& ident = identifier(pc[2].u.operand);
fpizlo@apple.com171d06f2016-11-15 23:21:50 +0000710 ConcurrentJSLocker locker(symbolTable->m_lock);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000711 auto iter = symbolTable->find(locker, ident.impl());
sbarati@apple.com2877c4a2016-03-31 00:47:15 +0000712 ASSERT(iter != symbolTable->end(locker));
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +0000713 iter->value.prepareToWatch();
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000714 instructions[i + 5].u.watchpointSet = iter->value.watchpointSet();
715 } else
716 instructions[i + 5].u.watchpointSet = nullptr;
717 break;
718 }
719
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000720 const Identifier& ident = identifier(pc[2].u.operand);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000721 int localScopeDepth = pc[5].u.operand;
722 instructions[i + 5].u.pointer = nullptr;
commit-queue@webkit.orgde7a90b2016-05-31 22:10:10 +0000723 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Put, getPutInfo.resolveType(), getPutInfo.initializationMode());
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000724 RETURN_IF_EXCEPTION(throwScope, false);
oliver@apple.com58c86752013-07-25 04:02:40 +0000725
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000726 instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
727 if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
fpizlo@apple.com40f7cbf2013-11-18 23:19:53 +0000728 instructions[i + 5].u.watchpointSet = op.watchpointSet;
fpizlo@apple.com88fedde2013-12-04 19:29:19 +0000729 else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) {
730 if (op.watchpointSet)
sbarati@apple.com0c3609d2016-06-28 21:30:20 +0000731 op.watchpointSet->invalidate(vm, PutToScopeFireDetail(this, ident));
fpizlo@apple.com88fedde2013-12-04 19:29:19 +0000732 } else if (op.structure)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000733 instructions[i + 5].u.structure.set(vm, this, op.structure);
mcatanzaro@igalia.com9e1bc292018-06-15 18:31:54 +0000734 instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000735
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000736 break;
737 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000738
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000739 case op_profile_type: {
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000740 RELEASE_ASSERT(vm.typeProfiler());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000741 // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000742 size_t instructionOffset = i + opLength - 1;
743 unsigned divotStart, divotEnd;
mark.lam@apple.comca860af2014-10-06 22:17:09 +0000744 GlobalVariableID globalVariableID = 0;
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000745 RefPtr<TypeSet> globalTypeSet;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000746 bool shouldAnalyze = m_unlinkedCode->typeProfilerExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000747 VirtualRegister profileRegister(pc[1].u.operand);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000748 ProfileTypeBytecodeFlag flag = static_cast<ProfileTypeBytecodeFlag>(pc[3].u.operand);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000749 SymbolTable* symbolTable = nullptr;
750
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000751 switch (flag) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000752 case ProfileTypeBytecodeClosureVar: {
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000753 const Identifier& ident = identifier(pc[4].u.operand);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000754 int localScopeDepth = pc[2].u.operand;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000755 ResolveType type = static_cast<ResolveType>(pc[5].u.operand);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000756 // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
757 // we're abstractly "read"ing from a JSScope.
commit-queue@webkit.orgde7a90b2016-05-31 22:10:10 +0000758 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization);
mark.lam@apple.com135cad52017-09-11 06:23:39 +0000759 RETURN_IF_EXCEPTION(throwScope, false);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000760
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000761 if (op.type == ClosureVar || op.type == ModuleVar)
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +0000762 symbolTable = op.lexicalEnvironment->symbolTable();
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000763 else if (op.type == GlobalVar)
764 symbolTable = m_globalObject.get()->symbolTable();
utatane.tea@gmail.com6c389582015-09-04 04:29:04 +0000765
766 UniquedStringImpl* impl = (op.type == ModuleVar) ? op.importedName.get() : ident.impl();
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000767 if (symbolTable) {
fpizlo@apple.com171d06f2016-11-15 23:21:50 +0000768 ConcurrentJSLocker locker(symbolTable->m_lock);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000769 // 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 +0000770 symbolTable->prepareForTypeProfiling(locker);
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000771 globalVariableID = symbolTable->uniqueIDForVariable(locker, impl, vm);
772 globalTypeSet = symbolTable->globalTypeSetForVariable(locker, impl, vm);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000773 } else
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000774 globalVariableID = TypeProfilerNoGlobalIDExists;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000775
776 break;
777 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000778 case ProfileTypeBytecodeLocallyResolved: {
779 int symbolTableIndex = pc[2].u.operand;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000780 SymbolTable* symbolTable = jsCast<SymbolTable*>(getConstant(symbolTableIndex));
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000781 const Identifier& ident = identifier(pc[4].u.operand);
fpizlo@apple.com171d06f2016-11-15 23:21:50 +0000782 ConcurrentJSLocker locker(symbolTable->m_lock);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000783 // 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 +0000784 globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), vm);
785 globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), vm);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000786
787 break;
788 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000789 case ProfileTypeBytecodeDoesNotHaveGlobalID:
790 case ProfileTypeBytecodeFunctionArgument: {
791 globalVariableID = TypeProfilerNoGlobalIDExists;
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000792 break;
793 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000794 case ProfileTypeBytecodeFunctionReturnStatement: {
commit-queue@webkit.orgf6bd2fb2014-08-26 02:17:58 +0000795 RELEASE_ASSERT(ownerExecutable->isFunctionExecutable());
796 globalTypeSet = jsCast<FunctionExecutable*>(ownerExecutable)->returnStatementTypeSet();
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000797 globalVariableID = TypeProfilerReturnStatement;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000798 if (!shouldAnalyze) {
commit-queue@webkit.org9653c662014-08-26 04:36:42 +0000799 // Because a return statement can be added implicitly to return undefined at the end of a function,
800 // and these nodes don't emit expression ranges because they aren't in the actual source text of
801 // the user's program, give the type profiler some range to identify these return statements.
commit-queue@webkit.orgf1d9ed82015-08-17 22:57:23 +0000802 // Currently, the text offset that is used as identification is "f" in the function keyword
commit-queue@webkit.org9653c662014-08-26 04:36:42 +0000803 // and is stored on TypeLocation's m_divotForFunctionOffsetIfReturnStatement member variable.
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000804 divotStart = divotEnd = ownerExecutable->typeProfilingStartOffset();
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000805 shouldAnalyze = true;
806 }
807 break;
808 }
809 }
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000810
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000811 std::pair<TypeLocation*, bool> locationPair = vm.typeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID,
utatane.tea@gmail.com2551c4b2017-02-15 17:09:22 +0000812 ownerExecutable->sourceID(), divotStart, divotEnd, WTFMove(globalTypeSet), &vm);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000813 TypeLocation* location = locationPair.first;
814 bool isNewLocation = locationPair.second;
815
commit-queue@webkit.org9653c662014-08-26 04:36:42 +0000816 if (flag == ProfileTypeBytecodeFunctionReturnStatement)
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +0000817 location->m_divotForFunctionOffsetIfReturnStatement = ownerExecutable->typeProfilingStartOffset();
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000818
819 if (shouldAnalyze && isNewLocation)
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000820 vm.typeProfiler()->insertNewLocation(location);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000821
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000822 instructions[i + 2].u.location = location;
823 break;
824 }
825
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +0000826 case op_debug: {
utatane.tea@gmail.com7b6754e2017-03-01 08:15:45 +0000827 if (pc[1].u.unsignedValue == DidReachBreakpoint)
mark.lam@apple.com3dec4c62014-03-03 22:12:10 +0000828 m_hasDebuggerStatement = true;
829 break;
830 }
831
sbarati@apple.com7a74ce72016-11-01 20:03:03 +0000832 case op_create_rest: {
833 int numberOfArgumentsToSkip = instructions[i + 3].u.operand;
834 ASSERT_UNUSED(numberOfArgumentsToSkip, numberOfArgumentsToSkip >= 0);
utatane.tea@gmail.com463aee12017-03-16 13:24:46 +0000835 // This is used when rematerializing the rest parameter during OSR exit in the FTL JIT.");
836 m_numberOfArgumentsToSkip = numberOfArgumentsToSkip;
sbarati@apple.com7a74ce72016-11-01 20:03:03 +0000837 break;
838 }
sbarati@apple.com60a3be72017-08-25 18:26:15 +0000839
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000840 default:
841 break;
842 }
sbarati@apple.com60a3be72017-08-25 18:26:15 +0000843
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000844 i += opLength;
845 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +0000846
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000847 if (vm.controlFlowProfiler())
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +0000848 insertBasicBlockBoundariesForControlFlowProfiler(instructions);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +0000849
aestes@apple.com13aae082016-01-02 08:03:08 +0000850 m_instructions = WTFMove(instructions);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000851
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +0000852 // Set optimization thresholds only after m_instructions is initialized, since these
853 // rely on the instruction count (and are in theory permitted to also inspect the
854 // instruction stream to more accurate assess the cost of tier-up).
855 optimizeAfterWarmUp();
856 jitAfterWarmUp();
857
oliver@apple.com9e1c8092013-07-25 04:03:16 +0000858 // If the concurrent thread will want the code block's hash, then compute it here
859 // synchronously.
msaboff@apple.com95894332014-01-29 19:18:54 +0000860 if (Options::alwaysComputeHash())
oliver@apple.com9e1c8092013-07-25 04:03:16 +0000861 hash();
862
msaboff@apple.com77adfde2012-11-29 03:16:11 +0000863 if (Options::dumpGeneratedBytecodes())
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +0000864 dumpBytecode();
sbarati@apple.com60a3be72017-08-25 18:26:15 +0000865
akling@apple.comce2ec582016-01-29 20:37:52 +0000866 heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
sbarati@apple.com60a3be72017-08-25 18:26:15 +0000867
commit-queue@webkit.org2162b032017-03-10 02:00:33 +0000868 return true;
weinig@apple.com0e9a7ee2008-12-06 22:31:14 +0000869}
870
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000871void CodeBlock::finishCreationCommon(VM& vm)
872{
873 m_ownerEdge.set(vm, this, ExecutableToCodeBlockEdge::create(vm, this));
874}
875
weinig@apple.com3412bb42008-09-01 21:22:54 +0000876CodeBlock::~CodeBlock()
877{
mark.lam@apple.come875b7e2018-01-08 22:59:10 +0000878 VM& vm = *m_poisonedVM;
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000879
880 vm.heap.codeBlockSet().remove(this);
881
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000882 if (UNLIKELY(vm.m_perBytecodeProfiler))
883 vm.m_perBytecodeProfiler->notifyDestruction(this);
ggaren@apple.com2b404592016-06-15 19:20:23 +0000884
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +0000885 if (!vm.heap.isShuttingDown() && unlinkedCodeBlock()->didOptimize() == MixedTriState)
ggaren@apple.com2b404592016-06-15 19:20:23 +0000886 unlinkedCodeBlock()->setDidOptimize(FalseTriState);
887
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +0000888#if ENABLE(VERBOSE_VALUE_PROFILE)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +0000889 dumpValueProfiles();
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +0000890#endif
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000891
fpizlo@apple.coma4749642011-09-07 02:05:02 +0000892 // We may be destroyed before any CodeBlocks that refer to us are destroyed.
893 // Consider that two CodeBlocks become unreachable at the same time. There
894 // is no guarantee about the order in which the CodeBlocks are destroyed.
895 // So, if we don't remove incoming calls, and get destroyed before the
896 // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's
897 // destructor will try to remove nodes from our (no longer valid) linked list.
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000898 unlinkIncomingCalls();
fpizlo@apple.com594887a2011-09-06 09:23:55 +0000899
900 // Note that our outgoing calls will be removed from other CodeBlocks'
901 // m_incomingCalls linked lists through the execution of the ~CallLinkInfo
902 // destructors.
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +0000903
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000904#if ENABLE(JIT)
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000905 for (auto iter = m_stubInfos.begin(); !!iter; ++iter) {
sbarati@apple.com9aacac42015-10-08 19:37:28 +0000906 StructureStubInfo* stub = *iter;
907 stub->aboutToDie();
908 stub->deref();
909 }
oliver@apple.com942e37d2010-07-07 01:35:56 +0000910#endif // ENABLE(JIT)
weinig@apple.com3412bb42008-09-01 21:22:54 +0000911}
912
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000913void CodeBlock::setConstantIdentifierSetRegisters(VM& vm, const Vector<ConstantIndentifierSetEntry>& constants)
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000914{
915 auto scope = DECLARE_THROW_SCOPE(vm);
916 JSGlobalObject* globalObject = m_globalObject.get();
917 ExecState* exec = globalObject->globalExec();
918
919 for (const auto& entry : constants) {
ticaiolima@gmail.comb2959e52017-08-10 00:42:24 +0000920 const IdentifierSet& set = entry.first;
921
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000922 Structure* setStructure = globalObject->setStructure();
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000923 RETURN_IF_EXCEPTION(scope, void());
ticaiolima@gmail.comb2959e52017-08-10 00:42:24 +0000924 JSSet* jsSet = JSSet::create(exec, vm, setStructure, set.size());
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000925 RETURN_IF_EXCEPTION(scope, void());
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000926
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000927 for (auto setEntry : set) {
928 JSString* jsString = jsOwnedString(&vm, setEntry.get());
929 jsSet->add(exec, jsString);
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000930 RETURN_IF_EXCEPTION(scope, void());
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000931 }
932 m_constantRegisters[entry.second].set(vm, this, jsSet);
933 }
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +0000934}
935
commit-queue@webkit.org55aecf12017-08-09 00:26:04 +0000936void CodeBlock::setConstantRegisters(const Vector<WriteBarrier<Unknown>>& constants, const Vector<SourceCodeRepresentation>& constantsSourceCodeRepresentation)
sbarati@apple.com93c4d332016-04-12 22:42:06 +0000937{
mark.lam@apple.come875b7e2018-01-08 22:59:10 +0000938 VM& vm = *m_poisonedVM;
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000939 auto scope = DECLARE_THROW_SCOPE(vm);
utatane.tea@gmail.com6cd55812017-04-05 07:09:41 +0000940 JSGlobalObject* globalObject = m_globalObject.get();
941 ExecState* exec = globalObject->globalExec();
942
sbarati@apple.com93c4d332016-04-12 22:42:06 +0000943 ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
944 size_t count = constants.size();
945 m_constantRegisters.resizeToFit(count);
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000946 bool hasTypeProfiler = !!vm.typeProfiler();
sbarati@apple.com93c4d332016-04-12 22:42:06 +0000947 for (size_t i = 0; i < count; i++) {
948 JSValue constant = constants[i].get();
949
950 if (!constant.isEmpty()) {
utatane.tea@gmail.com86feb2f2018-03-08 18:24:07 +0000951 if (constant.isCell()) {
952 JSCell* cell = constant.asCell();
953 if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(vm, cell)) {
954 if (hasTypeProfiler) {
955 ConcurrentJSLocker locker(symbolTable->m_lock);
956 symbolTable->prepareForTypeProfiling(locker);
957 }
958
959 SymbolTable* clone = symbolTable->cloneScopePart(vm);
960 if (wasCompiledWithDebuggingOpcodes())
961 clone->setRareDataCodeBlock(this);
962
963 constant = clone;
964 } else if (auto* descriptor = jsDynamicCast<JSTemplateObjectDescriptor*>(vm, cell)) {
965 auto* templateObject = descriptor->createTemplateObject(exec);
966 RETURN_IF_EXCEPTION(scope, void());
967 constant = templateObject;
sbarati@apple.com93c4d332016-04-12 22:42:06 +0000968 }
sbarati@apple.com93c4d332016-04-12 22:42:06 +0000969 }
970 }
971
mark.lam@apple.com4554ee52018-01-08 21:05:17 +0000972 m_constantRegisters[i].set(vm, this, constant);
sbarati@apple.com93c4d332016-04-12 22:42:06 +0000973 }
974
975 m_constantsSourceCodeRepresentation = constantsSourceCodeRepresentation;
976}
977
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000978void CodeBlock::setAlternative(VM& vm, CodeBlock* alternative)
979{
980 m_alternative.set(vm, this, alternative);
981}
982
fpizlo@apple.comc4d54962012-01-10 22:08:47 +0000983void CodeBlock::setNumParameters(int newValue)
984{
985 m_numParameters = newValue;
986
sbarati@apple.comcc032872018-05-11 07:57:21 +0000987 m_argumentValueProfiles = RefCountedArray<ValueProfile>(vm()->canUseJIT() ? newValue : 0);
fpizlo@apple.comc4d54962012-01-10 22:08:47 +0000988}
989
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000990CodeBlock* CodeBlock::specialOSREntryBlockOrNull()
991{
992#if ENABLE(FTL_JIT)
993 if (jitType() != JITCode::DFGJIT)
994 return 0;
995 DFG::JITCode* jitCode = m_jitCode->dfg();
ggaren@apple.com81def5f2015-10-09 23:10:16 +0000996 return jitCode->osrEntryBlock();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000997#else // ENABLE(FTL_JIT)
998 return 0;
999#endif // ENABLE(FTL_JIT)
1000}
1001
commit-queue@webkit.org00eb52f2016-03-01 02:07:12 +00001002size_t CodeBlock::estimatedSize(JSCell* cell)
1003{
1004 CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
1005 size_t extraMemoryAllocated = thisObject->m_instructions.size() * sizeof(Instruction);
1006 if (thisObject->m_jitCode)
1007 extraMemoryAllocated += thisObject->m_jitCode->size();
1008 return Base::estimatedSize(cell) + extraMemoryAllocated;
1009}
1010
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001011void CodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
1012{
1013 CodeBlock* thisObject = jsCast<CodeBlock*>(cell);
1014 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
keith_miller@apple.comcafcf702018-06-22 18:26:36 +00001015 Base::visitChildren(cell, visitor);
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001016 visitor.append(thisObject->m_ownerEdge);
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001017 thisObject->visitChildren(visitor);
1018}
1019
1020void CodeBlock::visitChildren(SlotVisitor& visitor)
1021{
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001022 ConcurrentJSLocker locker(m_lock);
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001023 if (CodeBlock* otherBlock = specialOSREntryBlockOrNull())
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001024 visitor.appendUnbarriered(otherBlock);
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001025
1026 if (m_jitCode)
1027 visitor.reportExtraMemoryVisited(m_jitCode->size());
fpizlo@apple.com8b6ca582016-11-02 22:01:04 +00001028 if (m_instructions.size()) {
1029 unsigned refCount = m_instructions.refCount();
fpizlo@apple.comc1ed3e72017-02-22 00:58:15 +00001030 if (!refCount) {
1031 dataLog("CodeBlock: ", RawPointer(this), "\n");
1032 dataLog("m_instructions.data(): ", RawPointer(m_instructions.data()), "\n");
1033 dataLog("refCount: ", refCount, "\n");
1034 RELEASE_ASSERT_NOT_REACHED();
1035 }
fpizlo@apple.com8b6ca582016-11-02 22:01:04 +00001036 visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / refCount);
1037 }
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001038
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001039 stronglyVisitStrongReferences(locker, visitor);
1040 stronglyVisitWeakReferences(locker, visitor);
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001041
1042 VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).add(this);
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001043}
1044
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001045bool CodeBlock::shouldVisitStrongly(const ConcurrentJSLocker& locker)
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00001046{
ggaren@apple.com05483852015-09-17 00:28:34 +00001047 if (Options::forceCodeBlockLiveness())
1048 return true;
1049
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001050 if (shouldJettisonDueToOldAge(locker))
ggaren@apple.com05483852015-09-17 00:28:34 +00001051 return false;
1052
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00001053 // Interpreter and Baseline JIT CodeBlocks don't need to be jettisoned when
1054 // their weak references go stale. So if a basline JIT CodeBlock gets
1055 // scanned, we can assume that this means that it's live.
1056 if (!JITCode::isOptimizingJIT(jitType()))
1057 return true;
1058
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00001059 return false;
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00001060}
1061
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001062bool CodeBlock::shouldJettisonDueToWeakReference()
1063{
ggaren@apple.com05483852015-09-17 00:28:34 +00001064 if (!JITCode::isOptimizingJIT(jitType()))
1065 return false;
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001066 return !Heap::isMarked(this);
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001067}
1068
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001069static Seconds timeToLive(JITCode::JITType jitType)
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001070{
1071 if (UNLIKELY(Options::useEagerCodeBlockJettisonTiming())) {
1072 switch (jitType) {
1073 case JITCode::InterpreterThunk:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001074 return 10_ms;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001075 case JITCode::BaselineJIT:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001076 return 30_ms;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001077 case JITCode::DFGJIT:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001078 return 40_ms;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001079 case JITCode::FTLJIT:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001080 return 120_ms;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001081 default:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001082 return Seconds::infinity();
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001083 }
1084 }
1085
1086 switch (jitType) {
1087 case JITCode::InterpreterThunk:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001088 return 5_s;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001089 case JITCode::BaselineJIT:
1090 // Effectively 10 additional seconds, since BaselineJIT and
1091 // InterpreterThunk share a CodeBlock.
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001092 return 15_s;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001093 case JITCode::DFGJIT:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001094 return 20_s;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001095 case JITCode::FTLJIT:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001096 return 60_s;
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001097 default:
utatane.tea@gmail.com5c7039d2017-12-27 00:33:11 +00001098 return Seconds::infinity();
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001099 }
1100}
1101
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001102bool CodeBlock::shouldJettisonDueToOldAge(const ConcurrentJSLocker&)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001103{
fpizlo@apple.comfb7cb892017-12-05 17:53:57 +00001104 if (Heap::isMarked(this))
sbarati@apple.com293f5da2016-08-05 06:46:55 +00001105 return false;
1106
1107 if (UNLIKELY(Options::forceCodeBlockToJettisonDueToOldAge()))
1108 return true;
1109
1110 if (timeSinceCreation() < timeToLive(jitType()))
1111 return false;
1112
1113 return true;
fpizlo@apple.com04a048c2014-04-28 19:01:07 +00001114}
1115
fpizlo@apple.com4adaa962014-08-06 05:55:39 +00001116#if ENABLE(DFG_JIT)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001117static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition)
1118{
fpizlo@apple.comfb7cb892017-12-05 17:53:57 +00001119 if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get()))
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001120 return false;
1121
fpizlo@apple.comfb7cb892017-12-05 17:53:57 +00001122 if (!Heap::isMarked(transition.m_from.get()))
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001123 return false;
1124
1125 return true;
1126}
fpizlo@apple.com4adaa962014-08-06 05:55:39 +00001127#endif // ENABLE(DFG_JIT)
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001128
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001129void CodeBlock::propagateTransitions(const ConcurrentJSLocker&, SlotVisitor& visitor)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001130{
1131 UNUSED_PARAM(visitor);
oliver@apple.coma1524712013-07-25 04:01:56 +00001132
commit-queue@webkit.orge30a9cd42018-01-10 19:41:12 +00001133 VM& vm = *m_poisonedVM;
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001134
oliver@apple.coma1524712013-07-25 04:01:56 +00001135 if (jitType() == JITCode::InterpreterThunk) {
1136 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
oliver@apple.comc0a31d72013-07-25 04:03:36 +00001137 for (size_t i = 0; i < propertyAccessInstructions.size(); ++i) {
oliver@apple.coma1524712013-07-25 04:01:56 +00001138 Instruction* instruction = &instructions()[propertyAccessInstructions[i]];
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00001139 switch (Interpreter::getOpcodeID(instruction[0])) {
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001140 case op_put_by_id: {
1141 StructureID oldStructureID = instruction[4].u.structureID;
1142 StructureID newStructureID = instruction[6].u.structureID;
1143 if (!oldStructureID || !newStructureID)
1144 break;
1145 Structure* oldStructure =
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001146 vm.heap.structureIDTable().get(oldStructureID);
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001147 Structure* newStructure =
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001148 vm.heap.structureIDTable().get(newStructureID);
fpizlo@apple.comfb7cb892017-12-05 17:53:57 +00001149 if (Heap::isMarked(oldStructure))
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001150 visitor.appendUnbarriered(newStructure);
oliver@apple.coma1524712013-07-25 04:01:56 +00001151 break;
1152 }
1153 default:
1154 break;
1155 }
1156 }
1157 }
oliver@apple.coma1524712013-07-25 04:01:56 +00001158
1159#if ENABLE(JIT)
1160 if (JITCode::isJIT(jitType())) {
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001161 for (auto iter = m_stubInfos.begin(); !!iter; ++iter)
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001162 (*iter)->propagateTransitions(visitor);
oliver@apple.coma1524712013-07-25 04:01:56 +00001163 }
1164#endif // ENABLE(JIT)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001165
1166#if ENABLE(DFG_JIT)
oliver@apple.coma1524712013-07-25 04:01:56 +00001167 if (JITCode::isOptimizingJIT(jitType())) {
1168 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
fpizlo@apple.comdd39b9e2016-05-04 02:23:28 +00001169 for (auto& weakReference : dfgCommon->weakStructureReferences)
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001170 weakReference->markIfCheap(visitor);
annulen@yandex.ru23120122016-12-20 18:26:10 +00001171
1172 for (auto& transition : dfgCommon->transitions) {
1173 if (shouldMarkTransition(transition)) {
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001174 // If the following three things are live, then the target of the
1175 // transition is also live:
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001176 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001177 // - This code block. We know it's live already because otherwise
1178 // we wouldn't be scanning ourselves.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001179 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001180 // - The code origin of the transition. Transitions may arise from
1181 // code that was inlined. They are not relevant if the user's
1182 // object that is required for the inlinee to run is no longer
1183 // live.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001184 //
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001185 // - The source of the transition. The transition checks if some
1186 // heap location holds the source, and if so, stores the target.
1187 // Hence the source must be live for the transition to be live.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001188 //
1189 // We also short-circuit the liveness if the structure is harmless
1190 // to mark (i.e. its global object and prototype are both already
1191 // live).
annulen@yandex.ru23120122016-12-20 18:26:10 +00001192
1193 visitor.append(transition.m_to);
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001194 }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001195 }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001196 }
oliver@apple.coma1524712013-07-25 04:01:56 +00001197#endif // ENABLE(DFG_JIT)
oliver@apple.coma1524712013-07-25 04:01:56 +00001198}
1199
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001200void CodeBlock::determineLiveness(const ConcurrentJSLocker&, SlotVisitor& visitor)
oliver@apple.coma1524712013-07-25 04:01:56 +00001201{
1202 UNUSED_PARAM(visitor);
1203
oliver@apple.coma1524712013-07-25 04:01:56 +00001204#if ENABLE(DFG_JIT)
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001205 if (Heap::isMarked(this))
commit-queue@webkit.orge30a9cd42018-01-10 19:41:12 +00001206 return;
1207
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001208 // In rare and weird cases, this could be called on a baseline CodeBlock. One that I found was
1209 // that we might decide that the CodeBlock should be jettisoned due to old age, so the
1210 // isMarked check doesn't protect us.
1211 if (!JITCode::isOptimizingJIT(jitType()))
1212 return;
1213
1214 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001215 // Now check all of our weak references. If all of them are live, then we
1216 // have proved liveness and so we scan our strong references. If at end of
1217 // GC we still have not proved liveness, then this code block is toast.
1218 bool allAreLiveSoFar = true;
oliver@apple.com02b179b2013-07-25 03:58:20 +00001219 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
keith_miller@apple.com45da7602017-01-27 01:47:52 +00001220 JSCell* reference = dfgCommon->weakReferences[i].get();
1221 ASSERT(!jsDynamicCast<CodeBlock*>(*reference->vm(), reference));
fpizlo@apple.comfb7cb892017-12-05 17:53:57 +00001222 if (!Heap::isMarked(reference)) {
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001223 allAreLiveSoFar = false;
1224 break;
1225 }
1226 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001227 if (allAreLiveSoFar) {
1228 for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) {
fpizlo@apple.comfb7cb892017-12-05 17:53:57 +00001229 if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001230 allAreLiveSoFar = false;
1231 break;
1232 }
1233 }
1234 }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001235
1236 // If some weak references are dead, then this fixpoint iteration was
1237 // unsuccessful.
1238 if (!allAreLiveSoFar)
1239 return;
1240
1241 // All weak references are live. Record this information so we don't
1242 // come back here again, and scan the strong references.
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001243 visitor.appendUnbarriered(this);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001244#endif // ENABLE(DFG_JIT)
1245}
1246
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00001247void CodeBlock::clearLLIntGetByIdCache(Instruction* instruction)
1248{
1249 instruction[0].u.opcode = LLInt::getOpcode(op_get_by_id);
1250 instruction[4].u.pointer = nullptr;
1251 instruction[5].u.pointer = nullptr;
1252 instruction[6].u.pointer = nullptr;
1253}
1254
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001255void CodeBlock::finalizeLLIntInlineCaches()
fpizlo@apple.comcf716122012-07-13 06:41:18 +00001256{
mark.lam@apple.come875b7e2018-01-08 22:59:10 +00001257 VM& vm = *m_poisonedVM;
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001258 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
1259 for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
1260 Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00001261 switch (Interpreter::getOpcodeID(curInstruction[0])) {
keith_miller@apple.com94d4d912018-05-30 23:07:16 +00001262 case op_get_by_id: {
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001263 StructureID oldStructureID = curInstruction[4].u.structureID;
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001264 if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001265 break;
1266 if (Options::verboseOSR())
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001267 dataLogF("Clearing LLInt property access.\n");
keith_miller@apple.com30e90262016-06-02 21:24:21 +00001268 clearLLIntGetByIdCache(curInstruction);
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001269 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001270 }
utatane.tea@gmail.com0e0c28a2018-04-08 16:21:38 +00001271 case op_get_by_id_direct: {
1272 StructureID oldStructureID = curInstruction[4].u.structureID;
1273 if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
1274 break;
1275 if (Options::verboseOSR())
1276 dataLogF("Clearing LLInt property access.\n");
1277 curInstruction[4].u.pointer = nullptr;
1278 curInstruction[5].u.pointer = nullptr;
1279 break;
1280 }
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001281 case op_put_by_id: {
1282 StructureID oldStructureID = curInstruction[4].u.structureID;
1283 StructureID newStructureID = curInstruction[6].u.structureID;
1284 StructureChain* chain = curInstruction[7].u.structureChain.get();
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001285 if ((!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
1286 && (!newStructureID || Heap::isMarked(vm.heap.structureIDTable().get(newStructureID)))
1287 && (!chain || Heap::isMarked(chain)))
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001288 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001289 if (Options::verboseOSR())
1290 dataLogF("Clearing LLInt put transition.\n");
1291 curInstruction[4].u.structureID = 0;
1292 curInstruction[5].u.operand = 0;
1293 curInstruction[6].u.structureID = 0;
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001294 curInstruction[7].u.structureChain.clear();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001295 break;
fpizlo@apple.come7ec7fb2015-09-15 00:55:17 +00001296 }
gskachkov@gmail.com077d7d52017-04-30 08:06:23 +00001297 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=166418
1298 // We need to add optimizations for op_resolve_scope_for_hoisting_func_decl_in_eval to do link time scope resolution.
1299 case op_resolve_scope_for_hoisting_func_decl_in_eval:
1300 break;
keith_miller@apple.com94d4d912018-05-30 23:07:16 +00001301 case op_get_by_id_proto_load:
1302 case op_get_by_id_unset:
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001303 case op_get_array_length:
1304 break;
1305 case op_to_this:
1306 if (!curInstruction[2].u.structure || Heap::isMarked(curInstruction[2].u.structure.get()))
1307 break;
1308 if (Options::verboseOSR())
1309 dataLogF("Clearing LLInt to_this with structure %p.\n", curInstruction[2].u.structure.get());
1310 curInstruction[2].u.structure.clear();
1311 curInstruction[3].u.toThisStatus = merge(
1312 curInstruction[3].u.toThisStatus, ToThisClearedByGC);
1313 break;
1314 case op_create_this: {
1315 auto& cacheWriteBarrier = curInstruction[4].u.jsCell;
1316 if (!cacheWriteBarrier || cacheWriteBarrier.unvalidatedGet() == JSCell::seenMultipleCalleeObjects())
1317 break;
1318 JSCell* cachedFunction = cacheWriteBarrier.get();
1319 if (Heap::isMarked(cachedFunction))
1320 break;
1321 if (Options::verboseOSR())
1322 dataLogF("Clearing LLInt create_this with cached callee %p.\n", cachedFunction);
1323 cacheWriteBarrier.clear();
1324 break;
1325 }
1326 case op_resolve_scope: {
1327 // Right now this isn't strictly necessary. Any symbol tables that this will refer to
1328 // are for outer functions, and we refer to those functions strongly, and they refer
1329 // to the symbol table strongly. But it's nice to be on the safe side.
1330 WriteBarrierBase<SymbolTable>& symbolTable = curInstruction[6].u.symbolTable;
1331 if (!symbolTable || Heap::isMarked(symbolTable.get()))
1332 break;
1333 if (Options::verboseOSR())
1334 dataLogF("Clearing dead symbolTable %p.\n", symbolTable.get());
1335 symbolTable.clear();
1336 break;
1337 }
1338 case op_get_from_scope:
1339 case op_put_to_scope: {
1340 GetPutInfo getPutInfo = GetPutInfo(curInstruction[4].u.operand);
1341 if (getPutInfo.resolveType() == GlobalVar || getPutInfo.resolveType() == GlobalVarWithVarInjectionChecks
1342 || getPutInfo.resolveType() == LocalClosureVar || getPutInfo.resolveType() == GlobalLexicalVar || getPutInfo.resolveType() == GlobalLexicalVarWithVarInjectionChecks)
1343 continue;
1344 WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;
1345 if (!structure || Heap::isMarked(structure.get()))
1346 break;
1347 if (Options::verboseOSR())
1348 dataLogF("Clearing scope access with structure %p.\n", structure.get());
1349 structure.clear();
1350 break;
1351 }
1352 default:
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00001353 OpcodeID opcodeID = Interpreter::getOpcodeID(curInstruction[0]);
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001354 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 +00001355 }
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00001356 }
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00001357
commit-queue@webkit.org687ce622018-05-11 21:16:05 +00001358 // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set
1359 // then cleared the cache without GCing in between.
keith_miller@apple.com94d4d912018-05-30 23:07:16 +00001360 m_llintGetByIdWatchpointMap.removeIf([&] (const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
1361 auto clear = [&] () {
1362 Instruction* instruction = std::get<1>(pair.key);
1363 OpcodeID opcode = Interpreter::getOpcodeID(*instruction);
1364 if (opcode == op_get_by_id_proto_load || opcode == op_get_by_id_unset) {
1365 if (Options::verboseOSR())
1366 dataLogF("Clearing LLInt property access.\n");
1367 clearLLIntGetByIdCache(instruction);
1368 }
1369 return true;
1370 };
1371
1372 if (!Heap::isMarked(std::get<0>(pair.key)))
1373 return clear();
1374
1375 for (const LLIntPrototypeLoadAdaptiveStructureWatchpoint* watchpoint : pair.value) {
1376 if (!watchpoint->key().isStillLive())
1377 return clear();
1378 }
1379
1380 return false;
commit-queue@webkit.org687ce622018-05-11 21:16:05 +00001381 });
1382
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001383 for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
1384 if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
1385 if (Options::verboseOSR())
1386 dataLog("Clearing LLInt call from ", *this, "\n");
1387 m_llintCallLinkInfos[i].unlink();
fpizlo@apple.com1e89af32012-11-19 02:55:14 +00001388 }
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001389 if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get()))
1390 m_llintCallLinkInfos[i].lastSeenCallee.clear();
1391 }
1392}
1393
1394void CodeBlock::finalizeBaselineJITInlineCaches()
1395{
ggaren@apple.com95bf67e2015-09-11 17:35:59 +00001396#if ENABLE(JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001397 for (auto iter = callLinkInfosBegin(); !!iter; ++iter)
1398 (*iter)->visitWeak(*vm());
1399
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001400 for (auto iter = m_stubInfos.begin(); !!iter; ++iter) {
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001401 StructureStubInfo& stubInfo = **iter;
1402 stubInfo.visitWeakReferences(this);
1403 }
ggaren@apple.com95bf67e2015-09-11 17:35:59 +00001404#endif
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001405}
1406
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001407void CodeBlock::finalizeUnconditionally(VM&)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001408{
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001409 updateAllPredictions();
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001410
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001411 if (JITCode::couldBeInterpreted(jitType()))
1412 finalizeLLIntInlineCaches();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001413
1414#if ENABLE(JIT)
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001415 if (!!jitCode())
1416 finalizeBaselineJITInlineCaches();
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001417#endif
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001418
1419 VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).remove(this);
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001420}
1421
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001422void CodeBlock::getStubInfoMap(const ConcurrentJSLocker&, StubInfoMap& result)
msaboff@apple.com95894332014-01-29 19:18:54 +00001423{
1424#if ENABLE(JIT)
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00001425 if (JITCode::isJIT(jitType()))
1426 toHashMap(m_stubInfos, getStructureStubInfoCodeOrigin, result);
msaboff@apple.com95894332014-01-29 19:18:54 +00001427#else
1428 UNUSED_PARAM(result);
1429#endif
1430}
1431
1432void CodeBlock::getStubInfoMap(StubInfoMap& result)
1433{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001434 ConcurrentJSLocker locker(m_lock);
msaboff@apple.com95894332014-01-29 19:18:54 +00001435 getStubInfoMap(locker, result);
1436}
1437
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001438void CodeBlock::getCallLinkInfoMap(const ConcurrentJSLocker&, CallLinkInfoMap& result)
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001439{
1440#if ENABLE(JIT)
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00001441 if (JITCode::isJIT(jitType()))
1442 toHashMap(m_callLinkInfos, getCallLinkInfoCodeOrigin, result);
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001443#else
1444 UNUSED_PARAM(result);
1445#endif
1446}
1447
1448void CodeBlock::getCallLinkInfoMap(CallLinkInfoMap& result)
1449{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001450 ConcurrentJSLocker locker(m_lock);
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001451 getCallLinkInfoMap(locker, result);
1452}
1453
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001454void CodeBlock::getByValInfoMap(const ConcurrentJSLocker&, ByValInfoMap& result)
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00001455{
1456#if ENABLE(JIT)
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00001457 if (JITCode::isJIT(jitType())) {
1458 for (auto* byValInfo : m_byValInfos)
1459 result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo);
1460 }
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00001461#else
1462 UNUSED_PARAM(result);
1463#endif
1464}
1465
1466void CodeBlock::getByValInfoMap(ByValInfoMap& result)
1467{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001468 ConcurrentJSLocker locker(m_lock);
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00001469 getByValInfoMap(locker, result);
1470}
1471
fpizlo@apple.comcf716122012-07-13 06:41:18 +00001472#if ENABLE(JIT)
fpizlo@apple.comb26b5242015-09-10 19:49:36 +00001473StructureStubInfo* CodeBlock::addStubInfo(AccessType accessType)
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00001474{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001475 ConcurrentJSLocker locker(m_lock);
fpizlo@apple.comb26b5242015-09-10 19:49:36 +00001476 return m_stubInfos.add(accessType);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +00001477}
1478
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001479JITAddIC* CodeBlock::addJITAddIC(ArithProfile* arithProfile, Instruction* instruction)
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001480{
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001481 return m_addICs.add(arithProfile, instruction);
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001482}
1483
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001484JITMulIC* CodeBlock::addJITMulIC(ArithProfile* arithProfile, Instruction* instruction)
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001485{
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001486 return m_mulICs.add(arithProfile, instruction);
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001487}
1488
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001489JITSubIC* CodeBlock::addJITSubIC(ArithProfile* arithProfile, Instruction* instruction)
sbarati@apple.com3e7ec7d2016-08-01 18:48:14 +00001490{
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001491 return m_subICs.add(arithProfile, instruction);
sbarati@apple.com3e7ec7d2016-08-01 18:48:14 +00001492}
1493
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001494JITNegIC* CodeBlock::addJITNegIC(ArithProfile* arithProfile, Instruction* instruction)
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00001495{
mark.lam@apple.com18b4eab2018-03-31 07:04:00 +00001496 return m_negICs.add(arithProfile, instruction);
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00001497}
1498
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00001499StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
1500{
1501 for (StructureStubInfo* stubInfo : m_stubInfos) {
1502 if (stubInfo->codeOrigin == codeOrigin)
1503 return stubInfo;
1504 }
1505 return nullptr;
1506}
1507
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00001508ByValInfo* CodeBlock::addByValInfo()
1509{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001510 ConcurrentJSLocker locker(m_lock);
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00001511 return m_byValInfos.add();
1512}
1513
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001514CallLinkInfo* CodeBlock::addCallLinkInfo()
1515{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001516 ConcurrentJSLocker locker(m_lock);
fpizlo@apple.comba262b22014-03-23 04:34:38 +00001517 return m_callLinkInfos.add();
1518}
1519
fpizlo@apple.comf7100b62014-03-24 17:29:51 +00001520CallLinkInfo* CodeBlock::getCallLinkInfoForBytecodeIndex(unsigned index)
1521{
1522 for (auto iter = m_callLinkInfos.begin(); !!iter; ++iter) {
msaboff@apple.com203a56e2015-06-24 22:37:30 +00001523 if ((*iter)->codeOrigin() == CodeOrigin(index))
fpizlo@apple.comf7100b62014-03-24 17:29:51 +00001524 return *iter;
1525 }
1526 return nullptr;
1527}
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00001528
1529void CodeBlock::resetJITData()
1530{
1531 RELEASE_ASSERT(!JITCode::isJIT(jitType()));
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001532 ConcurrentJSLocker locker(m_lock);
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00001533
1534 // We can clear these because no other thread will have references to any stub infos, call
1535 // link infos, or by val infos if we don't have JIT code. Attempts to query these data
1536 // structures using the concurrent API (getStubInfoMap and friends) will return nothing if we
1537 // don't have JIT code.
1538 m_stubInfos.clear();
1539 m_callLinkInfos.clear();
1540 m_byValInfos.clear();
1541
1542 // We can clear this because the DFG's queries to these data structures are guarded by whether
1543 // there is JIT code.
1544 m_rareCaseProfiles.clear();
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00001545}
fpizlo@apple.comcf716122012-07-13 06:41:18 +00001546#endif
1547
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001548void CodeBlock::visitOSRExitTargets(const ConcurrentJSLocker&, SlotVisitor& visitor)
ggaren@apple.com156eb592015-09-09 22:06:49 +00001549{
ggaren@apple.com05483852015-09-17 00:28:34 +00001550 // We strongly visit OSR exits targets because we don't want to deal with
1551 // the complexity of generating an exit target CodeBlock on demand and
1552 // guaranteeing that it matches the details of the CodeBlock we compiled
1553 // the OSR exit against.
ggaren@apple.com156eb592015-09-09 22:06:49 +00001554
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001555 visitor.append(m_alternative);
ggaren@apple.com156eb592015-09-09 22:06:49 +00001556
ggaren@apple.com6520f0c2015-09-09 22:26:16 +00001557#if ENABLE(DFG_JIT)
ggaren@apple.com156eb592015-09-09 22:06:49 +00001558 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
1559 if (dfgCommon->inlineCallFrames) {
ggaren@apple.com05483852015-09-17 00:28:34 +00001560 for (auto* inlineCallFrame : *dfgCommon->inlineCallFrames) {
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001561 ASSERT(inlineCallFrame->baselineCodeBlock);
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001562 visitor.append(inlineCallFrame->baselineCodeBlock);
ggaren@apple.com05483852015-09-17 00:28:34 +00001563 }
ggaren@apple.com156eb592015-09-09 22:06:49 +00001564 }
ggaren@apple.com6520f0c2015-09-09 22:26:16 +00001565#endif
ggaren@apple.com156eb592015-09-09 22:06:49 +00001566}
1567
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001568void CodeBlock::stronglyVisitStrongReferences(const ConcurrentJSLocker& locker, SlotVisitor& visitor)
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +00001569{
fpizlo@apple.coma2b5a3d2016-11-18 22:29:11 +00001570 UNUSED_PARAM(locker);
1571
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001572 visitor.append(m_globalObject);
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00001573 visitor.append(m_ownerExecutable); // This is extra important since it causes the ExecutableToCodeBlockEdge to be marked.
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001574 visitor.append(m_unlinkedCode);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001575 if (m_rareData)
ggaren@apple.com572890a2016-12-01 21:47:34 +00001576 m_rareData->m_directEvalCodeCache.visitAggregate(visitor);
oliver@apple.com433d02f2011-04-21 23:08:15 +00001577 visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
annulen@yandex.ru23120122016-12-20 18:26:10 +00001578 for (auto& functionExpr : m_functionExprs)
1579 visitor.append(functionExpr);
1580 for (auto& functionDecl : m_functionDecls)
1581 visitor.append(functionDecl);
1582 for (auto& objectAllocationProfile : m_objectAllocationProfiles)
1583 objectAllocationProfile.visitAggregate(visitor);
fpizlo@apple.comd13163d2011-09-03 05:14:04 +00001584
utatane.tea@gmail.comfb586932016-07-29 07:59:29 +00001585#if ENABLE(JIT)
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00001586 for (ByValInfo* byValInfo : m_byValInfos)
fpizlo@apple.comf7240e02016-12-16 02:16:19 +00001587 visitor.append(byValInfo->cachedSymbol);
utatane.tea@gmail.comfb586932016-07-29 07:59:29 +00001588#endif
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00001589
ggaren@apple.com156eb592015-09-09 22:06:49 +00001590#if ENABLE(DFG_JIT)
1591 if (JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001592 visitOSRExitTargets(locker, visitor);
ggaren@apple.com156eb592015-09-09 22:06:49 +00001593#endif
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00001594}
1595
fpizlo@apple.com71a012b2016-11-18 22:11:51 +00001596void CodeBlock::stronglyVisitWeakReferences(const ConcurrentJSLocker&, SlotVisitor& visitor)
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00001597{
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00001598 UNUSED_PARAM(visitor);
1599
1600#if ENABLE(DFG_JIT)
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00001601 if (!JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00001602 return;
oliver@apple.com02b179b2013-07-25 03:58:20 +00001603
1604 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00001605
annulen@yandex.ru23120122016-12-20 18:26:10 +00001606 for (auto& transition : dfgCommon->transitions) {
1607 if (!!transition.m_codeOrigin)
1608 visitor.append(transition.m_codeOrigin); // Almost certainly not necessary, since the code origin should also be a weak reference. Better to be safe, though.
1609 visitor.append(transition.m_from);
1610 visitor.append(transition.m_to);
fpizlo@apple.com5e37f9a2011-11-17 00:49:50 +00001611 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001612
annulen@yandex.ru23120122016-12-20 18:26:10 +00001613 for (auto& weakReference : dfgCommon->weakReferences)
1614 visitor.append(weakReference);
1615
1616 for (auto& weakStructureReference : dfgCommon->weakStructureReferences)
1617 visitor.append(weakStructureReference);
ggaren@apple.com51be9a22015-09-09 22:00:58 +00001618
1619 dfgCommon->livenessHasBeenProved = true;
ggaren@apple.com7ac9ed82011-11-17 01:43:48 +00001620#endif
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001621}
1622
fpizlo@apple.com501e6062013-11-01 22:10:52 +00001623CodeBlock* CodeBlock::baselineAlternative()
1624{
1625#if ENABLE(JIT)
1626 CodeBlock* result = this;
1627 while (result->alternative())
1628 result = result->alternative();
1629 RELEASE_ASSERT(result);
1630 RELEASE_ASSERT(JITCode::isBaselineCode(result->jitType()) || result->jitType() == JITCode::None);
1631 return result;
1632#else
1633 return this;
1634#endif
1635}
1636
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001637CodeBlock* CodeBlock::baselineVersion()
1638{
fpizlo@apple.com501e6062013-11-01 22:10:52 +00001639#if ENABLE(JIT)
fpizlo@apple.com669223d2013-09-01 02:02:47 +00001640 if (JITCode::isBaselineCode(jitType()))
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001641 return this;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001642 CodeBlock* result = replacement();
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00001643 if (!result) {
1644 // This can happen if we're creating the original CodeBlock for an executable.
1645 // Assume that we're the baseline CodeBlock.
fpizlo@apple.com501e6062013-11-01 22:10:52 +00001646 RELEASE_ASSERT(jitType() == JITCode::None);
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00001647 return this;
1648 }
fpizlo@apple.com501e6062013-11-01 22:10:52 +00001649 result = result->baselineAlternative();
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001650 return result;
1651#else
fpizlo@apple.comcd8eb2c2013-09-20 18:42:41 +00001652 return this;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001653#endif
1654}
1655
1656#if ENABLE(JIT)
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001657bool CodeBlock::hasOptimizedReplacement(JITCode::JITType typeToReplace)
1658{
1659 return JITCode::isHigherTier(replacement()->jitType(), typeToReplace);
1660}
1661
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001662bool CodeBlock::hasOptimizedReplacement()
1663{
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001664 return hasOptimizedReplacement(jitType());
oliver@apple.com284cc3d2013-07-25 04:00:33 +00001665}
1666#endif
1667
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00001668HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler requiredHandler)
mrowe@apple.comf88a4632008-09-07 05:44:58 +00001669{
oliver@apple.com49a2c142013-04-04 21:25:26 +00001670 RELEASE_ASSERT(bytecodeOffset < instructions().size());
sbarati@apple.com36c13402015-09-18 23:37:42 +00001671 return handlerForIndex(bytecodeOffset, requiredHandler);
1672}
weinig@apple.com06885cf2008-12-17 21:25:40 +00001673
sbarati@apple.com36c13402015-09-18 23:37:42 +00001674HandlerInfo* CodeBlock::handlerForIndex(unsigned index, RequiredHandler requiredHandler)
1675{
weinig@apple.com4557e842008-12-09 01:06:14 +00001676 if (!m_rareData)
1677 return 0;
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +00001678 return HandlerInfo::handlerForIndex(m_rareData->m_exceptionHandlers, index, requiredHandler);
mrowe@apple.comf88a4632008-09-07 05:44:58 +00001679}
1680
sbarati@apple.com9aacac42015-10-08 19:37:28 +00001681CallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite)
1682{
1683#if ENABLE(DFG_JIT)
sbarati@apple.com5bebda72015-11-10 07:48:54 +00001684 RELEASE_ASSERT(JITCode::isOptimizingJIT(jitType()));
sbarati@apple.com9aacac42015-10-08 19:37:28 +00001685 RELEASE_ASSERT(canGetCodeOrigin(originalCallSite));
1686 ASSERT(!!handlerForIndex(originalCallSite.bits()));
1687 CodeOrigin originalOrigin = codeOrigin(originalCallSite);
sbarati@apple.com2697fe72015-10-12 20:37:05 +00001688 return m_jitCode->dfgCommon()->addUniqueCallSiteIndex(originalOrigin);
sbarati@apple.com9aacac42015-10-08 19:37:28 +00001689#else
1690 // We never create new on-the-fly exception handling
1691 // call sites outside the DFG/FTL inline caches.
sbarati@apple.com9bf79cf2015-10-08 20:24:25 +00001692 UNUSED_PARAM(originalCallSite);
sbarati@apple.com9aacac42015-10-08 19:37:28 +00001693 RELEASE_ASSERT_NOT_REACHED();
mark.lam@apple.comceb2fc22015-10-14 16:23:16 +00001694 return CallSiteIndex(0u);
sbarati@apple.com9aacac42015-10-08 19:37:28 +00001695#endif
1696}
1697
sbarati@apple.com60a3be72017-08-25 18:26:15 +00001698void CodeBlock::ensureCatchLivenessIsComputedForBytecodeOffsetSlow(unsigned bytecodeOffset)
1699{
1700 ASSERT(Interpreter::getOpcodeID(m_instructions[bytecodeOffset]) == op_catch);
1701 BytecodeLivenessAnalysis& bytecodeLiveness = livenessAnalysis();
1702
1703 // We get the live-out set of variables at op_catch, not the live-in. This
1704 // is because the variables that the op_catch defines might be dead, and
1705 // we can avoid profiling them and extracting them when doing OSR entry
1706 // into the DFG.
sbarati@apple.com34906fa2017-10-28 01:03:22 +00001707 FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset(this, bytecodeOffset + OPCODE_LENGTH(op_catch));
sbarati@apple.com60a3be72017-08-25 18:26:15 +00001708 Vector<VirtualRegister> liveOperands;
1709 liveOperands.reserveInitialCapacity(liveLocals.bitCount());
1710 liveLocals.forEachSetBit([&] (unsigned liveLocal) {
1711 liveOperands.append(virtualRegisterForLocal(liveLocal));
1712 });
1713
1714 for (int i = 0; i < numParameters(); ++i)
1715 liveOperands.append(virtualRegisterForArgument(i));
1716
1717 auto profiles = std::make_unique<ValueProfileAndOperandBuffer>(liveOperands.size());
1718 RELEASE_ASSERT(profiles->m_size == liveOperands.size());
1719 for (unsigned i = 0; i < profiles->m_size; ++i)
1720 profiles->m_buffer.get()[i].m_operand = liveOperands[i].offset();
sbarati@apple.com941e82c2017-10-31 01:15:08 +00001721
1722 // The compiler thread will read this pointer value and then proceed to dereference it
1723 // if it is not null. We need to make sure all above stores happen before this store so
1724 // the compiler thread reads fully initialized data.
1725 WTF::storeStoreFence();
1726
sbarati@apple.com60a3be72017-08-25 18:26:15 +00001727 m_instructions[bytecodeOffset + 3].u.pointer = profiles.get();
1728
1729 {
1730 ConcurrentJSLocker locker(m_lock);
1731 m_catchProfiles.append(WTFMove(profiles));
1732 }
1733}
1734
sbarati@apple.com9aacac42015-10-08 19:37:28 +00001735void CodeBlock::removeExceptionHandlerForCallSite(CallSiteIndex callSiteIndex)
1736{
1737 RELEASE_ASSERT(m_rareData);
1738 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
1739 unsigned index = callSiteIndex.bits();
1740 for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
1741 HandlerInfo& handler = exceptionHandlers[i];
1742 if (handler.start <= index && handler.end > index) {
1743 exceptionHandlers.remove(i);
1744 return;
1745 }
1746 }
1747
1748 RELEASE_ASSERT_NOT_REACHED();
1749}
1750
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001751unsigned CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001752{
oliver@apple.com903b0c02013-01-24 01:40:37 +00001753 RELEASE_ASSERT(bytecodeOffset < instructions().size());
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001754 return ownerScriptExecutable()->firstLine() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001755}
1756
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001757unsigned CodeBlock::columnNumberForBytecodeOffset(unsigned bytecodeOffset)
oliver@apple.com90b88ae2008-07-19 01:44:24 +00001758{
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001759 int divot;
1760 int startOffset;
1761 int endOffset;
1762 unsigned line;
1763 unsigned column;
1764 expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
1765 return column;
1766}
1767
mark.lam@apple.com068a9522016-06-10 00:42:19 +00001768void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) const
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001769{
1770 m_unlinkedCode->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column);
oliver@apple.comf0c01b82012-11-07 00:13:54 +00001771 divot += m_sourceOffset;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00001772 column += line ? 1 : firstLineColumnOffset();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001773 line += ownerScriptExecutable()->firstLine();
oliver@apple.com90b88ae2008-07-19 01:44:24 +00001774}
1775
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001776bool CodeBlock::hasOpDebugForLineAndColumn(unsigned line, unsigned column)
1777{
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001778 const Instruction* begin = instructions().begin();
1779 const Instruction* end = instructions().end();
1780 for (const Instruction* it = begin; it != end;) {
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00001781 OpcodeID opcodeID = Interpreter::getOpcodeID(*it);
mark.lam@apple.com945b1392014-01-23 07:39:58 +00001782 if (opcodeID == op_debug) {
1783 unsigned bytecodeOffset = it - begin;
1784 int unused;
1785 unsigned opDebugLine;
1786 unsigned opDebugColumn;
1787 expressionRangeForBytecodeOffset(bytecodeOffset, unused, unused, unused, opDebugLine, opDebugColumn);
1788 if (line == opDebugLine && (column == Breakpoint::unspecifiedColumn || column == opDebugColumn))
1789 return true;
1790 }
1791 it += opcodeLengths[opcodeID];
1792 }
1793 return false;
1794}
1795
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00001796void CodeBlock::shrinkToFit(ShrinkMode shrinkMode)
weinig@apple.com9d9d25d2008-12-05 20:27:58 +00001797{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00001798 ConcurrentJSLocker locker(m_lock);
sbarati@apple.com4efe2472016-06-21 20:14:00 +00001799
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00001800 m_rareCaseProfiles.shrinkToFit();
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00001801
1802 if (shrinkMode == EarlyShrink) {
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00001803 m_constantRegisters.shrinkToFit();
benjamin@webkit.org54d94f52015-02-28 03:21:37 +00001804 m_constantsSourceCodeRepresentation.shrinkToFit();
oliver@apple.com9b7647b2013-07-25 04:03:00 +00001805
1806 if (m_rareData) {
oliver@apple.coma14cea52013-07-25 04:03:23 +00001807 m_rareData->m_switchJumpTables.shrinkToFit();
oliver@apple.com9b7647b2013-07-25 04:03:00 +00001808 m_rareData->m_stringSwitchJumpTables.shrinkToFit();
1809 }
fpizlo@apple.comdb79da22012-05-16 00:56:54 +00001810 } // else don't shrink these, because we would have already pointed pointers into these tables.
weinig@apple.com9d9d25d2008-12-05 20:27:58 +00001811}
1812
oliver@apple.com1db480d2011-06-28 01:32:01 +00001813#if ENABLE(JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00001814void CodeBlock::linkIncomingCall(ExecState* callerFrame, CallLinkInfo* incoming)
1815{
1816 noticeIncomingCall(callerFrame);
1817 m_incomingCalls.push(incoming);
1818}
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00001819
1820void CodeBlock::linkIncomingPolymorphicCall(ExecState* callerFrame, PolymorphicCallNode* incoming)
1821{
1822 noticeIncomingCall(callerFrame);
1823 m_incomingPolymorphicCalls.push(incoming);
1824}
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00001825#endif // ENABLE(JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00001826
fpizlo@apple.com594887a2011-09-06 09:23:55 +00001827void CodeBlock::unlinkIncomingCalls()
1828{
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00001829 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end())
1830 m_incomingLLIntCalls.begin()->unlink();
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00001831#if ENABLE(JIT)
fpizlo@apple.com594887a2011-09-06 09:23:55 +00001832 while (m_incomingCalls.begin() != m_incomingCalls.end())
fpizlo@apple.com7a797262015-09-03 21:11:59 +00001833 m_incomingCalls.begin()->unlink(*vm());
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00001834 while (m_incomingPolymorphicCalls.begin() != m_incomingPolymorphicCalls.end())
fpizlo@apple.com7a797262015-09-03 21:11:59 +00001835 m_incomingPolymorphicCalls.begin()->unlink(*vm());
commit-queue@webkit.orgea1f9022013-08-29 16:41:07 +00001836#endif // ENABLE(JIT)
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00001837}
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00001838
oliver@apple.comd2cdd312013-07-25 04:01:00 +00001839void CodeBlock::linkIncomingCall(ExecState* callerFrame, LLIntCallLinkInfo* incoming)
1840{
1841 noticeIncomingCall(callerFrame);
1842 m_incomingLLIntCalls.push(incoming);
1843}
commit-queue@webkit.orgf76b9d52012-08-20 23:48:00 +00001844
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001845CodeBlock* CodeBlock::newReplacement()
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00001846{
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001847 return ownerScriptExecutable()->newReplacementCodeBlockFor(specializationKind());
fpizlo@apple.com62b6af82013-08-29 18:25:36 +00001848}
1849
fpizlo@apple.comaf478bb2011-09-06 23:36:51 +00001850#if ENABLE(JIT)
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001851CodeBlock* CodeBlock::replacement()
fpizlo@apple.com594887a2011-09-06 09:23:55 +00001852{
keith_miller@apple.com45da7602017-01-27 01:47:52 +00001853 const ClassInfo* classInfo = this->classInfo(*vm());
fpizlo@apple.com594887a2011-09-06 09:23:55 +00001854
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001855 if (classInfo == FunctionCodeBlock::info())
1856 return jsCast<FunctionExecutable*>(ownerExecutable())->codeBlockFor(m_isConstructor ? CodeForConstruct : CodeForCall);
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00001857
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001858 if (classInfo == EvalCodeBlock::info())
1859 return jsCast<EvalExecutable*>(ownerExecutable())->codeBlock();
fpizlo@apple.com594887a2011-09-06 09:23:55 +00001860
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001861 if (classInfo == ProgramCodeBlock::info())
1862 return jsCast<ProgramExecutable*>(ownerExecutable())->codeBlock();
fpizlo@apple.com594887a2011-09-06 09:23:55 +00001863
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001864 if (classInfo == ModuleProgramCodeBlock::info())
1865 return jsCast<ModuleProgramExecutable*>(ownerExecutable())->codeBlock();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001866
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001867 RELEASE_ASSERT_NOT_REACHED();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001868 return nullptr;
1869}
1870
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001871DFG::CapabilityLevel CodeBlock::computeCapabilityLevel()
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001872{
keith_miller@apple.com45da7602017-01-27 01:47:52 +00001873 const ClassInfo* classInfo = this->classInfo(*vm());
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001874
1875 if (classInfo == FunctionCodeBlock::info()) {
1876 if (m_isConstructor)
1877 return DFG::functionForConstructCapabilityLevel(this);
1878 return DFG::functionForCallCapabilityLevel(this);
1879 }
1880
1881 if (classInfo == EvalCodeBlock::info())
1882 return DFG::evalCapabilityLevel(this);
1883
1884 if (classInfo == ProgramCodeBlock::info())
1885 return DFG::programCapabilityLevel(this);
1886
1887 if (classInfo == ModuleProgramCodeBlock::info())
1888 return DFG::programCapabilityLevel(this);
1889
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001890 RELEASE_ASSERT_NOT_REACHED();
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00001891 return DFG::CannotCompile;
1892}
ggaren@apple.com81def5f2015-10-09 23:10:16 +00001893
1894#endif // ENABLE(JIT)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00001895
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001896void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00001897{
ggaren@apple.com05483852015-09-17 00:28:34 +00001898#if !ENABLE(DFG_JIT)
1899 UNUSED_PARAM(mode);
1900 UNUSED_PARAM(detail);
1901#endif
fpizlo@apple.com4a528d02016-05-11 00:08:50 +00001902
1903 CODEBLOCK_LOG_EVENT(this, "jettison", ("due to ", reason, ", counting = ", mode == CountReoptimization, ", detail = ", pointerDump(detail)));
ggaren@apple.com05483852015-09-17 00:28:34 +00001904
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00001905 RELEASE_ASSERT(reason != Profiler::NotJettisoned);
1906
fpizlo@apple.com580c6f02013-10-30 20:22:40 +00001907#if ENABLE(DFG_JIT)
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00001908 if (DFG::shouldDumpDisassembly()) {
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001909 dataLog("Jettisoning ", *this);
1910 if (mode == CountReoptimization)
1911 dataLog(" and counting reoptimization");
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001912 dataLog(" due to ", reason);
1913 if (detail)
1914 dataLog(", ", *detail);
1915 dataLog(".\n");
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001916 }
1917
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001918 if (reason == Profiler::JettisonDueToWeakReference) {
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00001919 if (DFG::shouldDumpDisassembly()) {
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001920 dataLog(*this, " will be jettisoned because of the following dead references:\n");
1921 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
annulen@yandex.ru23120122016-12-20 18:26:10 +00001922 for (auto& transition : dfgCommon->transitions) {
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001923 JSCell* origin = transition.m_codeOrigin.get();
1924 JSCell* from = transition.m_from.get();
1925 JSCell* to = transition.m_to.get();
1926 if ((!origin || Heap::isMarked(origin)) && Heap::isMarked(from))
1927 continue;
1928 dataLog(" Transition under ", RawPointer(origin), ", ", RawPointer(from), " -> ", RawPointer(to), ".\n");
1929 }
1930 for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i) {
1931 JSCell* weak = dfgCommon->weakReferences[i].get();
1932 if (Heap::isMarked(weak))
1933 continue;
1934 dataLog(" Weak reference ", RawPointer(weak), ".\n");
1935 }
1936 }
1937 }
ggaren@apple.com05483852015-09-17 00:28:34 +00001938#endif // ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001939
mark.lam@apple.come875b7e2018-01-08 22:59:10 +00001940 VM& vm = *m_poisonedVM;
akling@apple.comce2ec582016-01-29 20:37:52 +00001941 DeferGCForAWhile deferGC(*heap());
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00001942
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001943 // We want to accomplish two things here:
1944 // 1) Make sure that if this CodeBlock is on the stack right now, then if we return to it
1945 // we should OSR exit at the top of the next bytecode instruction after the return.
1946 // 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 +00001947
ggaren@apple.com05483852015-09-17 00:28:34 +00001948#if ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001949 if (reason != Profiler::JettisonDueToOldAge) {
mark.lam@apple.com167235e2017-08-10 23:00:06 +00001950 Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get();
1951 if (UNLIKELY(compilation))
ggaren@apple.com05483852015-09-17 00:28:34 +00001952 compilation->setJettisonReason(reason, detail);
1953
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001954 // This accomplishes (1), and does its own book-keeping about whether it has already happened.
1955 if (!jitCode()->dfgCommon()->invalidate()) {
1956 // We've already been invalidated.
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001957 RELEASE_ASSERT(this != replacement() || (vm.heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable())));
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001958 return;
1959 }
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001960 }
1961
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00001962 if (DFG::shouldDumpDisassembly())
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001963 dataLog(" Did invalidate ", *this, "\n");
1964
1965 // Count the reoptimization if that's what the user wanted.
1966 if (mode == CountReoptimization) {
fpizlo@apple.com78e1b2b2013-11-03 00:32:23 +00001967 // FIXME: Maybe this should call alternative().
1968 // https://bugs.webkit.org/show_bug.cgi?id=123677
1969 baselineAlternative()->countReoptimization();
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00001970 if (DFG::shouldDumpDisassembly())
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001971 dataLog(" Did count reoptimization for ", *this, "\n");
1972 }
1973
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001974 if (this != replacement()) {
1975 // This means that we were never the entrypoint. This can happen for OSR entry code
1976 // blocks.
1977 return;
1978 }
ggaren@apple.com05483852015-09-17 00:28:34 +00001979
1980 if (alternative())
1981 alternative()->optimizeAfterWarmUp();
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001982
mark.lam@apple.comf842cd82017-03-09 19:08:46 +00001983 if (reason != Profiler::JettisonDueToOldAge && reason != Profiler::JettisonDueToVMTraps)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001984 tallyFrequentExitSites();
ggaren@apple.com05483852015-09-17 00:28:34 +00001985#endif // ENABLE(DFG_JIT)
ggaren@apple.com111b3fa2015-09-11 16:08:39 +00001986
msaboff@apple.comf2ab7952016-07-09 00:24:25 +00001987 // Jettison can happen during GC. We don't want to install code to a dead executable
1988 // because that would add a dead object to the remembered set.
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001989 if (vm.heap.isCurrentThreadBusy() && !Heap::isMarked(ownerScriptExecutable()))
msaboff@apple.comf2ab7952016-07-09 00:24:25 +00001990 return;
1991
ggaren@apple.com05483852015-09-17 00:28:34 +00001992 // This accomplishes (2).
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00001993 ownerScriptExecutable()->installCode(vm, alternative(), codeType(), specializationKind());
ggaren@apple.com05483852015-09-17 00:28:34 +00001994
1995#if ENABLE(DFG_JIT)
mark.lam@apple.comee3c4102015-10-14 18:57:07 +00001996 if (DFG::shouldDumpDisassembly())
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00001997 dataLog(" Did install baseline version of ", *this, "\n");
fpizlo@apple.com580c6f02013-10-30 20:22:40 +00001998#endif // ENABLE(DFG_JIT)
fpizlo@apple.com706f5f32011-09-21 23:36:35 +00001999}
fpizlo@apple.com594887a2011-09-06 09:23:55 +00002000
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00002001JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin)
2002{
2003 if (!codeOrigin.inlineCallFrame)
2004 return globalObject();
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002005 return codeOrigin.inlineCallFrame->baselineCodeBlock->globalObject();
fpizlo@apple.com5e2296a2013-01-07 02:24:58 +00002006}
2007
msaboff@apple.com4d563e42014-08-16 01:45:40 +00002008class RecursionCheckFunctor {
2009public:
2010 RecursionCheckFunctor(CallFrame* startCallFrame, CodeBlock* codeBlock, unsigned depthToCheck)
2011 : m_startCallFrame(startCallFrame)
2012 , m_codeBlock(codeBlock)
2013 , m_depthToCheck(depthToCheck)
2014 , m_foundStartCallFrame(false)
2015 , m_didRecurse(false)
2016 { }
2017
fpizlo@apple.com39303e02016-04-05 22:17:35 +00002018 StackVisitor::Status operator()(StackVisitor& visitor) const
msaboff@apple.com4d563e42014-08-16 01:45:40 +00002019 {
2020 CallFrame* currentCallFrame = visitor->callFrame();
2021
2022 if (currentCallFrame == m_startCallFrame)
2023 m_foundStartCallFrame = true;
2024
2025 if (m_foundStartCallFrame) {
2026 if (visitor->callFrame()->codeBlock() == m_codeBlock) {
2027 m_didRecurse = true;
2028 return StackVisitor::Done;
2029 }
2030
2031 if (!m_depthToCheck--)
2032 return StackVisitor::Done;
2033 }
2034
2035 return StackVisitor::Continue;
2036 }
2037
2038 bool didRecurse() const { return m_didRecurse; }
2039
2040private:
2041 CallFrame* m_startCallFrame;
2042 CodeBlock* m_codeBlock;
fpizlo@apple.com39303e02016-04-05 22:17:35 +00002043 mutable unsigned m_depthToCheck;
2044 mutable bool m_foundStartCallFrame;
2045 mutable bool m_didRecurse;
msaboff@apple.com4d563e42014-08-16 01:45:40 +00002046};
2047
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002048void CodeBlock::noticeIncomingCall(ExecState* callerFrame)
2049{
2050 CodeBlock* callerCodeBlock = callerFrame->codeBlock();
2051
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00002052 if (Options::verboseCallLink())
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002053 dataLog("Noticing call link from ", pointerDump(callerCodeBlock), " to ", *this, "\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002054
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002055#if ENABLE(DFG_JIT)
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002056 if (!m_shouldAlwaysBeInlined)
2057 return;
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002058
2059 if (!callerCodeBlock) {
2060 m_shouldAlwaysBeInlined = false;
2061 if (Options::verboseCallLink())
2062 dataLog(" Clearing SABI because caller is native.\n");
2063 return;
2064 }
oliver@apple.com58c86752013-07-25 04:02:40 +00002065
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002066 if (!hasBaselineJITProfiling())
2067 return;
oliver@apple.com58c86752013-07-25 04:02:40 +00002068
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002069 if (!DFG::mightInlineFunction(this))
2070 return;
oliver@apple.com58c86752013-07-25 04:02:40 +00002071
akling@apple.comce2ec582016-01-29 20:37:52 +00002072 if (!canInline(capabilityLevelState()))
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002073 return;
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00002074
2075 if (!DFG::isSmallEnoughToInlineCodeInto(callerCodeBlock)) {
2076 m_shouldAlwaysBeInlined = false;
2077 if (Options::verboseCallLink())
2078 dataLog(" Clearing SABI because caller is too large.\n");
2079 return;
2080 }
oliver@apple.com58c86752013-07-25 04:02:40 +00002081
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002082 if (callerCodeBlock->jitType() == JITCode::InterpreterThunk) {
2083 // If the caller is still in the interpreter, then we can't expect inlining to
2084 // happen anytime soon. Assume it's profitable to optimize it separately. This
2085 // ensures that a function is SABI only if it is called no more frequently than
2086 // any of its callers.
2087 m_shouldAlwaysBeInlined = false;
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00002088 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00002089 dataLog(" Clearing SABI because caller is in LLInt.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002090 return;
2091 }
2092
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002093 if (JITCode::isOptimizingJIT(callerCodeBlock->jitType())) {
2094 m_shouldAlwaysBeInlined = false;
2095 if (Options::verboseCallLink())
2096 dataLog(" Clearing SABI bcause caller was already optimized.\n");
2097 return;
2098 }
2099
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002100 if (callerCodeBlock->codeType() != FunctionCode) {
2101 // If the caller is either eval or global code, assume that that won't be
2102 // optimized anytime soon. For eval code this is particularly true since we
2103 // delay eval optimization by a *lot*.
2104 m_shouldAlwaysBeInlined = false;
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00002105 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00002106 dataLog(" Clearing SABI because caller is not a function.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002107 return;
2108 }
msaboff@apple.com4d563e42014-08-16 01:45:40 +00002109
2110 // Recursive calls won't be inlined.
2111 RecursionCheckFunctor functor(callerFrame, this, Options::maximumInliningDepth());
2112 vm()->topCallFrame->iterate(functor);
2113
2114 if (functor.didRecurse()) {
2115 if (Options::verboseCallLink())
2116 dataLog(" Clearing SABI because recursion was detected.\n");
2117 m_shouldAlwaysBeInlined = false;
2118 return;
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002119 }
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002120
akling@apple.comce2ec582016-01-29 20:37:52 +00002121 if (callerCodeBlock->capabilityLevelState() == DFG::CapabilityLevelNotSet) {
jfbastien@apple.comc6594e52017-02-22 01:16:42 +00002122 dataLog("In call from ", FullCodeOrigin(callerCodeBlock, callerFrame->codeOrigin()), " to ", *this, ": caller's DFG capability level is not set.\n");
fpizlo@apple.com8a5fd182015-02-02 18:38:08 +00002123 CRASH();
2124 }
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002125
akling@apple.comce2ec582016-01-29 20:37:52 +00002126 if (canCompile(callerCodeBlock->capabilityLevelState()))
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002127 return;
2128
oliver@apple.comafa7e3a2013-07-25 04:02:04 +00002129 if (Options::verboseCallLink())
fpizlo@apple.comafeb1a92014-02-23 18:48:43 +00002130 dataLog(" Clearing SABI because the caller is not a DFG candidate.\n");
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002131
2132 m_shouldAlwaysBeInlined = false;
oliver@apple.com58c86752013-07-25 04:02:40 +00002133#endif
oliver@apple.comd2cdd312013-07-25 04:01:00 +00002134}
2135
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002136unsigned CodeBlock::reoptimizationRetryCounter() const
2137{
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00002138#if ENABLE(JIT)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002139 ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax());
2140 return m_reoptimizationRetryCounter;
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00002141#else
2142 return 0;
2143#endif // ENABLE(JIT)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002144}
2145
mhahnenberg@apple.comd79127e2014-02-05 01:35:31 +00002146#if ENABLE(JIT)
msaboff@apple.com02085462015-09-10 17:47:16 +00002147void CodeBlock::setCalleeSaveRegisters(RegisterSet calleeSaveRegisters)
2148{
2149 m_calleeSaveRegisters = std::make_unique<RegisterAtOffsetList>(calleeSaveRegisters);
2150}
2151
2152void CodeBlock::setCalleeSaveRegisters(std::unique_ptr<RegisterAtOffsetList> registerAtOffsetList)
2153{
aestes@apple.com13aae082016-01-02 08:03:08 +00002154 m_calleeSaveRegisters = WTFMove(registerAtOffsetList);
msaboff@apple.com02085462015-09-10 17:47:16 +00002155}
2156
2157static size_t roundCalleeSaveSpaceAsVirtualRegisters(size_t calleeSaveRegisters)
2158{
2159 static const unsigned cpuRegisterSize = sizeof(void*);
2160 return (WTF::roundUpToMultipleOf(sizeof(Register), calleeSaveRegisters * cpuRegisterSize) / sizeof(Register));
2161
2162}
2163
2164size_t CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()
2165{
2166 return roundCalleeSaveSpaceAsVirtualRegisters(numberOfLLIntBaselineCalleeSaveRegisters());
2167}
2168
2169size_t CodeBlock::calleeSaveSpaceAsVirtualRegisters()
2170{
2171 return roundCalleeSaveSpaceAsVirtualRegisters(m_calleeSaveRegisters->size());
2172}
2173
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002174void CodeBlock::countReoptimization()
2175{
2176 m_reoptimizationRetryCounter++;
2177 if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax())
2178 m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax();
2179}
2180
oliver@apple.com37172f82013-07-25 04:01:17 +00002181unsigned CodeBlock::numberOfDFGCompiles()
2182{
2183 ASSERT(JITCode::isBaselineCode(jitType()));
msaboff@apple.com95894332014-01-29 19:18:54 +00002184 if (Options::testTheFTL()) {
2185 if (m_didFailFTLCompilation)
2186 return 1000000;
2187 return (m_hasBeenCompiledWithFTL ? 1 : 0) + m_reoptimizationRetryCounter;
2188 }
oliver@apple.com37172f82013-07-25 04:01:17 +00002189 return (JITCode::isOptimizingJIT(replacement()->jitType()) ? 1 : 0) + m_reoptimizationRetryCounter;
2190}
2191
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00002192int32_t CodeBlock::codeTypeThresholdMultiplier() const
2193{
2194 if (codeType() == EvalCode)
2195 return Options::evalThresholdMultiplier();
2196
2197 return 1;
2198}
2199
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002200double CodeBlock::optimizationThresholdScalingFactor()
2201{
cdumez@apple.com36849cc2016-07-17 00:19:41 +00002202 // This expression arises from doing a least-squares fit of
2203 //
2204 // F[x_] =: a * Sqrt[x + b] + Abs[c * x] + d
2205 //
2206 // against the data points:
2207 //
2208 // x F[x_]
2209 // 10 0.9 (smallest reasonable code block)
2210 // 200 1.0 (typical small-ish code block)
2211 // 320 1.2 (something I saw in 3d-cube that I wanted to optimize)
2212 // 1268 5.0 (something I saw in 3d-cube that I didn't want to optimize)
2213 // 4000 5.5 (random large size, used to cause the function to converge to a shallow curve of some sort)
2214 // 10000 6.0 (similar to above)
2215 //
2216 // I achieve the minimization using the following Mathematica code:
2217 //
2218 // MyFunctionTemplate[x_, a_, b_, c_, d_] := a*Sqrt[x + b] + Abs[c*x] + d
2219 //
2220 // samples = {{10, 0.9}, {200, 1}, {320, 1.2}, {1268, 5}, {4000, 5.5}, {10000, 6}}
2221 //
2222 // solution =
2223 // Minimize[Plus @@ ((MyFunctionTemplate[#[[1]], a, b, c, d] - #[[2]])^2 & /@ samples),
2224 // {a, b, c, d}][[2]]
2225 //
2226 // And the code below (to initialize a, b, c, d) is generated by:
2227 //
2228 // Print["const double " <> ToString[#[[1]]] <> " = " <>
2229 // If[#[[2]] < 0.00001, "0.0", ToString[#[[2]]]] <> ";"] & /@ solution
2230 //
2231 // We've long known the following to be true:
2232 // - Small code blocks are cheap to optimize and so we should do it sooner rather
2233 // than later.
2234 // - Large code blocks are expensive to optimize and so we should postpone doing so,
2235 // and sometimes have a large enough threshold that we never optimize them.
2236 // - The difference in cost is not totally linear because (a) just invoking the
2237 // DFG incurs some base cost and (b) for large code blocks there is enough slop
2238 // in the correlation between instruction count and the actual compilation cost
2239 // that for those large blocks, the instruction count should not have a strong
2240 // influence on our threshold.
2241 //
2242 // I knew the goals but I didn't know how to achieve them; so I picked an interesting
2243 // example where the heuristics were right (code block in 3d-cube with instruction
2244 // count 320, which got compiled early as it should have been) and one where they were
2245 // totally wrong (code block in 3d-cube with instruction count 1268, which was expensive
2246 // to compile and didn't run often enough to warrant compilation in my opinion), and
2247 // then threw in additional data points that represented my own guess of what our
2248 // heuristics should do for some round-numbered examples.
2249 //
2250 // The expression to which I decided to fit the data arose because I started with an
2251 // affine function, and then did two things: put the linear part in an Abs to ensure
2252 // that the fit didn't end up choosing a negative value of c (which would result in
2253 // the function turning over and going negative for large x) and I threw in a Sqrt
2254 // term because Sqrt represents my intution that the function should be more sensitive
2255 // to small changes in small values of x, but less sensitive when x gets large.
2256
2257 // Note that the current fit essentially eliminates the linear portion of the
2258 // expression (c == 0.0).
2259 const double a = 0.061504;
2260 const double b = 1.02406;
2261 const double c = 0.0;
2262 const double d = 0.825914;
2263
ggaren@apple.comf0193982013-04-03 01:41:16 +00002264 double instructionCount = this->instructionCount();
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002265
ggaren@apple.comf0193982013-04-03 01:41:16 +00002266 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 +00002267
ggaren@apple.comf0193982013-04-03 01:41:16 +00002268 double result = d + a * sqrt(instructionCount + b) + c * instructionCount;
fpizlo@apple.com3ce93232014-03-03 05:42:29 +00002269
2270 result *= codeTypeThresholdMultiplier();
2271
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002272 if (Options::verboseOSR()) {
2273 dataLog(
2274 *this, ": instruction count is ", instructionCount,
2275 ", scaling execution counter by ", result, " * ", codeTypeThresholdMultiplier(),
2276 "\n");
2277 }
fpizlo@apple.com3ce93232014-03-03 05:42:29 +00002278 return result;
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002279}
2280
2281static int32_t clipThreshold(double threshold)
2282{
2283 if (threshold < 1.0)
2284 return 1;
2285
2286 if (threshold > static_cast<double>(std::numeric_limits<int32_t>::max()))
2287 return std::numeric_limits<int32_t>::max();
2288
2289 return static_cast<int32_t>(threshold);
2290}
2291
fpizlo@apple.come5b68642013-08-29 20:27:15 +00002292int32_t CodeBlock::adjustedCounterValue(int32_t desiredThreshold)
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002293{
2294 return clipThreshold(
fpizlo@apple.come5b68642013-08-29 20:27:15 +00002295 static_cast<double>(desiredThreshold) *
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002296 optimizationThresholdScalingFactor() *
2297 (1 << reoptimizationRetryCounter()));
2298}
2299
2300bool CodeBlock::checkIfOptimizationThresholdReached()
2301{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002302#if ENABLE(DFG_JIT)
msaboff@apple.com95894332014-01-29 19:18:54 +00002303 if (DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull()) {
fpizlo@apple.com6931c472013-08-29 23:45:26 +00002304 if (worklist->compilationState(DFG::CompilationKey(this, DFG::DFGMode))
2305 == DFG::Worklist::Compiled) {
2306 optimizeNextInvocation();
2307 return true;
2308 }
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002309 }
2310#endif
2311
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002312 return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this);
2313}
2314
guijemont@igalia.comc178f162017-10-10 23:14:12 +00002315#if ENABLE(DFG_JIT)
mark.lam@apple.com75882892017-10-04 20:00:01 +00002316auto CodeBlock::updateOSRExitCounterAndCheckIfNeedToReoptimize(DFG::OSRExitState& exitState) -> OptimizeAction
2317{
2318 DFG::OSRExitBase& exit = exitState.exit;
2319 if (!exitKindMayJettison(exit.m_kind)) {
2320 // FIXME: We may want to notice that we're frequently exiting
2321 // at an op_catch that we didn't compile an entrypoint for, and
2322 // then trigger a reoptimization of this CodeBlock:
2323 // https://bugs.webkit.org/show_bug.cgi?id=175842
2324 return OptimizeAction::None;
2325 }
2326
2327 exit.m_count++;
2328 m_osrExitCounter++;
2329
2330 CodeBlock* baselineCodeBlock = exitState.baselineCodeBlock;
2331 ASSERT(baselineCodeBlock == baselineAlternative());
2332 if (UNLIKELY(baselineCodeBlock->jitExecuteCounter().hasCrossedThreshold()))
2333 return OptimizeAction::ReoptimizeNow;
2334
2335 // We want to figure out if there's a possibility that we're in a loop. For the outermost
2336 // code block in the inline stack, we handle this appropriately by having the loop OSR trigger
2337 // check the exit count of the replacement of the CodeBlock from which we are OSRing. The
2338 // problem is the inlined functions, which might also have loops, but whose baseline versions
2339 // don't know where to look for the exit count. Figure out if those loops are severe enough
2340 // that we had tried to OSR enter. If so, then we should use the loop reoptimization trigger.
2341 // Otherwise, we should use the normal reoptimization trigger.
2342
2343 bool didTryToEnterInLoop = false;
2344 for (InlineCallFrame* inlineCallFrame = exit.m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2345 if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2346 didTryToEnterInLoop = true;
2347 break;
2348 }
2349 }
2350
2351 uint32_t exitCountThreshold = didTryToEnterInLoop
2352 ? exitCountThresholdForReoptimizationFromLoop()
2353 : exitCountThresholdForReoptimization();
2354
2355 if (m_osrExitCounter > exitCountThreshold)
2356 return OptimizeAction::ReoptimizeNow;
2357
2358 // Too few fails. Adjust the execution counter such that the target is to only optimize after a while.
2359 baselineCodeBlock->m_jitExecuteCounter.setNewThresholdForOSRExit(exitState.activeThreshold, exitState.memoryUsageAdjustedThreshold);
2360 return OptimizeAction::None;
2361}
guijemont@igalia.comc178f162017-10-10 23:14:12 +00002362#endif
mark.lam@apple.com75882892017-10-04 20:00:01 +00002363
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002364void CodeBlock::optimizeNextInvocation()
2365{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002366 if (Options::verboseOSR())
2367 dataLog(*this, ": Optimizing next invocation.\n");
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002368 m_jitExecuteCounter.setNewThreshold(0, this);
2369}
2370
2371void CodeBlock::dontOptimizeAnytimeSoon()
2372{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002373 if (Options::verboseOSR())
2374 dataLog(*this, ": Not optimizing anytime soon.\n");
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002375 m_jitExecuteCounter.deferIndefinitely();
2376}
2377
2378void CodeBlock::optimizeAfterWarmUp()
2379{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002380 if (Options::verboseOSR())
2381 dataLog(*this, ": Optimizing after warm-up.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00002382#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00002383 m_jitExecuteCounter.setNewThreshold(
2384 adjustedCounterValue(Options::thresholdForOptimizeAfterWarmUp()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00002385#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002386}
2387
2388void CodeBlock::optimizeAfterLongWarmUp()
2389{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002390 if (Options::verboseOSR())
2391 dataLog(*this, ": Optimizing after long warm-up.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00002392#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00002393 m_jitExecuteCounter.setNewThreshold(
2394 adjustedCounterValue(Options::thresholdForOptimizeAfterLongWarmUp()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00002395#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002396}
2397
2398void CodeBlock::optimizeSoon()
2399{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002400 if (Options::verboseOSR())
2401 dataLog(*this, ": Optimizing soon.\n");
oliver@apple.com58c86752013-07-25 04:02:40 +00002402#if ENABLE(DFG_JIT)
fpizlo@apple.come5b68642013-08-29 20:27:15 +00002403 m_jitExecuteCounter.setNewThreshold(
2404 adjustedCounterValue(Options::thresholdForOptimizeSoon()), this);
oliver@apple.com58c86752013-07-25 04:02:40 +00002405#endif
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002406}
2407
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002408void CodeBlock::forceOptimizationSlowPathConcurrently()
2409{
2410 if (Options::verboseOSR())
2411 dataLog(*this, ": Forcing slow path concurrently.\n");
2412 m_jitExecuteCounter.forceSlowPathConcurrently();
2413}
2414
oliver@apple.com58c86752013-07-25 04:02:40 +00002415#if ENABLE(DFG_JIT)
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002416void CodeBlock::setOptimizationThresholdBasedOnCompilationResult(CompilationResult result)
2417{
fpizlo@apple.come7a417d2014-05-08 21:51:03 +00002418 JITCode::JITType type = jitType();
2419 if (type != JITCode::BaselineJIT) {
2420 dataLog(*this, ": expected to have baseline code but have ", type, "\n");
2421 RELEASE_ASSERT_NOT_REACHED();
2422 }
2423
2424 CodeBlock* theReplacement = replacement();
2425 if ((result == CompilationSuccessful) != (theReplacement != this)) {
2426 dataLog(*this, ": we have result = ", result, " but ");
2427 if (theReplacement == this)
2428 dataLog("we are our own replacement.\n");
2429 else
2430 dataLog("our replacement is ", pointerDump(theReplacement), "\n");
2431 RELEASE_ASSERT_NOT_REACHED();
2432 }
2433
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002434 switch (result) {
2435 case CompilationSuccessful:
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00002436 RELEASE_ASSERT(JITCode::isOptimizingJIT(replacement()->jitType()));
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002437 optimizeNextInvocation();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002438 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002439 case CompilationFailed:
2440 dontOptimizeAnytimeSoon();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002441 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002442 case CompilationDeferred:
2443 // We'd like to do dontOptimizeAnytimeSoon() but we cannot because
2444 // forceOptimizationSlowPathConcurrently() is inherently racy. It won't
2445 // necessarily guarantee anything. So, we make sure that even if that
2446 // function ends up being a no-op, we still eventually retry and realize
2447 // that we have optimized code ready.
2448 optimizeAfterWarmUp();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002449 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002450 case CompilationInvalidated:
2451 // Retry with exponential backoff.
2452 countReoptimization();
2453 optimizeAfterWarmUp();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002454 return;
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002455 }
fpizlo@apple.come7a417d2014-05-08 21:51:03 +00002456
2457 dataLog("Unrecognized result: ", static_cast<int>(result), "\n");
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00002458 RELEASE_ASSERT_NOT_REACHED();
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002459}
2460
oliver@apple.com807e7e12013-07-25 20:22:45 +00002461#endif
2462
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002463uint32_t CodeBlock::adjustedExitCountThreshold(uint32_t desiredThreshold)
2464{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00002465 ASSERT(JITCode::isOptimizingJIT(jitType()));
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002466 // Compute this the lame way so we don't saturate. This is called infrequently
2467 // enough that this loop won't hurt us.
2468 unsigned result = desiredThreshold;
2469 for (unsigned n = baselineVersion()->reoptimizationRetryCounter(); n--;) {
2470 unsigned newResult = result << 1;
2471 if (newResult < result)
2472 return std::numeric_limits<uint32_t>::max();
2473 result = newResult;
2474 }
2475 return result;
2476}
2477
2478uint32_t CodeBlock::exitCountThresholdForReoptimization()
2479{
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00002480 return adjustedExitCountThreshold(Options::osrExitCountForReoptimization() * codeTypeThresholdMultiplier());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002481}
2482
2483uint32_t CodeBlock::exitCountThresholdForReoptimizationFromLoop()
2484{
fpizlo@apple.comd29f9632012-12-18 22:49:40 +00002485 return adjustedExitCountThreshold(Options::osrExitCountForReoptimizationFromLoop() * codeTypeThresholdMultiplier());
fpizlo@apple.com7f7ba492012-12-09 20:41:09 +00002486}
2487
2488bool CodeBlock::shouldReoptimizeNow()
2489{
2490 return osrExitCounter() >= exitCountThresholdForReoptimization();
2491}
2492
2493bool CodeBlock::shouldReoptimizeFromLoopNow()
2494{
2495 return osrExitCounter() >= exitCountThresholdForReoptimizationFromLoop();
2496}
2497#endif
2498
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002499ArrayProfile* CodeBlock::getArrayProfile(const ConcurrentJSLocker&, unsigned bytecodeOffset)
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00002500{
annulen@yandex.ru23120122016-12-20 18:26:10 +00002501 for (auto& m_arrayProfile : m_arrayProfiles) {
2502 if (m_arrayProfile.bytecodeOffset() == bytecodeOffset)
2503 return &m_arrayProfile;
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00002504 }
2505 return 0;
2506}
2507
fpizlo@apple.com46050f72016-06-17 04:48:47 +00002508ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset)
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00002509{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002510 ConcurrentJSLocker locker(m_lock);
fpizlo@apple.com46050f72016-06-17 04:48:47 +00002511 return getArrayProfile(locker, bytecodeOffset);
2512}
2513
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002514ArrayProfile* CodeBlock::addArrayProfile(const ConcurrentJSLocker&, unsigned bytecodeOffset)
fpizlo@apple.com46050f72016-06-17 04:48:47 +00002515{
2516 m_arrayProfiles.append(ArrayProfile(bytecodeOffset));
2517 return &m_arrayProfiles.last();
2518}
2519
2520ArrayProfile* CodeBlock::addArrayProfile(unsigned bytecodeOffset)
2521{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002522 ConcurrentJSLocker locker(m_lock);
fpizlo@apple.com46050f72016-06-17 04:48:47 +00002523 return addArrayProfile(locker, bytecodeOffset);
2524}
2525
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002526ArrayProfile* CodeBlock::getOrAddArrayProfile(const ConcurrentJSLocker& locker, unsigned bytecodeOffset)
fpizlo@apple.com46050f72016-06-17 04:48:47 +00002527{
2528 ArrayProfile* result = getArrayProfile(locker, bytecodeOffset);
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00002529 if (result)
2530 return result;
fpizlo@apple.com46050f72016-06-17 04:48:47 +00002531 return addArrayProfile(locker, bytecodeOffset);
2532}
2533
2534ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset)
2535{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002536 ConcurrentJSLocker locker(m_lock);
fpizlo@apple.com46050f72016-06-17 04:48:47 +00002537 return getOrAddArrayProfile(locker, bytecodeOffset);
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00002538}
2539
fpizlo@apple.com8e470a22015-09-21 20:10:04 +00002540#if ENABLE(DFG_JIT)
2541Vector<CodeOrigin, 0, UnsafeVectorOverflow>& CodeBlock::codeOrigins()
2542{
2543 return m_jitCode->dfgCommon()->codeOrigins;
2544}
2545
2546size_t CodeBlock::numberOfDFGIdentifiers() const
2547{
2548 if (!JITCode::isOptimizingJIT(jitType()))
2549 return 0;
2550
2551 return m_jitCode->dfgCommon()->dfgIdentifiers.size();
2552}
2553
2554const Identifier& CodeBlock::identifier(int index) const
2555{
2556 size_t unlinkedIdentifiers = m_unlinkedCode->numberOfIdentifiers();
2557 if (static_cast<unsigned>(index) < unlinkedIdentifiers)
2558 return m_unlinkedCode->identifier(index);
2559 ASSERT(JITCode::isOptimizingJIT(jitType()));
2560 return m_jitCode->dfgCommon()->dfgIdentifiers[index - unlinkedIdentifiers];
2561}
2562#endif // ENABLE(DFG_JIT)
2563
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002564void CodeBlock::updateAllPredictionsAndCountLiveness(unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002565{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002566 ConcurrentJSLocker locker(m_lock);
sbarati@apple.com60a3be72017-08-25 18:26:15 +00002567
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002568 numberOfLiveNonArgumentValueProfiles = 0;
2569 numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full.
sbarati@apple.com60a3be72017-08-25 18:26:15 +00002570
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002571 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002572 ValueProfile& profile = getFromAllValueProfiles(i);
2573 unsigned numSamples = profile.totalNumberOfSamples();
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002574 if (numSamples > ValueProfile::numberOfBuckets)
2575 numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight.
2576 numberOfSamplesInProfiles += numSamples;
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002577 if (profile.m_bytecodeOffset < 0) {
2578 profile.computeUpdatedPrediction(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002579 continue;
2580 }
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002581 if (profile.numberOfSamples() || profile.m_prediction != SpecNone)
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002582 numberOfLiveNonArgumentValueProfiles++;
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002583 profile.computeUpdatedPrediction(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002584 }
sbarati@apple.com60a3be72017-08-25 18:26:15 +00002585
2586 for (auto& profileBucket : m_catchProfiles) {
2587 profileBucket->forEach([&] (ValueProfileAndOperand& profile) {
2588 profile.m_profile.computeUpdatedPrediction(locker);
2589 });
2590 }
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002591
2592#if ENABLE(DFG_JIT)
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002593 m_lazyOperandValueProfiles.computeUpdatedPredictions(locker);
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002594#endif
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002595}
2596
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002597void CodeBlock::updateAllValueProfilePredictions()
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002598{
2599 unsigned ignoredValue1, ignoredValue2;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002600 updateAllPredictionsAndCountLiveness(ignoredValue1, ignoredValue2);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002601}
2602
oliver@apple.com58cdc332013-07-25 04:04:59 +00002603void CodeBlock::updateAllArrayPredictions()
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002604{
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002605 ConcurrentJSLocker locker(m_lock);
oliver@apple.comc14eb7d2013-07-25 03:58:47 +00002606
fpizlo@apple.comf24804c2012-08-15 02:48:35 +00002607 for (unsigned i = m_arrayProfiles.size(); i--;)
oliver@apple.com58cdc332013-07-25 04:04:59 +00002608 m_arrayProfiles[i].computeUpdatedPrediction(locker, this);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002609
2610 // Don't count these either, for similar reasons.
2611 for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
utatane.tea@gmail.comb9355b52017-09-22 12:19:54 +00002612 m_arrayAllocationProfiles[i].updateProfile();
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002613}
2614
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002615void CodeBlock::updateAllPredictions()
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002616{
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002617 updateAllValueProfilePredictions();
oliver@apple.com58cdc332013-07-25 04:04:59 +00002618 updateAllArrayPredictions();
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002619}
2620
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002621bool CodeBlock::shouldOptimizeNow()
2622{
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002623 if (Options::verboseOSR())
2624 dataLog("Considering optimizing ", *this, "...\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002625
commit-queue@webkit.orgfbda60c2012-07-03 19:19:22 +00002626 if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay())
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002627 return true;
2628
fpizlo@apple.com75c91a72012-11-08 22:28:25 +00002629 updateAllArrayPredictions();
2630
fpizlo@apple.com3745dbc2012-06-26 02:14:07 +00002631 unsigned numberOfLiveNonArgumentValueProfiles;
2632 unsigned numberOfSamplesInProfiles;
mhahnenberg@apple.comc5684712013-09-26 17:16:47 +00002633 updateAllPredictionsAndCountLiveness(numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002634
oliver@apple.com284cc3d2013-07-25 04:00:33 +00002635 if (Options::verboseOSR()) {
2636 dataLogF(
2637 "Profile hotness: %lf (%u / %u), %lf (%u / %u)\n",
2638 (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(),
2639 numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(),
2640 (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(),
2641 numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles());
2642 }
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002643
commit-queue@webkit.orgfbda60c2012-07-03 19:19:22 +00002644 if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate())
2645 && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate())
2646 && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay())
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002647 return true;
2648
fpizlo@apple.com4043e812011-11-06 11:54:59 +00002649 ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max());
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002650 m_optimizationDelayCounter++;
2651 optimizeAfterWarmUp();
2652 return false;
2653}
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002654
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00002655#if ENABLE(DFG_JIT)
2656void CodeBlock::tallyFrequentExitSites()
2657{
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00002658 ASSERT(JITCode::isOptimizingJIT(jitType()));
2659 ASSERT(alternative()->jitType() == JITCode::BaselineJIT);
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00002660
2661 CodeBlock* profiledBlock = alternative();
2662
oliver@apple.com5a24fdd2013-07-25 04:00:54 +00002663 switch (jitType()) {
oliver@apple.comea771492013-07-25 03:58:38 +00002664 case JITCode::DFGJIT: {
2665 DFG::JITCode* jitCode = m_jitCode->dfg();
annulen@yandex.ru23120122016-12-20 18:26:10 +00002666 for (auto& exit : jitCode->osrExit)
benjamin@webkit.org6f63a8b2015-02-18 07:04:10 +00002667 exit.considerAddingAsFrequentExitSite(profiledBlock);
oliver@apple.comea771492013-07-25 03:58:38 +00002668 break;
2669 }
oliver@apple.com0c1b13e2013-07-25 03:58:43 +00002670
2671#if ENABLE(FTL_JIT)
oliver@apple.comea771492013-07-25 03:58:38 +00002672 case JITCode::FTLJIT: {
2673 // There is no easy way to avoid duplicating this code since the FTL::JITCode::osrExit
2674 // vector contains a totally different type, that just so happens to behave like
2675 // DFG::JITCode::osrExit.
oliver@apple.comea771492013-07-25 03:58:38 +00002676 FTL::JITCode* jitCode = m_jitCode->ftl();
2677 for (unsigned i = 0; i < jitCode->osrExit.size(); ++i) {
2678 FTL::OSRExit& exit = jitCode->osrExit[i];
benjamin@webkit.org6f63a8b2015-02-18 07:04:10 +00002679 exit.considerAddingAsFrequentExitSite(profiledBlock);
oliver@apple.comea771492013-07-25 03:58:38 +00002680 }
oliver@apple.comea771492013-07-25 03:58:38 +00002681 break;
oliver@apple.com0c1b13e2013-07-25 03:58:43 +00002682 }
2683#endif
oliver@apple.comea771492013-07-25 03:58:38 +00002684
2685 default:
2686 RELEASE_ASSERT_NOT_REACHED();
2687 break;
fpizlo@apple.com4ef9c872011-12-13 19:49:49 +00002688 }
2689}
2690#endif // ENABLE(DFG_JIT)
2691
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002692#if ENABLE(VERBOSE_VALUE_PROFILE)
2693void CodeBlock::dumpValueProfiles()
2694{
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00002695 dataLog("ValueProfile for ", *this, ":\n");
fpizlo@apple.com086d2af2011-12-21 02:29:15 +00002696 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) {
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002697 ValueProfile& profile = getFromAllValueProfiles(i);
2698 if (profile.m_bytecodeOffset < 0) {
2699 ASSERT(profile.m_bytecodeOffset == -1);
fpizlo@apple.com01902c82012-11-22 04:23:36 +00002700 dataLogF(" arg = %u: ", i);
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002701 } else
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002702 dataLogF(" bc = %d: ", profile.m_bytecodeOffset);
2703 if (!profile.numberOfSamples() && profile.m_prediction == SpecNone) {
fpizlo@apple.com01902c82012-11-22 04:23:36 +00002704 dataLogF("<empty>\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002705 continue;
2706 }
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002707 profile.dump(WTF::dataFile());
fpizlo@apple.com01902c82012-11-22 04:23:36 +00002708 dataLogF("\n");
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002709 }
fpizlo@apple.com0bfcc382012-11-30 03:42:29 +00002710 dataLog("RareCaseProfile for ", *this, ":\n");
barraclough@apple.come32d4ec2011-09-21 22:43:11 +00002711 for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) {
2712 RareCaseProfile* profile = rareCaseProfile(i);
fpizlo@apple.com01902c82012-11-22 04:23:36 +00002713 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter);
fpizlo@apple.com9b0b31e2011-09-19 22:27:38 +00002714 }
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002715}
fpizlo@apple.com8618e4b2012-07-03 01:27:16 +00002716#endif // ENABLE(VERBOSE_VALUE_PROFILE)
fpizlo@apple.com7f2d2342011-09-14 23:00:26 +00002717
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00002718unsigned CodeBlock::frameRegisterCount()
2719{
2720 switch (jitType()) {
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00002721 case JITCode::InterpreterThunk:
2722 return LLInt::frameRegisterCountFor(this);
fpizlo@apple.com81bb8bb2013-11-23 00:36:55 +00002723
2724#if ENABLE(JIT)
2725 case JITCode::BaselineJIT:
2726 return JIT::frameRegisterCountFor(this);
2727#endif // ENABLE(JIT)
2728
2729#if ENABLE(DFG_JIT)
2730 case JITCode::DFGJIT:
2731 case JITCode::FTLJIT:
2732 return jitCode()->dfgCommon()->frameRegisterCount;
2733#endif // ENABLE(DFG_JIT)
2734
2735 default:
2736 RELEASE_ASSERT_NOT_REACHED();
2737 return 0;
2738 }
2739}
2740
msaboff@apple.com95894332014-01-29 19:18:54 +00002741int CodeBlock::stackPointerOffset()
2742{
2743 return virtualRegisterForLocal(frameRegisterCount() - 1).offset();
2744}
2745
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00002746size_t CodeBlock::predictedMachineCodeSize()
2747{
mark.lam@apple.come875b7e2018-01-08 22:59:10 +00002748 VM* vm = m_poisonedVM.unpoisoned();
2749 // This will be called from CodeBlock::CodeBlock before either m_poisonedVM or the
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00002750 // instructions have been initialized. It's OK to return 0 because what will really
2751 // matter is the recomputation of this value when the slow path is triggered.
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00002752 if (!vm)
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00002753 return 0;
2754
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00002755 if (!*vm->machineCodeBytesPerBytecodeWordForBaselineJIT)
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00002756 return 0; // It's as good of a prediction as we'll get.
2757
2758 // Be conservative: return a size that will be an overestimation 84% of the time.
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00002759 double multiplier = vm->machineCodeBytesPerBytecodeWordForBaselineJIT->mean() +
2760 vm->machineCodeBytesPerBytecodeWordForBaselineJIT->standardDeviation();
fpizlo@apple.com254d43b2012-03-05 06:52:44 +00002761
2762 // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing
2763 // here is OK, since this whole method is just a heuristic.
2764 if (multiplier < 0 || multiplier > 1000)
2765 return 0;
2766
2767 double doubleResult = multiplier * m_instructions.size();
2768
2769 // Be even more paranoid: silently reject values that won't fit into a size_t. If
2770 // the function is so huge that we can't even fit it into virtual memory then we
2771 // should probably have some other guards in place to prevent us from even getting
2772 // to this point.
2773 if (doubleResult > std::numeric_limits<size_t>::max())
2774 return 0;
2775
2776 return static_cast<size_t>(doubleResult);
2777}
2778
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00002779String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
oliver@apple.coma08210b2012-07-18 23:26:06 +00002780{
annulen@yandex.ru23120122016-12-20 18:26:10 +00002781 for (auto& constantRegister : m_constantRegisters) {
2782 if (constantRegister.get().isEmpty())
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00002783 continue;
keith_miller@apple.com45da7602017-01-27 01:47:52 +00002784 if (SymbolTable* symbolTable = jsDynamicCast<SymbolTable*>(*vm(), constantRegister.get())) {
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00002785 ConcurrentJSLocker locker(symbolTable->m_lock);
saambarati1@gmail.com3321f092015-07-20 21:16:41 +00002786 auto end = symbolTable->end(locker);
2787 for (auto ptr = symbolTable->begin(locker); ptr != end; ++ptr) {
2788 if (ptr->value.varOffset() == VarOffset(virtualRegister)) {
2789 // FIXME: This won't work from the compilation thread.
2790 // https://bugs.webkit.org/show_bug.cgi?id=115300
2791 return ptr->key.get();
2792 }
2793 }
oliver@apple.comf72e22e2013-07-25 03:59:04 +00002794 }
oliver@apple.coma08210b2012-07-18 23:26:06 +00002795 }
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00002796 if (virtualRegister == thisRegister())
utatane.tea@gmail.com84077632018-06-23 08:39:34 +00002797 return "this"_s;
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00002798 if (virtualRegister.isArgument())
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002799 return String::format("arguments[%3d]", virtualRegister.toArgument());
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00002800
oliver@apple.coma08210b2012-07-18 23:26:06 +00002801 return "";
2802}
2803
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002804ValueProfile* CodeBlock::tryGetValueProfileForBytecodeOffset(int bytecodeOffset)
2805{
2806 return tryBinarySearch<ValueProfile, int>(
2807 m_valueProfiles, m_valueProfiles.size(), bytecodeOffset,
2808 getValueProfileBytecodeOffset<ValueProfile>);
2809}
2810
2811ValueProfile& CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset)
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00002812{
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00002813 OpcodeID opcodeID = Interpreter::getOpcodeID(instructions()[bytecodeOffset]);
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +00002814 unsigned length = opcodeLength(opcodeID);
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002815 ASSERT(!!tryGetValueProfileForBytecodeOffset(bytecodeOffset));
2816 return *instructions()[bytecodeOffset + length - 1].u.profile;
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00002817}
2818
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00002819void CodeBlock::validate()
2820{
2821 BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
2822
sbarati@apple.com34906fa2017-10-28 01:03:22 +00002823 FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(this, 0);
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00002824
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002825 if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeLocals)) {
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00002826 beginValidationDidFail();
2827 dataLog(" Wrong number of bits in result!\n");
2828 dataLog(" Result: ", liveAtHead, "\n");
2829 dataLog(" Bit count: ", liveAtHead.numBits(), "\n");
2830 endValidationDidFail();
2831 }
2832
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002833 for (unsigned i = m_numCalleeLocals; i--;) {
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00002834 VirtualRegister reg = virtualRegisterForLocal(i);
2835
fpizlo@apple.com4fe6b582016-09-12 04:03:36 +00002836 if (liveAtHead[i]) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002837 beginValidationDidFail();
2838 dataLog(" Variable ", reg, " is expected to be dead.\n");
2839 dataLog(" Result: ", liveAtHead, "\n");
2840 endValidationDidFail();
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00002841 }
2842 }
sbarati@apple.com8f3dc39c2017-08-22 16:28:13 +00002843
2844 for (unsigned i = 0; i + 1 < numberOfValueProfiles(); ++i) {
2845 if (valueProfile(i).m_bytecodeOffset > valueProfile(i + 1).m_bytecodeOffset) {
2846 beginValidationDidFail();
2847 dataLog(" Value profiles are not sorted.\n");
2848 endValidationDidFail();
2849 }
2850 }
sbarati@apple.com60a3be72017-08-25 18:26:15 +00002851
2852 for (unsigned bytecodeOffset = 0; bytecodeOffset < m_instructions.size(); ) {
2853 OpcodeID opcode = Interpreter::getOpcodeID(m_instructions[bytecodeOffset]);
2854 if (!!baselineAlternative()->handlerForBytecodeOffset(bytecodeOffset)) {
2855 if (opcode == op_catch || opcode == op_enter) {
2856 // op_catch/op_enter logically represent an entrypoint. Entrypoints are not allowed to be
2857 // inside of a try block because they are responsible for bootstrapping state. And they
2858 // are never allowed throw an exception because of this. We rely on this when compiling
2859 // in the DFG. Because an entrypoint never throws, the bytecode generator will never
2860 // allow once inside a try block.
2861 beginValidationDidFail();
2862 dataLog(" entrypoint not allowed inside a try block.");
2863 endValidationDidFail();
2864 }
2865 }
2866 bytecodeOffset += opcodeLength(opcode);
2867 }
fpizlo@apple.com2eb67ec2013-11-27 23:15:48 +00002868}
2869
2870void CodeBlock::beginValidationDidFail()
2871{
2872 dataLog("Validation failure in ", *this, ":\n");
2873 dataLog("\n");
2874}
2875
2876void CodeBlock::endValidationDidFail()
2877{
2878 dataLog("\n");
2879 dumpBytecode();
2880 dataLog("\n");
2881 dataLog("Validation failure.\n");
2882 RELEASE_ASSERT_NOT_REACHED();
2883}
2884
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00002885void CodeBlock::addBreakpoint(unsigned numBreakpoints)
2886{
2887 m_numBreakpoints += numBreakpoints;
2888 ASSERT(m_numBreakpoints);
mark.lam@apple.com51ccaab2014-02-01 20:29:23 +00002889 if (JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00002890 jettison(Profiler::JettisonDueToDebuggerBreakpoint);
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00002891}
2892
2893void CodeBlock::setSteppingMode(CodeBlock::SteppingMode mode)
2894{
2895 m_steppingMode = mode;
mark.lam@apple.com51ccaab2014-02-01 20:29:23 +00002896 if (mode == SteppingModeEnabled && JITCode::isOptimizingJIT(jitType()))
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00002897 jettison(Profiler::JettisonDueToDebuggerStepping);
mark.lam@apple.com6c4085b2014-01-28 17:43:07 +00002898}
2899
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00002900RareCaseProfile* CodeBlock::addRareCaseProfile(int bytecodeOffset)
2901{
2902 m_rareCaseProfiles.append(RareCaseProfile(bytecodeOffset));
2903 return &m_rareCaseProfiles.last();
2904}
2905
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00002906RareCaseProfile* CodeBlock::rareCaseProfileForBytecodeOffset(int bytecodeOffset)
2907{
2908 return tryBinarySearch<RareCaseProfile, int>(
2909 m_rareCaseProfiles, m_rareCaseProfiles.size(), bytecodeOffset,
2910 getRareCaseProfileBytecodeOffset);
2911}
2912
mark.lam@apple.comff2c14a2015-09-24 18:38:35 +00002913unsigned CodeBlock::rareCaseProfileCountForBytecodeOffset(int bytecodeOffset)
2914{
2915 RareCaseProfile* profile = rareCaseProfileForBytecodeOffset(bytecodeOffset);
2916 if (profile)
2917 return profile->m_counter;
2918 return 0;
2919}
2920
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00002921ArithProfile* CodeBlock::arithProfileForBytecodeOffset(int bytecodeOffset)
sbarati@apple.com900f8912016-04-12 18:38:16 +00002922{
mark.lam@apple.comd5b8e182018-03-21 18:23:30 +00002923 return arithProfileForPC(&instructions()[bytecodeOffset]);
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00002924}
2925
2926ArithProfile* CodeBlock::arithProfileForPC(Instruction* pc)
2927{
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00002928 auto opcodeID = Interpreter::getOpcodeID(pc[0]);
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00002929 switch (opcodeID) {
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00002930 case op_negate:
2931 return bitwise_cast<ArithProfile*>(&pc[3].u.operand);
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00002932 case op_bitor:
2933 case op_bitand:
2934 case op_bitxor:
2935 case op_add:
2936 case op_mul:
2937 case op_sub:
2938 case op_div:
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00002939 return bitwise_cast<ArithProfile*>(&pc[4].u.operand);
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00002940 default:
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00002941 break;
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00002942 }
2943
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00002944 return nullptr;
fpizlo@apple.com53af09c2016-06-23 20:55:41 +00002945}
2946
2947bool CodeBlock::couldTakeSpecialFastCase(int bytecodeOffset)
2948{
2949 if (!hasBaselineJITProfiling())
2950 return false;
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00002951 ArithProfile* profile = arithProfileForBytecodeOffset(bytecodeOffset);
2952 if (!profile)
2953 return false;
2954 return profile->tookSpecialFastPath();
sbarati@apple.com900f8912016-04-12 18:38:16 +00002955}
2956
mhahnenberg@apple.com0ef30c42014-05-02 21:21:04 +00002957#if ENABLE(JIT)
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00002958DFG::CapabilityLevel CodeBlock::capabilityLevel()
2959{
ggaren@apple.com81def5f2015-10-09 23:10:16 +00002960 DFG::CapabilityLevel result = computeCapabilityLevel();
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00002961 m_capabilityLevelState = result;
2962 return result;
2963}
mhahnenberg@apple.com0ef30c42014-05-02 21:21:04 +00002964#endif
mhahnenberg@apple.com1f265072014-05-02 18:52:10 +00002965
akling@apple.comf10f7a12015-10-10 21:14:56 +00002966void CodeBlock::insertBasicBlockBoundariesForControlFlowProfiler(RefCountedArray<Instruction>& instructions)
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002967{
akling@apple.com7dc7b8b2016-03-07 18:24:26 +00002968 if (!unlinkedCodeBlock()->hasOpProfileControlFlowBytecodeOffsets())
2969 return;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002970 const Vector<size_t>& bytecodeOffsets = unlinkedCodeBlock()->opProfileControlFlowBytecodeOffsets();
2971 for (size_t i = 0, offsetsLength = bytecodeOffsets.size(); i < offsetsLength; i++) {
2972 // Because op_profile_control_flow is emitted at the beginning of every basic block, finding
2973 // the next op_profile_control_flow will give us the text range of a single basic block.
2974 size_t startIdx = bytecodeOffsets[i];
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00002975 RELEASE_ASSERT(Interpreter::getOpcodeID(instructions[startIdx]) == op_profile_control_flow);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002976 int basicBlockStartOffset = instructions[startIdx + 1].u.operand;
2977 int basicBlockEndOffset;
2978 if (i + 1 < offsetsLength) {
2979 size_t endIdx = bytecodeOffsets[i + 1];
mark.lam@apple.com9b5601a2017-06-16 21:02:37 +00002980 RELEASE_ASSERT(Interpreter::getOpcodeID(instructions[endIdx]) == op_profile_control_flow);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002981 basicBlockEndOffset = instructions[endIdx + 1].u.operand - 1;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002982 } else {
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00002983 basicBlockEndOffset = m_sourceOffset + ownerScriptExecutable()->source().length() - 1; // Offset before the closing brace.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002984 basicBlockStartOffset = std::min(basicBlockStartOffset, basicBlockEndOffset); // Some start offsets may be at the closing brace, ensure it is the offset before.
2985 }
2986
2987 // The following check allows for the same textual JavaScript basic block to have its bytecode emitted more
2988 // than once and still play nice with the control flow profiler. When basicBlockStartOffset is larger than
2989 // basicBlockEndOffset, it indicates that the bytecode generator has emitted code for the same AST node
2990 // more than once (for example: ForInNode, Finally blocks in TryNode, etc). Though these are different
2991 // basic blocks at the bytecode level, they are generated from the same textual basic block in the JavaScript
2992 // program. The condition:
2993 // (basicBlockEndOffset < basicBlockStartOffset)
2994 // is encountered when op_profile_control_flow lies across the boundary of these duplicated bytecode basic
2995 // blocks and the textual offset goes from the end of the duplicated block back to the beginning. These
2996 // ranges are dummy ranges and are ignored. The duplicated bytecode basic blocks point to the same
2997 // internal data structure, so if any of them execute, it will record the same textual basic block in the
2998 // JavaScript program as executing.
2999 // At the bytecode level, this situation looks like:
3000 // j: op_profile_control_flow (from j->k, we have basicBlockEndOffset < basicBlockStartOffset)
3001 // ...
3002 // 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).
3003 // ...
3004 // m: op_profile_control_flow
3005 if (basicBlockEndOffset < basicBlockStartOffset) {
3006 RELEASE_ASSERT(i + 1 < offsetsLength); // We should never encounter dummy blocks at the end of a CodeBlock.
3007 instructions[startIdx + 1].u.basicBlockLocation = vm()->controlFlowProfiler()->dummyBasicBlock();
3008 continue;
3009 }
3010
commit-queue@webkit.orgfa196632015-08-28 21:07:22 +00003011 BasicBlockLocation* basicBlockLocation = vm()->controlFlowProfiler()->getBasicBlockLocation(ownerScriptExecutable()->sourceID(), basicBlockStartOffset, basicBlockEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003012
3013 // Find all functions that are enclosed within the range: [basicBlockStartOffset, basicBlockEndOffset]
3014 // and insert these functions' start/end offsets as gaps in the current BasicBlockLocation.
3015 // This is necessary because in the original source text of a JavaScript program,
3016 // function literals form new basic blocks boundaries, but they aren't represented
3017 // inside the CodeBlock's instruction stream.
3018 auto insertFunctionGaps = [basicBlockLocation, basicBlockStartOffset, basicBlockEndOffset] (const WriteBarrier<FunctionExecutable>& functionExecutable) {
3019 const UnlinkedFunctionExecutable* executable = functionExecutable->unlinkedExecutable();
3020 int functionStart = executable->typeProfilingStartOffset();
3021 int functionEnd = executable->typeProfilingEndOffset();
3022 if (functionStart >= basicBlockStartOffset && functionEnd <= basicBlockEndOffset)
3023 basicBlockLocation->insertGap(functionStart, functionEnd);
3024 };
3025
3026 for (const WriteBarrier<FunctionExecutable>& executable : m_functionDecls)
3027 insertFunctionGaps(executable);
3028 for (const WriteBarrier<FunctionExecutable>& executable : m_functionExprs)
3029 insertFunctionGaps(executable);
3030
3031 instructions[startIdx + 1].u.basicBlockLocation = basicBlockLocation;
3032 }
3033}
3034
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00003035#if ENABLE(JIT)
3036void CodeBlock::setPCToCodeOriginMap(std::unique_ptr<PCToCodeOriginMap>&& map)
3037{
3038 m_pcToCodeOriginMap = WTFMove(map);
3039}
3040
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003041std::optional<CodeOrigin> CodeBlock::findPC(void* pc)
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00003042{
3043 if (m_pcToCodeOriginMap) {
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003044 if (std::optional<CodeOrigin> codeOrigin = m_pcToCodeOriginMap->findPC(pc))
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00003045 return codeOrigin;
3046 }
3047
mark.lam@apple.com4554ee52018-01-08 21:05:17 +00003048 for (auto iter = m_stubInfos.begin(); !!iter; ++iter) {
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00003049 StructureStubInfo* stub = *iter;
3050 if (stub->containsPC(pc))
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003051 return std::optional<CodeOrigin>(stub->codeOrigin);
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00003052 }
3053
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003054 if (std::optional<CodeOrigin> codeOrigin = m_jitCode->findPC(this, pc))
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00003055 return codeOrigin;
3056
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003057 return std::nullopt;
sbarati@apple.comd3d0c002016-01-30 01:11:05 +00003058}
3059#endif // ENABLE(JIT)
3060
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003061std::optional<unsigned> CodeBlock::bytecodeOffsetFromCallSiteIndex(CallSiteIndex callSiteIndex)
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00003062{
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00003063 std::optional<unsigned> bytecodeOffset;
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00003064 JITCode::JITType jitType = this->jitType();
3065 if (jitType == JITCode::InterpreterThunk || jitType == JITCode::BaselineJIT) {
3066#if USE(JSVALUE64)
3067 bytecodeOffset = callSiteIndex.bits();
3068#else
3069 Instruction* instruction = bitwise_cast<Instruction*>(callSiteIndex.bits());
mark.lam@apple.comd5b8e182018-03-21 18:23:30 +00003070 bytecodeOffset = this->bytecodeOffset(instruction);
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00003071#endif
3072 } else if (jitType == JITCode::DFGJIT || jitType == JITCode::FTLJIT) {
sbarati@apple.com977e0ca2016-05-17 00:29:40 +00003073#if ENABLE(DFG_JIT)
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00003074 RELEASE_ASSERT(canGetCodeOrigin(callSiteIndex));
3075 CodeOrigin origin = codeOrigin(callSiteIndex);
3076 bytecodeOffset = origin.bytecodeIndex;
sbarati@apple.com977e0ca2016-05-17 00:29:40 +00003077#else
3078 RELEASE_ASSERT_NOT_REACHED();
3079#endif
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00003080 }
3081
3082 return bytecodeOffset;
3083}
3084
ggaren@apple.com2b404592016-06-15 19:20:23 +00003085int32_t CodeBlock::thresholdForJIT(int32_t threshold)
3086{
3087 switch (unlinkedCodeBlock()->didOptimize()) {
3088 case MixedTriState:
3089 return threshold;
3090 case FalseTriState:
3091 return threshold * 4;
3092 case TrueTriState:
3093 return threshold / 2;
3094 }
cdumez@apple.com92f1a7c2016-06-15 19:30:23 +00003095 ASSERT_NOT_REACHED();
3096 return threshold;
ggaren@apple.com2b404592016-06-15 19:20:23 +00003097}
3098
3099void CodeBlock::jitAfterWarmUp()
3100{
3101 m_llintExecuteCounter.setNewThreshold(thresholdForJIT(Options::thresholdForJITAfterWarmUp()), this);
3102}
3103
3104void CodeBlock::jitSoon()
3105{
3106 m_llintExecuteCounter.setNewThreshold(thresholdForJIT(Options::thresholdForJITSoon()), this);
3107}
3108
mark.lam@apple.comf842cd82017-03-09 19:08:46 +00003109bool CodeBlock::hasInstalledVMTrapBreakpoints() const
3110{
3111#if ENABLE(SIGNAL_BASED_VM_TRAPS)
mark.lam@apple.comf842cd82017-03-09 19:08:46 +00003112 // This function may be called from a signal handler. We need to be
3113 // careful to not call anything that is not signal handler safe, e.g.
3114 // we should not perturb the refCount of m_jitCode.
3115 if (!JITCode::isOptimizingJIT(jitType()))
3116 return false;
3117 return m_jitCode->dfgCommon()->hasInstalledVMTrapsBreakpoints();
3118#else
3119 return false;
3120#endif
3121}
3122
3123bool CodeBlock::installVMTrapBreakpoints()
3124{
3125#if ENABLE(SIGNAL_BASED_VM_TRAPS)
3126 // This function may be called from a signal handler. We need to be
3127 // careful to not call anything that is not signal handler safe, e.g.
3128 // we should not perturb the refCount of m_jitCode.
3129 if (!JITCode::isOptimizingJIT(jitType()))
3130 return false;
fpizlo@apple.coma5a2f0b2018-01-11 16:43:07 +00003131 auto& commonData = *m_jitCode->dfgCommon();
3132 commonData.installVMTrapBreakpoints(this);
mark.lam@apple.comf842cd82017-03-09 19:08:46 +00003133 return true;
3134#else
keith_miller@apple.comc670c532017-06-29 17:34:57 +00003135 UNREACHABLE_FOR_PLATFORM();
mark.lam@apple.comf842cd82017-03-09 19:08:46 +00003136 return false;
3137#endif
3138}
3139
sbarati@apple.comff204392016-07-25 20:40:39 +00003140void CodeBlock::dumpMathICStats()
3141{
3142#if ENABLE(MATH_IC_STATS)
3143 double numAdds = 0.0;
3144 double totalAddSize = 0.0;
3145 double numMuls = 0.0;
3146 double totalMulSize = 0.0;
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00003147 double numNegs = 0.0;
3148 double totalNegSize = 0.0;
sbarati@apple.com3e7ec7d2016-08-01 18:48:14 +00003149 double numSubs = 0.0;
3150 double totalSubSize = 0.0;
sbarati@apple.comff204392016-07-25 20:40:39 +00003151
3152 auto countICs = [&] (CodeBlock* codeBlock) {
3153 for (JITAddIC* addIC : codeBlock->m_addICs) {
3154 numAdds++;
3155 totalAddSize += addIC->codeSize();
3156 }
3157
3158 for (JITMulIC* mulIC : codeBlock->m_mulICs) {
3159 numMuls++;
3160 totalMulSize += mulIC->codeSize();
3161 }
3162
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00003163 for (JITNegIC* negIC : codeBlock->m_negICs) {
3164 numNegs++;
3165 totalNegSize += negIC->codeSize();
3166 }
3167
sbarati@apple.com3e7ec7d2016-08-01 18:48:14 +00003168 for (JITSubIC* subIC : codeBlock->m_subICs) {
3169 numSubs++;
3170 totalSubSize += subIC->codeSize();
3171 }
sbarati@apple.comff204392016-07-25 20:40:39 +00003172 };
3173 heap()->forEachCodeBlock(countICs);
3174
3175 dataLog("Num Adds: ", numAdds, "\n");
3176 dataLog("Total Add size in bytes: ", totalAddSize, "\n");
3177 dataLog("Average Add size: ", totalAddSize / numAdds, "\n");
3178 dataLog("\n");
3179 dataLog("Num Muls: ", numMuls, "\n");
3180 dataLog("Total Mul size in bytes: ", totalMulSize, "\n");
3181 dataLog("Average Mul size: ", totalMulSize / numMuls, "\n");
sbarati@apple.com3e7ec7d2016-08-01 18:48:14 +00003182 dataLog("\n");
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00003183 dataLog("Num Negs: ", numNegs, "\n");
3184 dataLog("Total Neg size in bytes: ", totalNegSize, "\n");
3185 dataLog("Average Neg size: ", totalNegSize / numNegs, "\n");
3186 dataLog("\n");
sbarati@apple.com3e7ec7d2016-08-01 18:48:14 +00003187 dataLog("Num Subs: ", numSubs, "\n");
3188 dataLog("Total Sub size in bytes: ", totalSubSize, "\n");
3189 dataLog("Average Sub size: ", totalSubSize / numSubs, "\n");
sbarati@apple.comff204392016-07-25 20:40:39 +00003190
3191 dataLog("-----------------------\n");
3192#endif
3193}
3194
mark.lam@apple.coma787fc72017-04-21 21:42:24 +00003195void setPrinter(Printer::PrintRecord& record, CodeBlock* codeBlock)
3196{
3197 Printer::setPrinter(record, toCString(codeBlock));
3198}
utatane.tea@gmail.comc2585192016-08-25 22:55:10 +00003199
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +00003200} // namespace JSC
mark.lam@apple.coma787fc72017-04-21 21:42:24 +00003201
3202namespace WTF {
3203
3204void printInternal(PrintStream& out, JSC::CodeBlock* codeBlock)
3205{
3206 if (UNLIKELY(!codeBlock)) {
3207 out.print("<null codeBlock>");
3208 return;
3209 }
3210 out.print(*codeBlock);
3211}
3212
3213} // namespace WTF