Sym.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. 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. const Js::ArgSlot StackSym::InvalidSlot = (Js::ArgSlot)-1;
  7. ///----------------------------------------------------------------------------
  8. ///
  9. /// StackSym::New
  10. ///
  11. /// Creates a StackSym
  12. ///
  13. ///----------------------------------------------------------------------------
  14. StackSym *
  15. StackSym::New(SymID id, IRType type, Js::RegSlot byteCodeRegSlot, Func *func)
  16. {
  17. StackSym * stackSym;
  18. if (byteCodeRegSlot != Js::Constants::NoRegister)
  19. {
  20. stackSym = AnewZ(func->m_alloc, ByteCodeStackSym, byteCodeRegSlot, func);
  21. stackSym->m_hasByteCodeRegSlot = true;
  22. }
  23. else
  24. {
  25. stackSym = AnewZ(func->m_alloc, StackSym);
  26. }
  27. stackSym->m_id = id;
  28. stackSym->m_kind = SymKindStack;
  29. // Assume SingleDef until proven false.
  30. stackSym->m_isConst = false;
  31. stackSym->m_isIntConst = false;
  32. stackSym->m_isTaggableIntConst = false;
  33. stackSym->m_isSingleDef = true;
  34. stackSym->m_isEncodedConstant = false;
  35. stackSym->m_isFltConst = false;
  36. stackSym->m_isInt64Const = false;
  37. stackSym->m_isStrConst = false;
  38. stackSym->m_isStrEmpty = false;
  39. stackSym->m_allocated = false;
  40. stackSym->m_isTypeSpec = false;
  41. stackSym->m_isArgSlotSym = false;
  42. stackSym->m_isArgSlotRegSym = false;
  43. stackSym->m_isParamSym = false;
  44. stackSym->m_isImplicitParamSym = false;
  45. stackSym->m_isBailOutReferenced = false;
  46. stackSym->m_isArgCaptured = false;
  47. stackSym->m_requiresBailOnNotNumber = false;
  48. stackSym->m_isCatchObjectSym = false;
  49. stackSym->m_isClosureSym = false;
  50. stackSym->m_builtInIndex = Js::BuiltinFunction::None;
  51. stackSym->m_slotNum = StackSym::InvalidSlot;
  52. stackSym->m_type = type;
  53. stackSym->m_equivNext = stackSym;
  54. stackSym->m_objectInfo = nullptr;
  55. AssertMsg(func->m_symTable->Find(id) == nullptr, "Trying to add new symbol which already exists.");
  56. func->m_symTable->Add(stackSym);
  57. return stackSym;
  58. }
  59. ObjectSymInfo *
  60. ObjectSymInfo::New(Func * func)
  61. {
  62. ObjectSymInfo * objSymInfo = JitAnewZ(func->m_alloc, ObjectSymInfo);
  63. return objSymInfo;
  64. }
  65. ObjectSymInfo *
  66. ObjectSymInfo::New(StackSym * typeSym, Func * func)
  67. {
  68. ObjectSymInfo * objSymInfo = ObjectSymInfo::New(func);
  69. objSymInfo->m_typeSym = typeSym;
  70. return objSymInfo;
  71. }
  72. ObjectSymInfo *
  73. StackSym::EnsureObjectInfo(Func * func)
  74. {
  75. if (this->m_objectInfo == nullptr)
  76. {
  77. this->m_objectInfo = ObjectSymInfo::New(func);
  78. }
  79. return this->m_objectInfo;
  80. }
  81. ///----------------------------------------------------------------------------
  82. ///
  83. /// StackSym::New
  84. ///
  85. /// Creates a StackSym
  86. ///
  87. ///----------------------------------------------------------------------------
  88. StackSym *
  89. StackSym::New(Func *func)
  90. {
  91. return StackSym::New(func->m_symTable->NewID(), TyVar, Js::Constants::NoRegister, func);
  92. }
  93. StackSym *
  94. StackSym::New(IRType type, Func *func)
  95. {
  96. return StackSym::New(func->m_symTable->NewID(), type, Js::Constants::NoRegister, func);
  97. }
  98. StackSym *
  99. StackSym::NewImplicitParamSym(Js::ArgSlot paramSlotNum, Func * func)
  100. {
  101. return func->m_symTable->GetImplicitParam(paramSlotNum);
  102. }
  103. StackSym *
  104. StackSym::NewParamSlotSym(Js::ArgSlot paramSlotNum, Func * func)
  105. {
  106. return NewParamSlotSym(paramSlotNum, func, TyVar);
  107. }
  108. StackSym *
  109. StackSym::NewParamSlotSym(Js::ArgSlot paramSlotNum, Func * func, IRType type)
  110. {
  111. StackSym * stackSym = StackSym::New(type, func);
  112. stackSym->m_isParamSym = true;
  113. stackSym->m_slotNum = paramSlotNum;
  114. return stackSym;
  115. }
  116. // Represents a temporary sym which is a copy of an arg slot sym.
  117. StackSym *
  118. StackSym::NewArgSlotRegSym(Js::ArgSlot argSlotNum, Func * func, IRType type /* = TyVar */)
  119. {
  120. StackSym * stackSym = StackSym::New(type, func);
  121. stackSym->m_isArgSlotRegSym = true;
  122. stackSym->m_slotNum = argSlotNum;
  123. #if defined(_M_X64)
  124. stackSym->m_argPosition = 0;
  125. #endif
  126. return stackSym;
  127. }
  128. StackSym *
  129. StackSym::NewArgSlotSym(Js::ArgSlot argSlotNum, Func * func, IRType type /* = TyVar */)
  130. {
  131. StackSym * stackSym = StackSym::New(type, func);
  132. stackSym->m_isArgSlotSym = true;
  133. stackSym->m_slotNum = argSlotNum;
  134. #if defined(_M_X64)
  135. stackSym->m_argPosition = 0;
  136. #endif
  137. return stackSym;
  138. }
  139. bool
  140. StackSym::IsTempReg(Func *const func) const
  141. {
  142. return !HasByteCodeRegSlot() || GetByteCodeRegSlot() >= func->GetJITFunctionBody()->GetFirstTmpReg();
  143. }
  144. #if DBG
  145. void
  146. StackSym::VerifyConstFlags() const
  147. {
  148. if (m_isConst)
  149. {
  150. Assert(this->m_isSingleDef);
  151. Assert(this->m_instrDef);
  152. if (m_isIntConst)
  153. {
  154. Assert(!m_isFltConst);
  155. }
  156. else
  157. {
  158. Assert(!m_isTaggableIntConst);
  159. }
  160. }
  161. else
  162. {
  163. Assert(!m_isIntConst);
  164. Assert(!m_isTaggableIntConst);
  165. Assert(!m_isFltConst);
  166. }
  167. }
  168. #endif
  169. bool
  170. StackSym::IsConst() const
  171. {
  172. #if DBG
  173. VerifyConstFlags();
  174. #endif
  175. return m_isConst;
  176. }
  177. bool
  178. StackSym::IsIntConst() const
  179. {
  180. #if DBG
  181. VerifyConstFlags();
  182. #endif
  183. return m_isIntConst;
  184. }
  185. bool
  186. StackSym::IsInt64Const() const
  187. {
  188. #if DBG
  189. VerifyConstFlags();
  190. #endif
  191. return m_isInt64Const;
  192. }
  193. bool
  194. StackSym::IsTaggableIntConst() const
  195. {
  196. #if DBG
  197. VerifyConstFlags();
  198. #endif
  199. return m_isTaggableIntConst;
  200. }
  201. bool
  202. StackSym::IsFloatConst() const
  203. {
  204. #if DBG
  205. VerifyConstFlags();
  206. #endif
  207. return m_isFltConst;
  208. }
  209. bool
  210. StackSym::IsSimd128Const() const
  211. {
  212. #if DBG
  213. VerifyConstFlags();
  214. #endif
  215. return m_isSimd128Const;
  216. }
  217. void
  218. StackSym::SetIsConst()
  219. {
  220. Assert(this->m_isSingleDef);
  221. Assert(this->m_instrDef);
  222. IR::Opnd * src = this->m_instrDef->GetSrc1();
  223. Assert(src->IsImmediateOpnd() || src->IsFloatConstOpnd() || src->IsSimd128ConstOpnd());
  224. if (src->IsIntConstOpnd())
  225. {
  226. Assert(this->m_instrDef->m_opcode == Js::OpCode::Ld_I4 || this->m_instrDef->m_opcode == Js::OpCode::LdC_A_I4 || LowererMD::IsAssign(this->m_instrDef));
  227. this->SetIsIntConst(src->AsIntConstOpnd()->GetValue());
  228. }
  229. else if (src->IsInt64ConstOpnd())
  230. {
  231. Assert(this->m_instrDef->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(this->m_instrDef));
  232. this->SetIsInt64Const();
  233. }
  234. else if (src->IsFloatConstOpnd())
  235. {
  236. Assert(this->m_instrDef->m_opcode == Js::OpCode::LdC_A_R8);
  237. this->SetIsFloatConst();
  238. }
  239. else if (src->IsSimd128ConstOpnd()){
  240. Assert(this->m_instrDef->m_opcode == Js::OpCode::Simd128_LdC);
  241. this->SetIsSimd128Const();
  242. }
  243. else
  244. {
  245. Assert(this->m_instrDef->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(this->m_instrDef));
  246. Assert(src->IsAddrOpnd());
  247. IR::AddrOpnd * addrOpnd = src->AsAddrOpnd();
  248. this->m_isConst = true;
  249. if (addrOpnd->IsVar())
  250. {
  251. Js::Var var = addrOpnd->m_address;
  252. if (Js::TaggedInt::Is(var))
  253. {
  254. this->m_isIntConst = true;
  255. this->m_isTaggableIntConst = true;
  256. }
  257. else if (var)
  258. {
  259. #if !FLOATVAR
  260. if (JITManager::GetJITManager()->IsOOPJITEnabled())
  261. {
  262. if (addrOpnd->m_localAddress && Js::JavascriptNumber::Is(addrOpnd->m_localAddress) && Js::JavascriptNumber::IsInt32_NoChecks(addrOpnd->m_localAddress))
  263. {
  264. this->m_isIntConst = true;
  265. }
  266. }
  267. else
  268. #endif
  269. {
  270. if (Js::JavascriptNumber::Is(var) && Js::JavascriptNumber::IsInt32_NoChecks(var))
  271. {
  272. this->m_isIntConst = true;
  273. }
  274. }
  275. }
  276. }
  277. }
  278. }
  279. void
  280. StackSym::SetIsIntConst(IntConstType value)
  281. {
  282. Assert(this->m_isSingleDef);
  283. Assert(this->m_instrDef);
  284. this->m_isConst = true;
  285. this->m_isIntConst = true;
  286. this->m_isInt64Const = false;
  287. this->m_isTaggableIntConst = !Js::TaggedInt::IsOverflow(value);
  288. this->m_isFltConst = false;
  289. this->m_isStrConst = false;
  290. }
  291. void StackSym::SetIsInt64Const()
  292. {
  293. Assert(this->m_isSingleDef);
  294. Assert(this->m_instrDef);
  295. this->m_isConst = true;
  296. this->m_isInt64Const = true;
  297. this->m_isIntConst = false;
  298. this->m_isTaggableIntConst = false;
  299. this->m_isFltConst = false;
  300. this->m_isStrConst = false;
  301. }
  302. void
  303. StackSym::SetIsFloatConst()
  304. {
  305. Assert(this->m_isSingleDef);
  306. Assert(this->m_instrDef);
  307. this->m_isConst = true;
  308. this->m_isIntConst = false;
  309. this->m_isTaggableIntConst = false;
  310. this->m_isFltConst = true;
  311. this->m_isStrConst = false;
  312. }
  313. void
  314. StackSym::SetIsSimd128Const()
  315. {
  316. Assert(this->m_isSingleDef);
  317. Assert(this->m_instrDef);
  318. this->m_isConst = true;
  319. this->m_isIntConst = false;
  320. this->m_isTaggableIntConst = false;
  321. this->m_isFltConst = false;
  322. this->m_isSimd128Const = true;
  323. this->m_isStrConst = false;
  324. this->m_isNotNumber = true;
  325. }
  326. void
  327. StackSym::SetIsStrConst()
  328. {
  329. Assert(this->m_isSingleDef);
  330. Assert(this->m_instrDef);
  331. this->m_isConst = true;
  332. this->m_isIntConst = false;
  333. this->m_isTaggableIntConst = false;
  334. this->m_isFltConst = false;
  335. this->m_isSimd128Const = false;
  336. this->m_isStrConst = true;
  337. this->m_isNotNumber = true;
  338. }
  339. Js::RegSlot
  340. StackSym::GetByteCodeRegSlot() const
  341. {
  342. Assert(HasByteCodeRegSlot());
  343. return ((ByteCodeStackSym *)this)->byteCodeRegSlot;
  344. }
  345. Func *
  346. StackSym::GetByteCodeFunc() const
  347. {
  348. Assert(HasByteCodeRegSlot());
  349. return ((ByteCodeStackSym *)this)->byteCodeFunc;
  350. }
  351. void
  352. StackSym::IncrementArgSlotNum()
  353. {
  354. Assert(IsArgSlotSym());
  355. m_slotNum++;
  356. }
  357. void
  358. StackSym::DecrementArgSlotNum()
  359. {
  360. Assert(IsArgSlotSym());
  361. m_slotNum--;
  362. }
  363. void
  364. StackSym::FixupStackOffset(Func * currentFunc)
  365. {
  366. int offsetFixup = 0;
  367. Func * parentFunc = currentFunc->GetParentFunc();
  368. while (parentFunc)
  369. {
  370. if (parentFunc->callSiteToArgumentsOffsetFixupMap)
  371. {
  372. parentFunc->callSiteToArgumentsOffsetFixupMap->TryGetValue(currentFunc->callSiteIdInParentFunc, &offsetFixup);
  373. this->m_offset += offsetFixup * MachPtr;
  374. }
  375. parentFunc = parentFunc->GetParentFunc();
  376. currentFunc = currentFunc->GetParentFunc();
  377. offsetFixup = 0;
  378. }
  379. }
  380. ///----------------------------------------------------------------------------
  381. ///
  382. /// StackSym::FindOrCreate
  383. ///
  384. /// Look for a StackSym with the given ID. If not found, create it.
  385. ///
  386. ///----------------------------------------------------------------------------
  387. StackSym *
  388. StackSym::FindOrCreate(SymID id, Js::RegSlot byteCodeRegSlot, Func *func, IRType type)
  389. {
  390. StackSym * stackSym;
  391. stackSym = func->m_symTable->FindStackSym(id);
  392. if (stackSym)
  393. {
  394. Assert(!stackSym->HasByteCodeRegSlot() ||
  395. (stackSym->GetByteCodeRegSlot() == byteCodeRegSlot && stackSym->GetByteCodeFunc() == func));
  396. Assert(stackSym->GetType() == type);
  397. return stackSym;
  398. }
  399. return StackSym::New(id, type, byteCodeRegSlot, func);
  400. }
  401. StackSym *
  402. StackSym::CloneDef(Func *func)
  403. {
  404. Cloner * cloner = func->GetCloner();
  405. StackSym * newSym = nullptr;
  406. AssertMsg(cloner, "Use Func::BeginClone to initialize cloner");
  407. if (!this->m_isSingleDef)
  408. {
  409. return this;
  410. }
  411. switch (this->m_instrDef->m_opcode)
  412. {
  413. // Note: we were cloning single-def load constant instr's, but couldn't guarantee
  414. // that we were cloning all the uses.
  415. case Js::OpCode::ArgOut_A:
  416. case Js::OpCode::ArgOut_A_Dynamic:
  417. case Js::OpCode::ArgOut_A_InlineBuiltIn:
  418. case Js::OpCode::ArgOut_A_SpreadArg:
  419. case Js::OpCode::StartCall:
  420. case Js::OpCode::InlineeMetaArg:
  421. // Go ahead and clone: we need a single-def sym.
  422. // Arg/StartCall trees must be single-def.
  423. // Uses of int-const syms may need to find their defining instr's.
  424. break;
  425. default:
  426. return this;
  427. }
  428. if (cloner->symMap == nullptr)
  429. {
  430. cloner->symMap = HashTable<StackSym*>::New(cloner->alloc, 7);
  431. }
  432. else
  433. {
  434. StackSym **entry = cloner->symMap->Get(m_id);
  435. if (entry)
  436. {
  437. newSym = *entry;
  438. }
  439. }
  440. if (newSym == nullptr)
  441. {
  442. // NOTE: We don't care about the bytecode register information for cloned symbol
  443. // As those are the float sym that we will convert back to Var before jumping back
  444. // to the slow path's bailout. The bailout can just track the original symbol.
  445. newSym = StackSym::New(func);
  446. newSym->m_isConst = m_isConst;
  447. newSym->m_isIntConst = m_isIntConst;
  448. newSym->m_isTaggableIntConst = m_isTaggableIntConst;
  449. newSym->m_isArgSlotSym = m_isArgSlotSym;
  450. newSym->m_isArgSlotRegSym = m_isArgSlotRegSym;
  451. newSym->m_isParamSym = m_isParamSym;
  452. newSym->m_isImplicitParamSym = m_isImplicitParamSym;
  453. newSym->m_isArgCaptured = m_isArgCaptured;
  454. newSym->m_isBailOutReferenced = m_isBailOutReferenced;
  455. newSym->m_slotNum = m_slotNum;
  456. #if defined(_M_X64)
  457. newSym->m_argPosition = m_argPosition;
  458. #endif
  459. newSym->m_offset = m_offset;
  460. newSym->m_allocated = m_allocated;
  461. newSym->m_isInlinedArgSlot = m_isInlinedArgSlot;
  462. newSym->m_isCatchObjectSym = m_isCatchObjectSym;
  463. newSym->m_isClosureSym = m_isClosureSym;
  464. newSym->m_type = m_type;
  465. newSym->CopySymAttrs(this);
  466. // NOTE: It is not clear what the right thing to do is here...
  467. newSym->m_equivNext = newSym;
  468. cloner->symMap->FindOrInsert(newSym, m_id);
  469. }
  470. return newSym;
  471. }
  472. StackSym *
  473. StackSym::CloneUse(Func *func)
  474. {
  475. Cloner * cloner = func->GetCloner();
  476. StackSym ** newSym;
  477. AssertMsg(cloner, "Use Func::BeginClone to initialize cloner");
  478. if (cloner->symMap == nullptr)
  479. {
  480. return this;
  481. }
  482. newSym = cloner->symMap->Get(m_id);
  483. if (newSym == nullptr)
  484. {
  485. return this;
  486. }
  487. return *newSym;
  488. }
  489. void
  490. StackSym::CopySymAttrs(StackSym *symSrc)
  491. {
  492. m_isNotNumber = symSrc->m_isNotNumber;
  493. m_isSafeThis = symSrc->m_isSafeThis;
  494. m_builtInIndex = symSrc->m_builtInIndex;
  495. }
  496. // StackSym::GetIntConstValue
  497. int32
  498. StackSym::GetIntConstValue() const
  499. {
  500. Assert(this->IsIntConst());
  501. IR::Instr *defInstr = this->m_instrDef;
  502. IR::Opnd *src1 = defInstr->GetSrc1();
  503. if (src1->IsIntConstOpnd())
  504. {
  505. Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || defInstr->m_opcode == Js::OpCode::LdC_A_I4 || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
  506. return src1->AsIntConstOpnd()->AsInt32();
  507. }
  508. if (src1->IsAddrOpnd())
  509. {
  510. Assert(defInstr->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  511. IR::AddrOpnd *addr = src1->AsAddrOpnd();
  512. Assert(addr->IsVar());
  513. Js::Var var = src1->AsAddrOpnd()->m_address;
  514. if (Js::TaggedInt::Is(var))
  515. {
  516. return Js::TaggedInt::ToInt32(var);
  517. }
  518. int32 value = 0xCCCCCCCC;
  519. const bool isInt32 = Js::JavascriptNumber::TryGetInt32Value(Js::JavascriptNumber::GetValue(var), &value);
  520. Assert(isInt32);
  521. return value;
  522. }
  523. Assert(src1->IsRegOpnd());
  524. return src1->AsRegOpnd()->m_sym->GetIntConstValue();
  525. }
  526. Js::Var StackSym::GetFloatConstValueAsVar_PostGlobOpt() const
  527. {
  528. Assert(this->IsConst());
  529. IR::Instr *defInstr = this->m_instrDef;
  530. IR::Opnd *src1 = defInstr->GetSrc1();
  531. StackSym * stackSym = nullptr;
  532. if (src1->IsRegOpnd())
  533. {
  534. stackSym = src1->AsRegOpnd()->m_sym;
  535. Assert(!stackSym->m_isEncodedConstant);
  536. if (stackSym->m_isSingleDef)
  537. {
  538. //In ARM constant load is always legalized. Try to get the constant from src def
  539. defInstr = stackSym->m_instrDef;
  540. src1 = defInstr->GetSrc1();
  541. }
  542. }
  543. Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));
  544. IR::AddrOpnd *addrOpnd;
  545. if (src1->IsAddrOpnd())
  546. {
  547. Assert(defInstr->m_opcode == Js::OpCode::Ld_A);
  548. addrOpnd = src1->AsAddrOpnd();
  549. }
  550. else
  551. {
  552. Assert(src1->IsFloatConstOpnd());
  553. Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
  554. addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
  555. // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
  556. // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
  557. defInstr->ReplaceSrc1(addrOpnd);
  558. defInstr->m_opcode = Js::OpCode::Ld_A;
  559. }
  560. const Js::Var address = addrOpnd->m_address;
  561. Assert(Js::JavascriptNumber::Is(addrOpnd->m_localAddress? addrOpnd->m_localAddress: addrOpnd->m_address));
  562. return address;
  563. }
  564. void *StackSym::GetConstAddress(bool useLocal /*= false*/) const
  565. {
  566. Assert(this->IsConst());
  567. IR::Instr *defInstr = this->m_instrDef;
  568. IR::Opnd *src1 = defInstr->GetSrc1();
  569. StackSym * stackSym = nullptr;
  570. if (src1->IsRegOpnd())
  571. {
  572. stackSym = src1->AsRegOpnd()->m_sym;
  573. Assert(!stackSym->m_isEncodedConstant);
  574. if (stackSym->m_isSingleDef)
  575. {
  576. //In ARM constant load is always legalized. Try to get the constant from src def
  577. defInstr = stackSym->m_instrDef;
  578. src1 = defInstr->GetSrc1();
  579. }
  580. }
  581. Assert(src1->IsAddrOpnd());
  582. Assert(defInstr->m_opcode == Js::OpCode::Ld_A || defInstr->m_opcode == Js::OpCode::LdStr || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
  583. return useLocal ? src1->AsAddrOpnd()->m_localAddress : src1->AsAddrOpnd()->m_address;
  584. }
  585. intptr_t StackSym::GetLiteralConstValue_PostGlobOpt() const
  586. {
  587. Assert(this->IsConst());
  588. IR::Instr *defInstr = this->m_instrDef;
  589. IR::Opnd *src1 = defInstr->GetSrc1();
  590. StackSym * stackSym = nullptr;
  591. if (src1->IsRegOpnd())
  592. {
  593. stackSym = src1->AsRegOpnd()->m_sym;
  594. if (stackSym->m_isEncodedConstant)
  595. {
  596. Assert(!stackSym->m_isSingleDef);
  597. Assert(LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  598. return stackSym->constantValue;
  599. }
  600. if (stackSym->m_isSingleDef)
  601. {
  602. //In ARM constant load is always legalized. Try to get the constant from src def
  603. defInstr = stackSym->m_instrDef;
  604. src1 = defInstr->GetSrc1();
  605. }
  606. }
  607. if (src1->IsAddrOpnd())
  608. {
  609. Assert(defInstr->m_opcode == Js::OpCode::Ld_A || defInstr->m_opcode == Js::OpCode::LdStr || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
  610. return reinterpret_cast<intptr_t>(src1->AsAddrOpnd()->m_address);
  611. }
  612. if (src1->IsIntConstOpnd())
  613. {
  614. Assert(this->IsIntConst() || (stackSym && stackSym->IsIntConst()));
  615. if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
  616. {
  617. IR::AddrOpnd *const addrOpnd = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
  618. const Js::Var address = addrOpnd->m_address;
  619. // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
  620. // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
  621. defInstr->ReplaceSrc1(addrOpnd);
  622. defInstr->m_opcode = Js::OpCode::Ld_A;
  623. return reinterpret_cast<intptr_t>(address);
  624. }
  625. Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  626. return src1->AsIntConstOpnd()->GetValue();
  627. }
  628. if (src1->IsFloatConstOpnd())
  629. {
  630. Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));
  631. Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
  632. IR::AddrOpnd *const addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
  633. const Js::Var address = addrOpnd->m_address;
  634. // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
  635. // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
  636. defInstr->ReplaceSrc1(addrOpnd);
  637. defInstr->m_opcode = Js::OpCode::Ld_A;
  638. return reinterpret_cast<intptr_t>(address);
  639. }
  640. AssertMsg(UNREACHED, "Unknown const value");
  641. return 0;
  642. }
  643. IR::Opnd *
  644. StackSym::GetConstOpnd() const
  645. {
  646. Assert(IsConst());
  647. IR::Instr *defInstr = this->m_instrDef;
  648. IR::Opnd *src1 = defInstr->GetSrc1();
  649. if (!src1)
  650. {
  651. #if defined(_M_IX86) || defined(_M_X64)
  652. Assert(defInstr->m_opcode == Js::OpCode::MOVSD_ZERO);
  653. #else
  654. Assert(UNREACHED);
  655. #endif
  656. }
  657. else if (src1->IsIntConstOpnd())
  658. {
  659. Assert(this->IsIntConst());
  660. if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
  661. {
  662. src1 = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
  663. defInstr->ReplaceSrc1(src1);
  664. defInstr->m_opcode = Js::OpCode::Ld_A;
  665. }
  666. else
  667. {
  668. Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  669. }
  670. }
  671. else if (src1->IsInt64ConstOpnd())
  672. {
  673. Assert(this->m_isInt64Const);
  674. Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr));
  675. }
  676. else if (src1->IsFloatConstOpnd())
  677. {
  678. Assert(this->IsFloatConst());
  679. Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
  680. src1 = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
  681. defInstr->ReplaceSrc1(src1);
  682. defInstr->m_opcode = Js::OpCode::Ld_A;
  683. }
  684. else if (src1->IsFloat32ConstOpnd())
  685. {
  686. Assert(this->IsFloatConst());
  687. Assert(defInstr->m_opcode == Js::OpCode::LdC_F8_R8 || LowererMD::IsAssign(defInstr));
  688. }
  689. else if (src1->IsAddrOpnd())
  690. {
  691. Assert(defInstr->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  692. }
  693. else if (src1->IsMemRefOpnd())
  694. {
  695. Assert(this->IsFloatConst() || this->IsSimd128Const());
  696. }
  697. else
  698. {
  699. AssertMsg(UNREACHED, "Invalid const value");
  700. }
  701. return src1;
  702. }
  703. BailoutConstantValue StackSym::GetConstValueForBailout() const
  704. {
  705. Assert(this->IsConst());
  706. IR::Instr *defInstr = this->m_instrDef;
  707. IR::Opnd *src1 = defInstr->GetSrc1();
  708. return src1->GetConstValue();
  709. }
  710. StackSym *
  711. StackSym::GetFloat64EquivSym(Func *func)
  712. {
  713. return this->GetTypeEquivSym(TyFloat64, func);
  714. }
  715. StackSym *
  716. StackSym::GetInt32EquivSym(Func *func)
  717. {
  718. return this->GetTypeEquivSym(TyInt32, func);
  719. }
  720. StackSym *
  721. StackSym::GetVarEquivSym(Func *func)
  722. {
  723. return this->GetTypeEquivSym(TyVar, func);
  724. }
  725. StackSym *
  726. StackSym::GetVarEquivSym_NoCreate()
  727. {
  728. return this->GetTypeEquivSym_NoCreate(TyVar);
  729. }
  730. StackSym const *
  731. StackSym::GetVarEquivSym_NoCreate() const
  732. {
  733. return this->GetTypeEquivSym_NoCreate(TyVar);
  734. }
  735. StackSym *
  736. StackSym::GetTypeEquivSym(IRType type, Func *func)
  737. {
  738. StackSym *sym = this->GetTypeEquivSym_NoCreate(type);
  739. if (sym != nullptr)
  740. {
  741. return sym;
  742. }
  743. // Don't allocate if func wasn't passed in.
  744. if (func == nullptr)
  745. {
  746. return nullptr;
  747. }
  748. if (this->HasByteCodeRegSlot())
  749. {
  750. sym = StackSym::New(func->m_symTable->NewID(), type,
  751. this->GetByteCodeRegSlot(), this->GetByteCodeFunc());
  752. }
  753. else
  754. {
  755. sym = StackSym::New(type, func);
  756. }
  757. sym->m_equivNext = this->m_equivNext;
  758. this->m_equivNext = sym;
  759. if (type != TyVar)
  760. {
  761. sym->m_isTypeSpec = true;
  762. }
  763. return sym;
  764. }
  765. StackSym *
  766. StackSym::GetTypeEquivSym_NoCreate(IRType type)
  767. {
  768. return const_cast<StackSym*>(static_cast<const StackSym*>(this)->GetTypeEquivSym_NoCreate(type));
  769. }
  770. StackSym const *
  771. StackSym::GetTypeEquivSym_NoCreate(IRType type) const
  772. {
  773. Assert(this->m_type != type);
  774. StackSym *sym = this->m_equivNext;
  775. int i = 1;
  776. while (sym != this)
  777. {
  778. Assert(i <= 5); // circular of at most 6 syms : var, f64, i32, simd128I4, simd128F4, simd128D2
  779. if (sym->m_type == type)
  780. {
  781. return sym;
  782. }
  783. sym = sym->m_equivNext;
  784. i++;
  785. }
  786. return nullptr;
  787. }
  788. StackSym *StackSym::GetVarEquivStackSym_NoCreate(Sym *const sym)
  789. {
  790. return const_cast<StackSym*>(GetVarEquivStackSym_NoCreate((Sym const * const)sym));
  791. }
  792. StackSym const *StackSym::GetVarEquivStackSym_NoCreate(Sym const * const sym)
  793. {
  794. Assert(sym);
  795. if(!sym->IsStackSym())
  796. {
  797. return nullptr;
  798. }
  799. StackSym const *stackSym = sym->AsStackSym();
  800. if(stackSym->IsTypeSpec())
  801. {
  802. stackSym = stackSym->GetVarEquivSym_NoCreate();
  803. }
  804. return stackSym;
  805. }
  806. StackSym *StackSym::EnsureAuxSlotPtrSym(Func * func)
  807. {
  808. Assert(HasObjectInfo());
  809. StackSym * auxSlotPtrSym = GetObjectInfo()->m_auxSlotPtrSym;
  810. if (auxSlotPtrSym == nullptr)
  811. {
  812. auxSlotPtrSym = GetObjectInfo()->m_auxSlotPtrSym = StackSym::New(func);
  813. }
  814. return auxSlotPtrSym;
  815. }
  816. ///----------------------------------------------------------------------------
  817. ///
  818. /// PropertySym::New
  819. ///
  820. /// Creates a PropertySym
  821. ///
  822. ///----------------------------------------------------------------------------
  823. PropertySym *
  824. PropertySym::New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
  825. {
  826. StackSym * stackSym;
  827. stackSym = func->m_symTable->FindStackSym(stackSymID);
  828. AssertMsg(stackSym != nullptr, "Adding propertySym to non-existing stackSym... Can this happen??");
  829. return PropertySym::New(stackSym, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
  830. }
  831. PropertySym *
  832. PropertySym::New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
  833. {
  834. PropertySym * propertySym;
  835. propertySym = JitAnewZ(func->m_alloc, PropertySym);
  836. propertySym->m_func = func;
  837. propertySym->m_id = func->m_symTable->NewID();
  838. propertySym->m_kind = SymKindProperty;
  839. propertySym->m_propertyId = propertyId;
  840. propertyIdIndex = (uint)-1;
  841. inlineCacheIndex = (uint)-1;
  842. propertySym->m_propertyIdIndex = propertyIdIndex;
  843. propertySym->m_inlineCacheIndex = inlineCacheIndex;
  844. Assert(propertyIdIndex == (uint)-1 || inlineCacheIndex == (uint)-1);
  845. propertySym->m_loadInlineCacheIndex = (uint)-1;
  846. propertySym->m_loadInlineCacheFunc = nullptr;
  847. propertySym->m_fieldKind = fieldKind;
  848. propertySym->m_stackSym = stackSym;
  849. propertySym->m_propertyEquivSet = nullptr;
  850. // Add to list
  851. func->m_symTable->Add(propertySym);
  852. // Keep track of all the property we use from this sym so we can invalidate
  853. // the value in glob opt
  854. ObjectSymInfo * objectSymInfo = stackSym->EnsureObjectInfo(func);
  855. propertySym->m_nextInStackSymList = objectSymInfo->m_propertySymList;
  856. objectSymInfo->m_propertySymList = propertySym;
  857. return propertySym;
  858. }
  859. ///----------------------------------------------------------------------------
  860. ///
  861. /// PropertySym::FindOrCreate
  862. ///
  863. /// Look for a PropertySym with the given ID/propertyId.
  864. ///
  865. ///----------------------------------------------------------------------------
  866. PropertySym *
  867. PropertySym::Find(SymID stackSymID, int32 propertyId, Func *func)
  868. {
  869. return func->m_symTable->FindPropertySym(stackSymID, propertyId);
  870. }
  871. ///----------------------------------------------------------------------------
  872. ///
  873. /// PropertySym::FindOrCreate
  874. ///
  875. /// Look for a PropertySym with the given ID/propertyId. If not found,
  876. /// create it.
  877. ///
  878. ///----------------------------------------------------------------------------
  879. PropertySym *
  880. PropertySym::FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
  881. {
  882. PropertySym * propertySym;
  883. propertySym = Find(stackSymID, propertyId, func);
  884. if (propertySym)
  885. {
  886. return propertySym;
  887. }
  888. return PropertySym::New(stackSymID, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
  889. }
  890. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  891. ///----------------------------------------------------------------------------
  892. ///
  893. /// Sym::Dump
  894. ///
  895. ///----------------------------------------------------------------------------
  896. void
  897. Sym::Dump(IRDumpFlags flags, const ValueType valueType) const
  898. {
  899. bool const AsmDumpMode = flags & IRDumpFlags_AsmDumpMode;
  900. bool const SimpleForm = !!(flags & IRDumpFlags_SimpleForm);
  901. if (AsmDumpMode)
  902. {
  903. if (this->IsStackSym() && this->AsStackSym()->IsArgSlotSym())
  904. {
  905. Output::Print(_u("arg "));
  906. }
  907. else if (this->IsStackSym() && this->AsStackSym()->IsParamSlotSym())
  908. {
  909. Output::Print(_u("param "));
  910. }
  911. }
  912. else if (this->IsStackSym())
  913. {
  914. StackSym const *stackSym = this->AsStackSym();
  915. if (stackSym->IsArgSlotSym())
  916. {
  917. if (stackSym->m_isInlinedArgSlot)
  918. {
  919. Output::Print(_u("iarg%d"), stackSym->GetArgSlotNum());
  920. }
  921. else
  922. {
  923. Output::Print(_u("arg%d"), stackSym->GetArgSlotNum());
  924. }
  925. Output::Print(_u("(s%d)"), m_id);
  926. }
  927. else if (stackSym->IsParamSlotSym())
  928. {
  929. if (stackSym->IsImplicitParamSym())
  930. {
  931. switch (stackSym->GetParamSlotNum())
  932. {
  933. case 1:
  934. Output::Print(_u("callInfo"));
  935. break;
  936. case 2:
  937. Output::Print(_u("funcInfo"));
  938. break;
  939. case 3:
  940. Output::Print(_u("genObj"));
  941. break;
  942. case 4:
  943. Output::Print(_u("genFrame"));
  944. break;
  945. default:
  946. Output::Print(_u("implPrm%d"), stackSym->GetParamSlotNum());
  947. }
  948. }
  949. else
  950. {
  951. Output::Print(_u("prm%d"), stackSym->GetParamSlotNum());
  952. }
  953. }
  954. else
  955. {
  956. Output::Print(_u("s%d"), m_id);
  957. if (Js::Configuration::Global.flags.Debug && stackSym->HasByteCodeRegSlot())
  958. {
  959. if (!JITManager::GetJITManager()->IsOOPJITEnabled())
  960. {
  961. Js::FunctionBody* functionBody = (Js::FunctionBody*)stackSym->GetByteCodeFunc()->GetJITFunctionBody()->GetAddr();
  962. if (functionBody->GetPropertyIdOnRegSlotsContainer())
  963. {
  964. if (functionBody->IsNonTempLocalVar(stackSym->GetByteCodeRegSlot()))
  965. {
  966. uint index = stackSym->GetByteCodeRegSlot() - stackSym->GetByteCodeFunc()->GetJITFunctionBody()->GetConstCount();
  967. Js::PropertyId propertyId = functionBody->GetPropertyIdOnRegSlotsContainer()->propertyIdsForRegSlots[index];
  968. Output::Print(_u("(%s)"), stackSym->GetByteCodeFunc()->GetInProcThreadContext()->GetPropertyRecord(propertyId)->GetBuffer());
  969. }
  970. }
  971. }
  972. }
  973. if (stackSym->IsVar())
  974. {
  975. if (stackSym->HasObjectTypeSym() && !SimpleForm)
  976. {
  977. Output::Print(_u("<s%d>"), stackSym->GetObjectTypeSym()->m_id);
  978. }
  979. }
  980. else
  981. {
  982. StackSym const *varSym = stackSym->GetVarEquivSym_NoCreate();
  983. if (varSym)
  984. {
  985. Output::Print(_u("(s%d)"), varSym->m_id);
  986. }
  987. }
  988. if (!SimpleForm)
  989. {
  990. if (stackSym->m_builtInIndex != Js::BuiltinFunction::None)
  991. {
  992. Output::Print(_u("[ffunc]"));
  993. }
  994. }
  995. IR::Opnd::DumpValueType(valueType);
  996. }
  997. }
  998. else if (this->IsPropertySym())
  999. {
  1000. PropertySym const *propertySym = this->AsPropertySym();
  1001. if (!SimpleForm)
  1002. {
  1003. Output::Print(_u("s%d("), m_id);
  1004. }
  1005. switch (propertySym->m_fieldKind)
  1006. {
  1007. case PropertyKindData:
  1008. propertySym->m_stackSym->Dump(flags, valueType);
  1009. if (JITManager::GetJITManager()->IsOOPJITEnabled())
  1010. {
  1011. Output::Print(_u("->#%d"), propertySym->m_propertyId);
  1012. }
  1013. else
  1014. {
  1015. Js::PropertyRecord const* fieldName = propertySym->m_func->GetInProcThreadContext()->GetPropertyRecord(propertySym->m_propertyId);
  1016. Output::Print(_u("->%s"), fieldName->GetBuffer());
  1017. }
  1018. break;
  1019. case PropertyKindSlots:
  1020. case PropertyKindSlotArray:
  1021. propertySym->m_stackSym->Dump(flags, valueType);
  1022. Output::Print(_u("[%d]"), propertySym->m_propertyId);
  1023. break;
  1024. case PropertyKindLocalSlots:
  1025. propertySym->m_stackSym->Dump(flags, valueType);
  1026. Output::Print(_u("l[%d]"), propertySym->m_propertyId);
  1027. break;
  1028. default:
  1029. AssertMsg(0, "Unknown field kind");
  1030. break;
  1031. }
  1032. if (!SimpleForm)
  1033. {
  1034. Output::Print(_u(")"));
  1035. }
  1036. }
  1037. }
  1038. void
  1039. Sym::Dump(const ValueType valueType) const
  1040. {
  1041. this->Dump(IRDumpFlags_None, valueType);
  1042. }
  1043. void
  1044. Sym::DumpSimple() const
  1045. {
  1046. this->Dump(IRDumpFlags_SimpleForm);
  1047. }
  1048. #endif // DBG_DUMP