Sym.cpp 33 KB

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