JITTimeFunctionBody.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "Backend.h"
  6. JITTimeFunctionBody::JITTimeFunctionBody(FunctionBodyDataIDL * bodyData) :
  7. m_bodyData(*bodyData)
  8. {
  9. CompileAssert(sizeof(JITTimeFunctionBody) == sizeof(FunctionBodyDataIDL));
  10. }
  11. /* static */
  12. void
  13. JITTimeFunctionBody::InitializeJITFunctionData(
  14. __in Recycler * recycler,
  15. __in Js::FunctionBody *functionBody,
  16. __out FunctionBodyDataIDL * jitBody)
  17. {
  18. Assert(functionBody != nullptr);
  19. // const table
  20. jitBody->constCount = functionBody->GetConstantCount();
  21. if (functionBody->GetConstantCount() > 0)
  22. {
  23. jitBody->constTable = (intptr_t *)functionBody->GetConstTable();
  24. if (!functionBody->GetIsAsmJsFunction())
  25. {
  26. jitBody->constTableContent = RecyclerNewStructZ(recycler, ConstTableContentIDL);
  27. jitBody->constTableContent->count = functionBody->GetConstantCount();
  28. jitBody->constTableContent->content = RecyclerNewArrayZ(recycler, RecyclableObjectIDL*, functionBody->GetConstantCount());
  29. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < functionBody->GetConstantCount(); ++reg)
  30. {
  31. Js::Var varConst = functionBody->GetConstantVar(reg);
  32. Assert(varConst != nullptr);
  33. if (Js::TaggedInt::Is(varConst) ||
  34. varConst == (Js::Var)&Js::NullFrameDisplay ||
  35. varConst == (Js::Var)&Js::StrictNullFrameDisplay)
  36. {
  37. // don't need TypeId for these
  38. }
  39. else
  40. {
  41. if (Js::TaggedNumber::Is(varConst))
  42. {
  43. // the typeid should be TypeIds_Number, determine this directly from const table
  44. }
  45. else
  46. {
  47. jitBody->constTableContent->content[reg - Js::FunctionBody::FirstRegSlot] = (RecyclableObjectIDL*)varConst;
  48. }
  49. }
  50. }
  51. }
  52. }
  53. Js::SmallSpanSequence * statementMap = functionBody->GetStatementMapSpanSequence();
  54. // REVIEW: OOP JIT, is it possible for this to not match with isJitInDebugMode?
  55. if (functionBody->IsInDebugMode())
  56. {
  57. Assert(!statementMap);
  58. jitBody->byteCodeLength = functionBody->GetOriginalByteCode()->GetLength();
  59. jitBody->byteCodeBuffer = functionBody->GetOriginalByteCode()->GetBuffer();
  60. auto fullStatementMaps = functionBody->GetStatementMaps();
  61. jitBody->fullStatementMapCount = fullStatementMaps->Count();
  62. jitBody->fullStatementMaps = RecyclerNewArrayZ(recycler, StatementMapIDL, jitBody->fullStatementMapCount);
  63. fullStatementMaps->Map([jitBody](int index, Js::FunctionBody::StatementMap * map) {
  64. jitBody->fullStatementMaps[index] = *(StatementMapIDL*)map;
  65. Assert(jitBody->fullStatementMaps[index].byteCodeSpanBegin == map->byteCodeSpan.Begin());
  66. Assert(jitBody->fullStatementMaps[index].byteCodeSpanEnd == map->byteCodeSpan.End());
  67. Assert(jitBody->fullStatementMaps[index].sourceSpanBegin == map->sourceSpan.Begin());
  68. Assert(jitBody->fullStatementMaps[index].sourceSpanEnd == map->sourceSpan.End());
  69. Assert((jitBody->fullStatementMaps[index].isSubExpression != FALSE) == map->isSubexpression);
  70. });
  71. if (functionBody->GetPropertyIdOnRegSlotsContainer())
  72. {
  73. jitBody->propertyIdsForRegSlotsCount = functionBody->GetPropertyIdOnRegSlotsContainer()->length;
  74. jitBody->propertyIdsForRegSlots = functionBody->GetPropertyIdOnRegSlotsContainer()->propertyIdsForRegSlots;
  75. }
  76. }
  77. else
  78. {
  79. Assert(statementMap);
  80. jitBody->byteCodeLength = functionBody->GetByteCode()->GetLength();
  81. jitBody->byteCodeBuffer = functionBody->GetByteCode()->GetBuffer();
  82. jitBody->statementMap = RecyclerNewStructZ(recycler, SmallSpanSequenceIDL);
  83. jitBody->statementMap->baseValue = statementMap->baseValue;
  84. if (statementMap->pActualOffsetList)
  85. {
  86. jitBody->statementMap->actualOffsetLength = statementMap->pActualOffsetList->Count();
  87. jitBody->statementMap->actualOffsetList = statementMap->pActualOffsetList->GetBuffer();
  88. }
  89. if (statementMap->pStatementBuffer)
  90. {
  91. jitBody->statementMap->statementLength = statementMap->pStatementBuffer->Count();
  92. jitBody->statementMap->statementBuffer = statementMap->pStatementBuffer->GetBuffer();
  93. }
  94. }
  95. jitBody->inlineCacheCount = functionBody->GetInlineCacheCount();
  96. if (functionBody->GetInlineCacheCount() > 0)
  97. {
  98. jitBody->cacheIdToPropertyIdMap = functionBody->GetCacheIdToPropertyIdMap();
  99. }
  100. jitBody->inlineCaches = reinterpret_cast<intptr_t*>(functionBody->GetInlineCaches());
  101. // body data
  102. jitBody->functionBodyAddr = (intptr_t)functionBody;
  103. jitBody->funcNumber = functionBody->GetFunctionNumber();
  104. jitBody->sourceContextId = functionBody->GetSourceContextId();
  105. jitBody->nestedCount = functionBody->GetNestedCount();
  106. if (functionBody->GetNestedCount() > 0)
  107. {
  108. jitBody->nestedFuncArrayAddr = (intptr_t)functionBody->GetNestedFuncArray();
  109. }
  110. jitBody->scopeSlotArraySize = functionBody->scopeSlotArraySize;
  111. jitBody->paramScopeSlotArraySize = functionBody->paramScopeSlotArraySize;
  112. jitBody->attributes = functionBody->GetAttributes();
  113. jitBody->isInstInlineCacheCount = functionBody->GetIsInstInlineCacheCount();
  114. if (functionBody->GetUtf8SourceInfo()->GetCbLength() > UINT_MAX)
  115. {
  116. Js::Throw::OutOfMemory();
  117. }
  118. jitBody->byteCodeCount = functionBody->GetByteCodeCount();
  119. jitBody->byteCodeInLoopCount = functionBody->GetByteCodeInLoopCount();
  120. jitBody->nonLoadByteCodeCount = functionBody->GetByteCodeWithoutLDACount();
  121. jitBody->loopCount = functionBody->GetLoopCount();
  122. if (functionBody->GetHasAllocatedLoopHeaders())
  123. {
  124. jitBody->loopHeaderArrayAddr = (intptr_t)functionBody->GetLoopHeaderArrayPtr();
  125. jitBody->loopHeaderArrayLength = functionBody->GetLoopCount();
  126. jitBody->loopHeaders = RecyclerNewArray(recycler, JITLoopHeaderIDL, functionBody->GetLoopCount());
  127. for (uint i = 0; i < functionBody->GetLoopCount(); ++i)
  128. {
  129. jitBody->loopHeaders[i].startOffset = functionBody->GetLoopHeader(i)->startOffset;
  130. jitBody->loopHeaders[i].endOffset = functionBody->GetLoopHeader(i)->endOffset;
  131. jitBody->loopHeaders[i].isNested = functionBody->GetLoopHeader(i)->isNested;
  132. jitBody->loopHeaders[i].isInTry = functionBody->GetLoopHeader(i)->isInTry;
  133. jitBody->loopHeaders[i].interpretCount = functionBody->GetLoopInterpretCount(functionBody->GetLoopHeader(i));
  134. }
  135. }
  136. jitBody->localFrameDisplayReg = functionBody->GetLocalFrameDisplayRegister();
  137. jitBody->localClosureReg = functionBody->GetLocalClosureRegister();
  138. jitBody->envReg = functionBody->GetEnvRegister();
  139. jitBody->firstTmpReg = functionBody->GetFirstTmpReg();
  140. jitBody->varCount = functionBody->GetVarCount();
  141. jitBody->innerScopeCount = functionBody->GetInnerScopeCount();
  142. if (functionBody->GetInnerScopeCount() > 0)
  143. {
  144. jitBody->firstInnerScopeReg = functionBody->GetFirstInnerScopeRegister();
  145. }
  146. jitBody->envDepth = functionBody->GetEnvDepth();
  147. jitBody->profiledIterations = functionBody->GetProfiledIterations();
  148. jitBody->profiledCallSiteCount = functionBody->GetProfiledCallSiteCount();
  149. jitBody->inParamCount = functionBody->GetInParamsCount();
  150. jitBody->thisRegisterForEventHandler = functionBody->GetThisRegisterForEventHandler();
  151. jitBody->funcExprScopeRegister = functionBody->GetFuncExprScopeRegister();
  152. jitBody->recursiveCallSiteCount = functionBody->GetNumberOfRecursiveCallSites();
  153. jitBody->argUsedForBranch = functionBody->m_argUsedForBranch;
  154. jitBody->flags = functionBody->GetFlags();
  155. jitBody->doBackendArgumentsOptimization = functionBody->GetDoBackendArgumentsOptimization();
  156. jitBody->isLibraryCode = functionBody->GetUtf8SourceInfo()->GetIsLibraryCode();
  157. jitBody->isAsmJsMode = functionBody->GetIsAsmjsMode();
  158. jitBody->isStrictMode = functionBody->GetIsStrictMode();
  159. jitBody->isEval = functionBody->IsEval();
  160. jitBody->isGlobalFunc = functionBody->GetIsGlobalFunc();
  161. jitBody->isInlineApplyDisabled = functionBody->IsInlineApplyDisabled();
  162. jitBody->doJITLoopBody = functionBody->DoJITLoopBody();
  163. jitBody->hasScopeObject = functionBody->HasScopeObject();
  164. jitBody->hasImplicitArgIns = functionBody->GetHasImplicitArgIns();
  165. jitBody->hasCachedScopePropIds = functionBody->HasCachedScopePropIds();
  166. jitBody->inlineCachesOnFunctionObject = functionBody->GetInlineCachesOnFunctionObject();
  167. jitBody->doInterruptProbe = functionBody->GetScriptContext()->GetThreadContext()->DoInterruptProbe(functionBody);
  168. jitBody->disableInlineSpread = functionBody->IsInlineSpreadDisabled();
  169. jitBody->hasNestedLoop = functionBody->GetHasNestedLoop();
  170. jitBody->isParamAndBodyScopeMerged = functionBody->IsParamAndBodyScopeMerged();
  171. jitBody->paramClosureReg = functionBody->GetParamClosureRegister();
  172. jitBody->usesArgumentsObject = functionBody->GetUsesArgumentsObject();
  173. //CompileAssert(sizeof(PropertyIdArrayIDL) == sizeof(Js::PropertyIdArray));
  174. jitBody->formalsPropIdArray = (PropertyIdArrayIDL*)functionBody->GetFormalsPropIdArray(false);
  175. jitBody->formalsPropIdArrayAddr = (intptr_t)functionBody->GetFormalsPropIdArray(false);
  176. if (functionBody->HasDynamicProfileInfo() && Js::DynamicProfileInfo::HasCallSiteInfo(functionBody))
  177. {
  178. jitBody->hasNonBuiltInCallee = functionBody->HasNonBuiltInCallee();
  179. }
  180. if (functionBody->GetAuxiliaryData() != nullptr)
  181. {
  182. jitBody->auxDataCount = functionBody->GetAuxiliaryData()->GetLength();
  183. jitBody->auxData = functionBody->GetAuxiliaryData()->GetBuffer();
  184. jitBody->auxDataBufferAddr = (intptr_t)functionBody->GetAuxiliaryData()->GetBuffer();
  185. }
  186. if (functionBody->GetAuxiliaryContextData() != nullptr)
  187. {
  188. jitBody->auxContextDataCount = functionBody->GetAuxiliaryContextData()->GetLength();
  189. jitBody->auxContextData = functionBody->GetAuxiliaryContextData()->GetBuffer();
  190. }
  191. jitBody->scriptIdAddr = (intptr_t)functionBody->GetAddressOfScriptId();
  192. jitBody->flagsAddr = (intptr_t)functionBody->GetAddressOfFlags();
  193. jitBody->probeCountAddr = (intptr_t)&functionBody->GetSourceInfo()->m_probeCount;
  194. jitBody->regAllocLoadCountAddr = (intptr_t)&functionBody->regAllocLoadCount;
  195. jitBody->regAllocStoreCountAddr = (intptr_t)&functionBody->regAllocStoreCount;
  196. jitBody->callCountStatsAddr = (intptr_t)&functionBody->callCountStats;
  197. jitBody->referencedPropertyIdCount = functionBody->GetReferencedPropertyIdCount();
  198. jitBody->referencedPropertyIdMap = functionBody->GetReferencedPropertyIdMap();
  199. jitBody->hasFinally = functionBody->GetHasFinally();
  200. jitBody->nameLength = functionBody->GetDisplayNameLength() + 1; // +1 for null terminator
  201. jitBody->displayName = (char16 *)functionBody->GetDisplayName();
  202. jitBody->objectLiteralTypesAddr = (intptr_t)functionBody->GetObjectLiteralTypes();
  203. jitBody->literalRegexCount = functionBody->GetLiteralRegexCount();
  204. jitBody->literalRegexes = (intptr_t*)functionBody->GetLiteralRegexes();
  205. if (functionBody->GetIsAsmJsFunction())
  206. {
  207. jitBody->asmJsData = RecyclerNew(recycler, AsmJsDataIDL);
  208. Js::AsmJsFunctionInfo * asmFuncInfo = functionBody->GetAsmJsFunctionInfo();
  209. jitBody->asmJsData->intConstCount = asmFuncInfo->GetIntConstCount();
  210. jitBody->asmJsData->doubleConstCount = asmFuncInfo->GetDoubleConstCount();
  211. jitBody->asmJsData->floatConstCount = asmFuncInfo->GetFloatConstCount();
  212. jitBody->asmJsData->simdConstCount = asmFuncInfo->GetSimdConstCount();
  213. jitBody->asmJsData->intTmpCount = asmFuncInfo->GetIntTmpCount();
  214. jitBody->asmJsData->doubleTmpCount = asmFuncInfo->GetDoubleTmpCount();
  215. jitBody->asmJsData->floatTmpCount = asmFuncInfo->GetFloatTmpCount();
  216. jitBody->asmJsData->simdTmpCount = asmFuncInfo->GetSimdTmpCount();
  217. jitBody->asmJsData->intVarCount = asmFuncInfo->GetIntVarCount();
  218. jitBody->asmJsData->doubleVarCount = asmFuncInfo->GetDoubleVarCount();
  219. jitBody->asmJsData->floatVarCount = asmFuncInfo->GetFloatVarCount();
  220. jitBody->asmJsData->simdVarCount = asmFuncInfo->GetSimdVarCount();
  221. jitBody->asmJsData->intByteOffset = asmFuncInfo->GetIntByteOffset();
  222. jitBody->asmJsData->doubleByteOffset = asmFuncInfo->GetDoubleByteOffset();
  223. jitBody->asmJsData->floatByteOffset = asmFuncInfo->GetFloatByteOffset();
  224. jitBody->asmJsData->simdByteOffset = asmFuncInfo->GetSimdByteOffset();
  225. jitBody->asmJsData->argCount = asmFuncInfo->GetArgCount();
  226. jitBody->asmJsData->argTypeArray = (byte*)asmFuncInfo->GetArgTypeArray();
  227. jitBody->asmJsData->argByteSize = asmFuncInfo->GetArgByteSize();
  228. jitBody->asmJsData->retType = asmFuncInfo->GetReturnType().which();
  229. jitBody->asmJsData->isHeapBufferConst = asmFuncInfo->IsHeapBufferConst();
  230. jitBody->asmJsData->usesHeapBuffer = asmFuncInfo->UsesHeapBuffer();
  231. jitBody->asmJsData->totalSizeInBytes = asmFuncInfo->GetTotalSizeinBytes();
  232. }
  233. }
  234. intptr_t
  235. JITTimeFunctionBody::GetAddr() const
  236. {
  237. return m_bodyData.functionBodyAddr;
  238. }
  239. uint
  240. JITTimeFunctionBody::GetFunctionNumber() const
  241. {
  242. return m_bodyData.funcNumber;
  243. }
  244. uint
  245. JITTimeFunctionBody::GetSourceContextId() const
  246. {
  247. return m_bodyData.sourceContextId;
  248. }
  249. uint
  250. JITTimeFunctionBody::GetNestedCount() const
  251. {
  252. return m_bodyData.nestedCount;
  253. }
  254. uint
  255. JITTimeFunctionBody::GetScopeSlotArraySize() const
  256. {
  257. return m_bodyData.scopeSlotArraySize;
  258. }
  259. uint
  260. JITTimeFunctionBody::GetParamScopeSlotArraySize() const
  261. {
  262. return m_bodyData.paramScopeSlotArraySize;
  263. }
  264. uint
  265. JITTimeFunctionBody::GetByteCodeCount() const
  266. {
  267. return m_bodyData.byteCodeCount;
  268. }
  269. uint
  270. JITTimeFunctionBody::GetByteCodeInLoopCount() const
  271. {
  272. return m_bodyData.byteCodeInLoopCount;
  273. }
  274. uint
  275. JITTimeFunctionBody::GetNonLoadByteCodeCount() const
  276. {
  277. return m_bodyData.nonLoadByteCodeCount;
  278. }
  279. uint
  280. JITTimeFunctionBody::GetLoopCount() const
  281. {
  282. return m_bodyData.loopCount;
  283. }
  284. bool
  285. JITTimeFunctionBody::HasLoops() const
  286. {
  287. return GetLoopCount() != 0;
  288. }
  289. uint
  290. JITTimeFunctionBody::GetByteCodeLength() const
  291. {
  292. return m_bodyData.byteCodeLength;
  293. }
  294. uint
  295. JITTimeFunctionBody::GetInnerScopeCount() const
  296. {
  297. return m_bodyData.innerScopeCount;
  298. }
  299. uint
  300. JITTimeFunctionBody::GetInlineCacheCount() const
  301. {
  302. return m_bodyData.inlineCacheCount;
  303. }
  304. uint
  305. JITTimeFunctionBody::GetRecursiveCallSiteCount() const
  306. {
  307. return m_bodyData.recursiveCallSiteCount;
  308. }
  309. Js::RegSlot
  310. JITTimeFunctionBody::GetLocalFrameDisplayReg() const
  311. {
  312. return static_cast<Js::RegSlot>(m_bodyData.localFrameDisplayReg);
  313. }
  314. Js::RegSlot
  315. JITTimeFunctionBody::GetLocalClosureReg() const
  316. {
  317. return static_cast<Js::RegSlot>(m_bodyData.localClosureReg);
  318. }
  319. Js::RegSlot
  320. JITTimeFunctionBody::GetEnvReg() const
  321. {
  322. return static_cast<Js::RegSlot>(m_bodyData.envReg);
  323. }
  324. Js::RegSlot
  325. JITTimeFunctionBody::GetFirstTmpReg() const
  326. {
  327. return static_cast<Js::RegSlot>(m_bodyData.firstTmpReg);
  328. }
  329. Js::RegSlot
  330. JITTimeFunctionBody::GetFirstInnerScopeReg() const
  331. {
  332. return static_cast<Js::RegSlot>(m_bodyData.firstInnerScopeReg);
  333. }
  334. Js::RegSlot
  335. JITTimeFunctionBody::GetVarCount() const
  336. {
  337. return static_cast<Js::RegSlot>(m_bodyData.varCount);
  338. }
  339. Js::RegSlot
  340. JITTimeFunctionBody::GetConstCount() const
  341. {
  342. return static_cast<Js::RegSlot>(m_bodyData.constCount);
  343. }
  344. Js::RegSlot
  345. JITTimeFunctionBody::GetLocalsCount() const
  346. {
  347. return GetConstCount() + GetVarCount();
  348. }
  349. Js::RegSlot
  350. JITTimeFunctionBody::GetTempCount() const
  351. {
  352. return GetLocalsCount() - GetFirstTmpReg();
  353. }
  354. Js::RegSlot
  355. JITTimeFunctionBody::GetFuncExprScopeReg() const
  356. {
  357. return static_cast<Js::RegSlot>(m_bodyData.funcExprScopeRegister);
  358. }
  359. Js::RegSlot
  360. JITTimeFunctionBody::GetThisRegForEventHandler() const
  361. {
  362. return static_cast<Js::RegSlot>(m_bodyData.thisRegisterForEventHandler);
  363. }
  364. Js::RegSlot
  365. JITTimeFunctionBody::GetParamClosureReg() const
  366. {
  367. return static_cast<Js::RegSlot>(m_bodyData.paramClosureReg);
  368. }
  369. Js::RegSlot
  370. JITTimeFunctionBody::GetFirstNonTempLocalIndex() const
  371. {
  372. // First local var starts when the const vars end.
  373. return GetConstCount();
  374. }
  375. Js::RegSlot
  376. JITTimeFunctionBody::GetEndNonTempLocalIndex() const
  377. {
  378. // It will give the index on which current non temp locals ends, which is a first temp reg.
  379. return GetFirstTmpReg() != Js::Constants::NoRegister ? GetFirstTmpReg() : GetLocalsCount();
  380. }
  381. Js::RegSlot
  382. JITTimeFunctionBody::GetNonTempLocalVarCount() const
  383. {
  384. Assert(GetEndNonTempLocalIndex() >= GetFirstNonTempLocalIndex());
  385. return GetEndNonTempLocalIndex() - GetFirstNonTempLocalIndex();
  386. }
  387. Js::RegSlot
  388. JITTimeFunctionBody::GetRestParamRegSlot() const
  389. {
  390. Js::RegSlot dstRegSlot = GetConstCount();
  391. if (HasImplicitArgIns())
  392. {
  393. dstRegSlot += GetInParamsCount() - 1;
  394. }
  395. return dstRegSlot;
  396. }
  397. Js::PropertyId
  398. JITTimeFunctionBody::GetPropertyIdFromCacheId(uint cacheId) const
  399. {
  400. Assert(m_bodyData.cacheIdToPropertyIdMap);
  401. Assert(cacheId < GetInlineCacheCount());
  402. return static_cast<Js::PropertyId>(m_bodyData.cacheIdToPropertyIdMap[cacheId]);
  403. }
  404. Js::PropertyId
  405. JITTimeFunctionBody::GetReferencedPropertyId(uint index) const
  406. {
  407. if (index < (uint)TotalNumberOfBuiltInProperties)
  408. {
  409. return index;
  410. }
  411. uint mapIndex = index - TotalNumberOfBuiltInProperties;
  412. Assert(m_bodyData.referencedPropertyIdMap != nullptr);
  413. Assert(mapIndex < m_bodyData.referencedPropertyIdCount);
  414. return m_bodyData.referencedPropertyIdMap[mapIndex];
  415. }
  416. uint16
  417. JITTimeFunctionBody::GetArgUsedForBranch() const
  418. {
  419. return m_bodyData.argUsedForBranch;
  420. }
  421. uint16
  422. JITTimeFunctionBody::GetEnvDepth() const
  423. {
  424. return m_bodyData.envDepth;
  425. }
  426. uint16
  427. JITTimeFunctionBody::GetProfiledIterations() const
  428. {
  429. return m_bodyData.profiledIterations;
  430. }
  431. Js::ProfileId
  432. JITTimeFunctionBody::GetProfiledCallSiteCount() const
  433. {
  434. return static_cast<Js::ProfileId>(m_bodyData.profiledCallSiteCount);
  435. }
  436. Js::ArgSlot
  437. JITTimeFunctionBody::GetInParamsCount() const
  438. {
  439. return static_cast<Js::ArgSlot>(m_bodyData.inParamCount);
  440. }
  441. bool
  442. JITTimeFunctionBody::DoStackNestedFunc() const
  443. {
  444. return Js::FunctionBody::DoStackNestedFunc(GetFlags());
  445. }
  446. bool
  447. JITTimeFunctionBody::DoStackClosure() const
  448. {
  449. return Js::FunctionBody::DoStackClosure(this);
  450. }
  451. bool
  452. JITTimeFunctionBody::HasTry() const
  453. {
  454. return Js::FunctionBody::GetHasTry(GetFlags());
  455. }
  456. bool
  457. JITTimeFunctionBody::HasThis() const
  458. {
  459. return Js::FunctionBody::GetHasThis(GetFlags());
  460. }
  461. bool
  462. JITTimeFunctionBody::HasFinally() const
  463. {
  464. return m_bodyData.hasFinally != FALSE;
  465. }
  466. bool
  467. JITTimeFunctionBody::HasOrParentHasArguments() const
  468. {
  469. return Js::FunctionBody::GetHasOrParentHasArguments(GetFlags());
  470. }
  471. bool
  472. JITTimeFunctionBody::DoBackendArgumentsOptimization() const
  473. {
  474. return m_bodyData.doBackendArgumentsOptimization != FALSE;
  475. }
  476. bool
  477. JITTimeFunctionBody::IsLibraryCode() const
  478. {
  479. return m_bodyData.isLibraryCode != FALSE;
  480. }
  481. bool
  482. JITTimeFunctionBody::IsAsmJsMode() const
  483. {
  484. return m_bodyData.isAsmJsMode != FALSE;
  485. }
  486. bool
  487. JITTimeFunctionBody::IsStrictMode() const
  488. {
  489. return m_bodyData.isStrictMode != FALSE;
  490. }
  491. bool
  492. JITTimeFunctionBody::IsEval() const
  493. {
  494. return m_bodyData.isEval != FALSE;
  495. }
  496. bool
  497. JITTimeFunctionBody::HasScopeObject() const
  498. {
  499. return m_bodyData.hasScopeObject != FALSE;
  500. }
  501. bool
  502. JITTimeFunctionBody::HasNestedLoop() const
  503. {
  504. return m_bodyData.hasNestedLoop != FALSE;
  505. }
  506. bool
  507. JITTimeFunctionBody::UsesArgumentsObject() const
  508. {
  509. return m_bodyData.usesArgumentsObject != FALSE;
  510. }
  511. bool
  512. JITTimeFunctionBody::IsParamAndBodyScopeMerged() const
  513. {
  514. return m_bodyData.isParamAndBodyScopeMerged != FALSE;
  515. }
  516. bool
  517. JITTimeFunctionBody::IsCoroutine() const
  518. {
  519. return Js::FunctionInfo::IsCoroutine(GetAttributes());
  520. }
  521. bool
  522. JITTimeFunctionBody::IsGenerator() const
  523. {
  524. return Js::FunctionInfo::IsGenerator(GetAttributes());
  525. }
  526. bool
  527. JITTimeFunctionBody::IsLambda() const
  528. {
  529. return Js::FunctionInfo::IsLambda(GetAttributes());
  530. }
  531. bool
  532. JITTimeFunctionBody::HasImplicitArgIns() const
  533. {
  534. return m_bodyData.hasImplicitArgIns != FALSE;
  535. }
  536. bool
  537. JITTimeFunctionBody::HasCachedScopePropIds() const
  538. {
  539. return m_bodyData.hasCachedScopePropIds != FALSE;
  540. }
  541. bool
  542. JITTimeFunctionBody::HasInlineCachesOnFunctionObject() const
  543. {
  544. return m_bodyData.inlineCachesOnFunctionObject != FALSE;
  545. }
  546. bool
  547. JITTimeFunctionBody::DoInterruptProbe() const
  548. {
  549. // TODO michhol: this is technically a threadcontext flag,
  550. // may want to pass all these when initializing thread context
  551. return m_bodyData.doInterruptProbe != FALSE;
  552. }
  553. bool
  554. JITTimeFunctionBody::HasRestParameter() const
  555. {
  556. return Js::FunctionBody::GetHasRestParameter(GetFlags());
  557. }
  558. bool
  559. JITTimeFunctionBody::IsGlobalFunc() const
  560. {
  561. return m_bodyData.isGlobalFunc != FALSE;
  562. }
  563. void
  564. JITTimeFunctionBody::DisableInlineApply()
  565. {
  566. m_bodyData.isInlineApplyDisabled = TRUE;
  567. }
  568. bool
  569. JITTimeFunctionBody::IsInlineApplyDisabled() const
  570. {
  571. return m_bodyData.isInlineApplyDisabled != FALSE;
  572. }
  573. bool
  574. JITTimeFunctionBody::IsNonTempLocalVar(uint32 varIndex) const
  575. {
  576. return GetFirstNonTempLocalIndex() <= varIndex && varIndex < GetEndNonTempLocalIndex();
  577. }
  578. bool
  579. JITTimeFunctionBody::DoJITLoopBody() const
  580. {
  581. return m_bodyData.doJITLoopBody != FALSE;
  582. }
  583. void
  584. JITTimeFunctionBody::DisableInlineSpread()
  585. {
  586. m_bodyData.disableInlineSpread = TRUE;
  587. }
  588. bool
  589. JITTimeFunctionBody::IsInlineSpreadDisabled() const
  590. {
  591. return m_bodyData.disableInlineSpread != FALSE;
  592. }
  593. bool
  594. JITTimeFunctionBody::HasNonBuiltInCallee() const
  595. {
  596. return m_bodyData.hasNonBuiltInCallee != FALSE;
  597. }
  598. bool
  599. JITTimeFunctionBody::CanInlineRecursively(uint depth, bool tryAggressive) const
  600. {
  601. uint recursiveInlineSpan = GetRecursiveCallSiteCount();
  602. uint minRecursiveInlineDepth = (uint)CONFIG_FLAG(RecursiveInlineDepthMin);
  603. if (recursiveInlineSpan != GetProfiledCallSiteCount() || tryAggressive == false)
  604. {
  605. return depth < minRecursiveInlineDepth;
  606. }
  607. uint maxRecursiveInlineDepth = (uint)CONFIG_FLAG(RecursiveInlineDepthMax);
  608. uint maxRecursiveBytecodeBudget = (uint)CONFIG_FLAG(RecursiveInlineThreshold);
  609. uint numberOfAllowedFuncs = maxRecursiveBytecodeBudget / GetNonLoadByteCodeCount();
  610. uint maxDepth;
  611. if (recursiveInlineSpan == 1)
  612. {
  613. maxDepth = numberOfAllowedFuncs;
  614. }
  615. else
  616. {
  617. maxDepth = (uint)ceil(log((double)((double)numberOfAllowedFuncs) / log((double)recursiveInlineSpan)));
  618. }
  619. maxDepth = maxDepth < minRecursiveInlineDepth ? minRecursiveInlineDepth : maxDepth;
  620. maxDepth = maxDepth < maxRecursiveInlineDepth ? maxDepth : maxRecursiveInlineDepth;
  621. return depth < maxDepth;
  622. }
  623. bool
  624. JITTimeFunctionBody::NeedScopeObjectForArguments(bool hasNonSimpleParams) const
  625. {
  626. // TODO: OOP JIT, enable assert
  627. //Assert(HasReferenceableBuiltInArguments());
  628. // We can avoid creating a scope object with arguments present if:
  629. bool dontNeedScopeObject =
  630. // Either we are in strict mode, or have strict mode formal semantics from a non-simple parameter list, and
  631. (IsStrictMode() || hasNonSimpleParams)
  632. // Neither of the scopes are objects
  633. && !HasScopeObject();
  634. return
  635. // Regardless of the conditions above, we won't need a scope object if there aren't any formals.
  636. (GetInParamsCount() > 1 || HasRestParameter())
  637. && !dontNeedScopeObject;
  638. }
  639. const byte *
  640. JITTimeFunctionBody::GetByteCodeBuffer() const
  641. {
  642. return m_bodyData.byteCodeBuffer;
  643. }
  644. StatementMapIDL *
  645. JITTimeFunctionBody::GetFullStatementMap() const
  646. {
  647. return m_bodyData.fullStatementMaps;
  648. }
  649. uint
  650. JITTimeFunctionBody::GetFullStatementMapCount() const
  651. {
  652. return m_bodyData.fullStatementMapCount;
  653. }
  654. intptr_t
  655. JITTimeFunctionBody::GetScriptIdAddr() const
  656. {
  657. return m_bodyData.scriptIdAddr;
  658. }
  659. intptr_t
  660. JITTimeFunctionBody::GetProbeCountAddr() const
  661. {
  662. return m_bodyData.probeCountAddr;
  663. }
  664. intptr_t
  665. JITTimeFunctionBody::GetFlagsAddr() const
  666. {
  667. return m_bodyData.flagsAddr;
  668. }
  669. intptr_t
  670. JITTimeFunctionBody::GetRegAllocLoadCountAddr() const
  671. {
  672. return m_bodyData.regAllocLoadCountAddr;
  673. }
  674. intptr_t
  675. JITTimeFunctionBody::GetFormalsPropIdArrayAddr() const
  676. {
  677. return m_bodyData.formalsPropIdArrayAddr;
  678. }
  679. intptr_t
  680. JITTimeFunctionBody::GetRegAllocStoreCountAddr() const
  681. {
  682. return m_bodyData.regAllocStoreCountAddr;
  683. }
  684. intptr_t
  685. JITTimeFunctionBody::GetCallCountStatsAddr() const
  686. {
  687. return m_bodyData.callCountStatsAddr;
  688. }
  689. intptr_t
  690. JITTimeFunctionBody::GetObjectLiteralTypeRef(uint index) const
  691. {
  692. Assert(m_bodyData.objectLiteralTypesAddr != 0);
  693. return m_bodyData.objectLiteralTypesAddr + index * MachPtr;
  694. }
  695. intptr_t
  696. JITTimeFunctionBody::GetConstantVar(Js::RegSlot location) const
  697. {
  698. Assert(m_bodyData.constTable != nullptr);
  699. Assert(location < GetConstCount());
  700. Assert(location != 0);
  701. return static_cast<intptr_t>(m_bodyData.constTable[location - Js::FunctionBody::FirstRegSlot]);
  702. }
  703. JITRecyclableObject *
  704. JITTimeFunctionBody::GetConstantContent(Js::RegSlot location) const
  705. {
  706. Assert(m_bodyData.constTableContent != nullptr);
  707. Assert(m_bodyData.constTableContent->content != nullptr);
  708. Assert(location < GetConstCount());
  709. Assert(location != 0);
  710. JITRecyclableObject * obj = (JITRecyclableObject *)m_bodyData.constTableContent->content[location - Js::FunctionBody::FirstRegSlot];
  711. Assert(obj);
  712. return obj;
  713. }
  714. intptr_t
  715. JITTimeFunctionBody::GetInlineCache(uint index) const
  716. {
  717. Assert(m_bodyData.inlineCaches != nullptr);
  718. Assert(index < GetInlineCacheCount());
  719. #if 0 // TODO: michhol OOP JIT, add these asserts
  720. Assert(this->m_inlineCacheTypes[index] == InlineCacheTypeNone ||
  721. this->m_inlineCacheTypes[index] == InlineCacheTypeInlineCache);
  722. this->m_inlineCacheTypes[index] = InlineCacheTypeInlineCache;
  723. #endif
  724. return static_cast<intptr_t>(m_bodyData.inlineCaches[index]);
  725. }
  726. intptr_t
  727. JITTimeFunctionBody::GetIsInstInlineCache(uint index) const
  728. {
  729. Assert(m_bodyData.inlineCaches != nullptr);
  730. Assert(index < m_bodyData.isInstInlineCacheCount);
  731. index += GetInlineCacheCount();
  732. #if 0 // TODO: michhol OOP JIT, add these asserts
  733. Assert(this->m_inlineCacheTypes[index] == InlineCacheTypeNone ||
  734. this->m_inlineCacheTypes[index] == InlineCacheTypeIsInst);
  735. this->m_inlineCacheTypes[index] = InlineCacheTypeIsInst;
  736. #endif
  737. return static_cast<intptr_t>(m_bodyData.inlineCaches[index]);
  738. }
  739. Js::TypeId
  740. JITTimeFunctionBody::GetConstantType(Js::RegSlot location) const
  741. {
  742. Assert(m_bodyData.constTable != nullptr);
  743. Assert(m_bodyData.constTableContent != nullptr);
  744. Assert(location < GetConstCount());
  745. Assert(location != 0);
  746. auto obj = m_bodyData.constTableContent->content[location - Js::FunctionBody::FirstRegSlot];
  747. if (obj == nullptr)
  748. {
  749. if (Js::TaggedNumber::Is((Js::Var)GetConstantVar(location)))
  750. {
  751. // tagged float
  752. return Js::TypeId::TypeIds_Number;
  753. }
  754. else
  755. {
  756. return Js::TypeId::TypeIds_Limit;
  757. }
  758. }
  759. return static_cast<Js::TypeId>(*(obj->typeId));
  760. }
  761. intptr_t
  762. JITTimeFunctionBody::GetLiteralRegexAddr(uint index) const
  763. {
  764. Assert(index < m_bodyData.literalRegexCount);
  765. return m_bodyData.literalRegexes[index];
  766. }
  767. void *
  768. JITTimeFunctionBody::GetConstTable() const
  769. {
  770. return m_bodyData.constTable;
  771. }
  772. bool
  773. JITTimeFunctionBody::IsConstRegPropertyString(Js::RegSlot reg, ScriptContextInfo * context) const
  774. {
  775. RecyclableObjectIDL * content = m_bodyData.constTableContent->content[reg - Js::FunctionBody::FirstRegSlot];
  776. if (content != nullptr && content->vtbl == context->GetVTableAddress(VtablePropertyString))
  777. {
  778. return true;
  779. }
  780. return false;
  781. }
  782. intptr_t
  783. JITTimeFunctionBody::GetRootObject() const
  784. {
  785. Assert(m_bodyData.constTable != nullptr);
  786. return m_bodyData.constTable[Js::FunctionBody::RootObjectRegSlot - Js::FunctionBody::FirstRegSlot];
  787. }
  788. intptr_t
  789. JITTimeFunctionBody::GetNestedFuncRef(uint index) const
  790. {
  791. Assert(index < GetNestedCount());
  792. intptr_t baseAddr = m_bodyData.nestedFuncArrayAddr;
  793. return baseAddr + (index * sizeof(void*));
  794. }
  795. intptr_t
  796. JITTimeFunctionBody::GetLoopHeaderAddr(uint loopNum) const
  797. {
  798. Assert(loopNum < GetLoopCount());
  799. intptr_t baseAddr = m_bodyData.loopHeaderArrayAddr;
  800. return baseAddr + (loopNum * sizeof(Js::LoopHeader));
  801. }
  802. const JITLoopHeaderIDL *
  803. JITTimeFunctionBody::GetLoopHeaderData(uint loopNum) const
  804. {
  805. Assert(loopNum < GetLoopCount());
  806. return &m_bodyData.loopHeaders[loopNum];
  807. }
  808. const AsmJsJITInfo *
  809. JITTimeFunctionBody::GetAsmJsInfo() const
  810. {
  811. return reinterpret_cast<const AsmJsJITInfo *>(m_bodyData.asmJsData);
  812. }
  813. JITTimeProfileInfo *
  814. JITTimeFunctionBody::GetProfileInfo() const
  815. {
  816. return reinterpret_cast<JITTimeProfileInfo *>(m_bodyData.profileData);
  817. }
  818. const JITTimeProfileInfo *
  819. JITTimeFunctionBody::GetReadOnlyProfileInfo() const
  820. {
  821. return reinterpret_cast<const JITTimeProfileInfo *>(m_bodyData.profileData);
  822. }
  823. bool
  824. JITTimeFunctionBody::HasProfileInfo() const
  825. {
  826. return m_bodyData.profileData != nullptr;
  827. }
  828. bool
  829. JITTimeFunctionBody::HasPropIdToFormalsMap() const
  830. {
  831. return m_bodyData.propertyIdsForRegSlotsCount > 0 && GetFormalsPropIdArray() != nullptr;
  832. }
  833. bool
  834. JITTimeFunctionBody::IsRegSlotFormal(Js::RegSlot reg) const
  835. {
  836. Assert(reg < m_bodyData.propertyIdsForRegSlotsCount);
  837. Js::PropertyId propId = (Js::PropertyId)m_bodyData.propertyIdsForRegSlots[reg];
  838. Js::PropertyIdArray * formalProps = GetFormalsPropIdArray();
  839. for (uint32 i = 0; i < formalProps->count; i++)
  840. {
  841. if (formalProps->elements[i] == propId)
  842. {
  843. return true;
  844. }
  845. }
  846. return false;
  847. }
  848. /* static */
  849. bool
  850. JITTimeFunctionBody::LoopContains(const JITLoopHeaderIDL * loop1, const JITLoopHeaderIDL * loop2)
  851. {
  852. return (loop1->startOffset <= loop2->startOffset && loop2->endOffset <= loop1->endOffset);
  853. }
  854. Js::FunctionBody::FunctionBodyFlags
  855. JITTimeFunctionBody::GetFlags() const
  856. {
  857. return static_cast<Js::FunctionBody::FunctionBodyFlags>(m_bodyData.flags);
  858. }
  859. Js::FunctionInfo::Attributes
  860. JITTimeFunctionBody::GetAttributes() const
  861. {
  862. return static_cast<Js::FunctionInfo::Attributes>(m_bodyData.attributes);
  863. }
  864. intptr_t
  865. JITTimeFunctionBody::GetAuxDataAddr(uint offset) const
  866. {
  867. return m_bodyData.auxDataBufferAddr + offset;
  868. }
  869. void *
  870. JITTimeFunctionBody::ReadFromAuxData(uint offset) const
  871. {
  872. return (void *)(m_bodyData.auxData + offset);
  873. }
  874. void *
  875. JITTimeFunctionBody::ReadFromAuxContextData(uint offset) const
  876. {
  877. return (void *)(m_bodyData.auxContextData + offset);
  878. }
  879. const Js::PropertyIdArray *
  880. JITTimeFunctionBody::ReadPropertyIdArrayFromAuxData(uint offset) const
  881. {
  882. Js::PropertyIdArray * auxArray = (Js::PropertyIdArray *)(m_bodyData.auxData + offset);
  883. Assert(offset + auxArray->GetDataSize() <= m_bodyData.auxDataCount);
  884. return auxArray;
  885. }
  886. Js::PropertyIdArray *
  887. JITTimeFunctionBody::GetFormalsPropIdArray() const
  888. {
  889. return (Js::PropertyIdArray *)m_bodyData.formalsPropIdArray;
  890. }
  891. bool
  892. JITTimeFunctionBody::InitializeStatementMap(Js::SmallSpanSequence * statementMap, ArenaAllocator* alloc) const
  893. {
  894. if (!m_bodyData.statementMap)
  895. {
  896. return false;
  897. }
  898. const uint statementsLength = m_bodyData.statementMap->statementLength;
  899. const uint offsetsLength = m_bodyData.statementMap->actualOffsetLength;
  900. statementMap->baseValue = m_bodyData.statementMap->baseValue;
  901. // TODO: (leish OOP JIT) using arena to prevent memory leak, fix to really implement GrowingUint32ArenaArray::Create()
  902. // or find other way to reuse like michhol's comments
  903. typedef JsUtil::GrowingArray<uint32, ArenaAllocator> GrowingUint32ArenaArray;
  904. if (statementsLength > 0)
  905. {
  906. // TODO: (michhol OOP JIT) should be able to directly use statementMap.statementBuffer
  907. statementMap->pStatementBuffer = (JsUtil::GrowingUint32HeapArray*)Anew(alloc, GrowingUint32ArenaArray, alloc, statementsLength);
  908. statementMap->pStatementBuffer->SetCount(statementsLength);
  909. js_memcpy_s(
  910. statementMap->pStatementBuffer->GetBuffer(),
  911. statementMap->pStatementBuffer->Count() * sizeof(uint32),
  912. m_bodyData.statementMap->statementBuffer,
  913. statementsLength * sizeof(uint32));
  914. }
  915. if (offsetsLength > 0)
  916. {
  917. statementMap->pActualOffsetList = (JsUtil::GrowingUint32HeapArray*)Anew(alloc, GrowingUint32ArenaArray, alloc, offsetsLength);
  918. statementMap->pActualOffsetList->SetCount(offsetsLength);
  919. js_memcpy_s(
  920. statementMap->pActualOffsetList->GetBuffer(),
  921. statementMap->pActualOffsetList->Count() * sizeof(uint32),
  922. m_bodyData.statementMap->actualOffsetList,
  923. offsetsLength * sizeof(uint32));
  924. }
  925. return true;
  926. }
  927. char16*
  928. JITTimeFunctionBody::GetDisplayName() const
  929. {
  930. return m_bodyData.displayName;
  931. }