JITTimeFunctionBody.cpp 34 KB

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