Sym.cpp 30 KB

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