Sym.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  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. }
  290. void StackSym::SetIsInt64Const()
  291. {
  292. Assert(this->m_isSingleDef);
  293. Assert(this->m_instrDef);
  294. this->m_isConst = true;
  295. this->m_isInt64Const = true;
  296. this->m_isIntConst = false;
  297. this->m_isTaggableIntConst = false;
  298. this->m_isFltConst = false;
  299. }
  300. void
  301. StackSym::SetIsFloatConst()
  302. {
  303. Assert(this->m_isSingleDef);
  304. Assert(this->m_instrDef);
  305. this->m_isConst = true;
  306. this->m_isIntConst = false;
  307. this->m_isTaggableIntConst = false;
  308. this->m_isFltConst = true;
  309. }
  310. void
  311. StackSym::SetIsSimd128Const()
  312. {
  313. Assert(this->m_isSingleDef);
  314. Assert(this->m_instrDef);
  315. this->m_isConst = true;
  316. this->m_isIntConst = false;
  317. this->m_isTaggableIntConst = false;
  318. this->m_isFltConst = false;
  319. this->m_isSimd128Const = true;
  320. }
  321. Js::RegSlot
  322. StackSym::GetByteCodeRegSlot() const
  323. {
  324. Assert(HasByteCodeRegSlot());
  325. return ((ByteCodeStackSym *)this)->byteCodeRegSlot;
  326. }
  327. Func *
  328. StackSym::GetByteCodeFunc() const
  329. {
  330. Assert(HasByteCodeRegSlot());
  331. return ((ByteCodeStackSym *)this)->byteCodeFunc;
  332. }
  333. void
  334. StackSym::IncrementArgSlotNum()
  335. {
  336. Assert(IsArgSlotSym());
  337. m_slotNum++;
  338. }
  339. void
  340. StackSym::DecrementArgSlotNum()
  341. {
  342. Assert(IsArgSlotSym());
  343. m_slotNum--;
  344. }
  345. void
  346. StackSym::FixupStackOffset(Func * currentFunc)
  347. {
  348. int offsetFixup = 0;
  349. Func * parentFunc = currentFunc->GetParentFunc();
  350. while (parentFunc)
  351. {
  352. if (parentFunc->callSiteToArgumentsOffsetFixupMap)
  353. {
  354. parentFunc->callSiteToArgumentsOffsetFixupMap->TryGetValue(currentFunc->callSiteIdInParentFunc, &offsetFixup);
  355. this->m_offset += offsetFixup * MachPtr;
  356. }
  357. parentFunc = parentFunc->GetParentFunc();
  358. currentFunc = currentFunc->GetParentFunc();
  359. offsetFixup = 0;
  360. }
  361. }
  362. ///----------------------------------------------------------------------------
  363. ///
  364. /// StackSym::FindOrCreate
  365. ///
  366. /// Look for a StackSym with the given ID. If not found, create it.
  367. ///
  368. ///----------------------------------------------------------------------------
  369. StackSym *
  370. StackSym::FindOrCreate(SymID id, Js::RegSlot byteCodeRegSlot, Func *func, IRType type)
  371. {
  372. StackSym * stackSym;
  373. stackSym = func->m_symTable->FindStackSym(id);
  374. if (stackSym)
  375. {
  376. Assert(!stackSym->HasByteCodeRegSlot() ||
  377. (stackSym->GetByteCodeRegSlot() == byteCodeRegSlot && stackSym->GetByteCodeFunc() == func));
  378. Assert(stackSym->GetType() == type);
  379. return stackSym;
  380. }
  381. return StackSym::New(id, type, byteCodeRegSlot, func);
  382. }
  383. StackSym *
  384. StackSym::CloneDef(Func *func)
  385. {
  386. Cloner * cloner = func->GetCloner();
  387. StackSym * newSym = nullptr;
  388. AssertMsg(cloner, "Use Func::BeginClone to initialize cloner");
  389. if (!this->m_isSingleDef)
  390. {
  391. return this;
  392. }
  393. switch (this->m_instrDef->m_opcode)
  394. {
  395. // Note: we were cloning single-def load constant instr's, but couldn't guarantee
  396. // that we were cloning all the uses.
  397. case Js::OpCode::ArgOut_A:
  398. case Js::OpCode::ArgOut_A_Dynamic:
  399. case Js::OpCode::ArgOut_A_InlineBuiltIn:
  400. case Js::OpCode::ArgOut_A_SpreadArg:
  401. case Js::OpCode::StartCall:
  402. case Js::OpCode::InlineeMetaArg:
  403. // Go ahead and clone: we need a single-def sym.
  404. // Arg/StartCall trees must be single-def.
  405. // Uses of int-const syms may need to find their defining instr's.
  406. break;
  407. default:
  408. return this;
  409. }
  410. if (cloner->symMap == nullptr)
  411. {
  412. cloner->symMap = HashTable<StackSym*>::New(cloner->alloc, 7);
  413. }
  414. else
  415. {
  416. StackSym **entry = cloner->symMap->Get(m_id);
  417. if (entry)
  418. {
  419. newSym = *entry;
  420. }
  421. }
  422. if (newSym == nullptr)
  423. {
  424. // NOTE: We don't care about the bytecode register information for cloned symbol
  425. // As those are the float sym that we will convert back to Var before jumping back
  426. // to the slow path's bailout. The bailout can just track the original symbol.
  427. newSym = StackSym::New(func);
  428. newSym->m_isConst = m_isConst;
  429. newSym->m_isIntConst = m_isIntConst;
  430. newSym->m_isTaggableIntConst = m_isTaggableIntConst;
  431. newSym->m_isArgSlotSym = m_isArgSlotSym;
  432. newSym->m_isArgSlotRegSym = m_isArgSlotRegSym;
  433. newSym->m_isParamSym = m_isParamSym;
  434. newSym->m_isImplicitParamSym = m_isImplicitParamSym;
  435. newSym->m_isArgCaptured = m_isArgCaptured;
  436. newSym->m_isBailOutReferenced = m_isBailOutReferenced;
  437. newSym->m_slotNum = m_slotNum;
  438. #if defined(_M_X64)
  439. newSym->m_argPosition = m_argPosition;
  440. #endif
  441. newSym->m_offset = m_offset;
  442. newSym->m_allocated = m_allocated;
  443. newSym->m_isInlinedArgSlot = m_isInlinedArgSlot;
  444. newSym->m_isCatchObjectSym = m_isCatchObjectSym;
  445. newSym->m_isClosureSym = m_isClosureSym;
  446. newSym->m_type = m_type;
  447. newSym->CopySymAttrs(this);
  448. // NOTE: It is not clear what the right thing to do is here...
  449. newSym->m_equivNext = newSym;
  450. cloner->symMap->FindOrInsert(newSym, m_id);
  451. }
  452. return newSym;
  453. }
  454. StackSym *
  455. StackSym::CloneUse(Func *func)
  456. {
  457. Cloner * cloner = func->GetCloner();
  458. StackSym ** newSym;
  459. AssertMsg(cloner, "Use Func::BeginClone to initialize cloner");
  460. if (cloner->symMap == nullptr)
  461. {
  462. return this;
  463. }
  464. newSym = cloner->symMap->Get(m_id);
  465. if (newSym == nullptr)
  466. {
  467. return this;
  468. }
  469. return *newSym;
  470. }
  471. void
  472. StackSym::CopySymAttrs(StackSym *symSrc)
  473. {
  474. m_isNotInt = symSrc->m_isNotInt;
  475. m_isSafeThis = symSrc->m_isSafeThis;
  476. m_builtInIndex = symSrc->m_builtInIndex;
  477. }
  478. // StackSym::GetIntConstValue
  479. int32
  480. StackSym::GetIntConstValue() const
  481. {
  482. Assert(this->IsIntConst());
  483. IR::Instr *defInstr = this->m_instrDef;
  484. IR::Opnd *src1 = defInstr->GetSrc1();
  485. if (src1->IsIntConstOpnd())
  486. {
  487. 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));
  488. return src1->AsIntConstOpnd()->AsInt32();
  489. }
  490. if (src1->IsAddrOpnd())
  491. {
  492. 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);
  493. IR::AddrOpnd *addr = src1->AsAddrOpnd();
  494. Assert(addr->IsVar());
  495. Js::Var var = src1->AsAddrOpnd()->m_address;
  496. if (Js::TaggedInt::Is(var))
  497. {
  498. return Js::TaggedInt::ToInt32(var);
  499. }
  500. int32 value;
  501. const bool isInt32 = Js::JavascriptNumber::TryGetInt32Value(Js::JavascriptNumber::GetValue(var), &value);
  502. Assert(isInt32);
  503. return value;
  504. }
  505. Assert(src1->IsRegOpnd());
  506. return src1->AsRegOpnd()->m_sym->GetIntConstValue();
  507. }
  508. Js::Var StackSym::GetFloatConstValueAsVar_PostGlobOpt() const
  509. {
  510. Assert(this->IsConst());
  511. IR::Instr *defInstr = this->m_instrDef;
  512. IR::Opnd *src1 = defInstr->GetSrc1();
  513. StackSym * stackSym = nullptr;
  514. if (src1->IsRegOpnd())
  515. {
  516. stackSym = src1->AsRegOpnd()->m_sym;
  517. Assert(!stackSym->m_isEncodedConstant);
  518. if (stackSym->m_isSingleDef)
  519. {
  520. //In ARM constant load is always legalized. Try to get the constant from src def
  521. defInstr = stackSym->m_instrDef;
  522. src1 = defInstr->GetSrc1();
  523. }
  524. }
  525. Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));
  526. IR::AddrOpnd *addrOpnd;
  527. if (src1->IsAddrOpnd())
  528. {
  529. Assert(defInstr->m_opcode == Js::OpCode::Ld_A);
  530. addrOpnd = src1->AsAddrOpnd();
  531. }
  532. else
  533. {
  534. Assert(src1->IsFloatConstOpnd());
  535. Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
  536. addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
  537. // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
  538. // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
  539. defInstr->ReplaceSrc1(addrOpnd);
  540. defInstr->m_opcode = Js::OpCode::Ld_A;
  541. }
  542. const Js::Var address = addrOpnd->m_address;
  543. Assert(Js::JavascriptNumber::Is(addrOpnd->m_localAddress? addrOpnd->m_localAddress: addrOpnd->m_address));
  544. return address;
  545. }
  546. void *StackSym::GetConstAddress(bool useLocal /*= false*/) const
  547. {
  548. Assert(this->IsConst());
  549. IR::Instr *defInstr = this->m_instrDef;
  550. IR::Opnd *src1 = defInstr->GetSrc1();
  551. StackSym * stackSym = nullptr;
  552. if (src1->IsRegOpnd())
  553. {
  554. stackSym = src1->AsRegOpnd()->m_sym;
  555. Assert(!stackSym->m_isEncodedConstant);
  556. if (stackSym->m_isSingleDef)
  557. {
  558. //In ARM constant load is always legalized. Try to get the constant from src def
  559. defInstr = stackSym->m_instrDef;
  560. src1 = defInstr->GetSrc1();
  561. }
  562. }
  563. Assert(src1->IsAddrOpnd());
  564. 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));
  565. return useLocal ? src1->AsAddrOpnd()->m_localAddress : src1->AsAddrOpnd()->m_address;
  566. }
  567. intptr_t StackSym::GetLiteralConstValue_PostGlobOpt() const
  568. {
  569. Assert(this->IsConst());
  570. IR::Instr *defInstr = this->m_instrDef;
  571. IR::Opnd *src1 = defInstr->GetSrc1();
  572. StackSym * stackSym = nullptr;
  573. if (src1->IsRegOpnd())
  574. {
  575. stackSym = src1->AsRegOpnd()->m_sym;
  576. if (stackSym->m_isEncodedConstant)
  577. {
  578. Assert(!stackSym->m_isSingleDef);
  579. Assert(LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  580. return stackSym->constantValue;
  581. }
  582. if (stackSym->m_isSingleDef)
  583. {
  584. //In ARM constant load is always legalized. Try to get the constant from src def
  585. defInstr = stackSym->m_instrDef;
  586. src1 = defInstr->GetSrc1();
  587. }
  588. }
  589. if (src1->IsAddrOpnd())
  590. {
  591. 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));
  592. return reinterpret_cast<intptr_t>(src1->AsAddrOpnd()->m_address);
  593. }
  594. if (src1->IsIntConstOpnd())
  595. {
  596. Assert(this->IsIntConst() || (stackSym && stackSym->IsIntConst()));
  597. if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
  598. {
  599. IR::AddrOpnd *const addrOpnd = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
  600. const Js::Var address = addrOpnd->m_address;
  601. // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
  602. // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
  603. defInstr->ReplaceSrc1(addrOpnd);
  604. defInstr->m_opcode = Js::OpCode::Ld_A;
  605. return reinterpret_cast<intptr_t>(address);
  606. }
  607. Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  608. return src1->AsIntConstOpnd()->GetValue();
  609. }
  610. if (src1->IsFloatConstOpnd())
  611. {
  612. Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));
  613. Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
  614. IR::AddrOpnd *const addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
  615. const Js::Var address = addrOpnd->m_address;
  616. // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
  617. // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
  618. defInstr->ReplaceSrc1(addrOpnd);
  619. defInstr->m_opcode = Js::OpCode::Ld_A;
  620. return reinterpret_cast<intptr_t>(address);
  621. }
  622. AssertMsg(UNREACHED, "Unknown const value");
  623. return 0;
  624. }
  625. IR::Opnd *
  626. StackSym::GetConstOpnd() const
  627. {
  628. Assert(IsConst());
  629. IR::Instr *defInstr = this->m_instrDef;
  630. IR::Opnd *src1 = defInstr->GetSrc1();
  631. if (!src1)
  632. {
  633. #if defined(_M_IX86) || defined(_M_X64)
  634. Assert(defInstr->m_opcode == Js::OpCode::MOVSD_ZERO);
  635. #else
  636. Assert(UNREACHED);
  637. #endif
  638. }
  639. else if (src1->IsIntConstOpnd())
  640. {
  641. Assert(this->IsIntConst());
  642. if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
  643. {
  644. src1 = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
  645. defInstr->ReplaceSrc1(src1);
  646. defInstr->m_opcode = Js::OpCode::Ld_A;
  647. }
  648. else
  649. {
  650. Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  651. }
  652. }
  653. else if (src1->IsInt64ConstOpnd())
  654. {
  655. Assert(this->m_isInt64Const);
  656. Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr));
  657. }
  658. else if (src1->IsFloatConstOpnd())
  659. {
  660. Assert(this->IsFloatConst());
  661. Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
  662. src1 = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
  663. defInstr->ReplaceSrc1(src1);
  664. defInstr->m_opcode = Js::OpCode::Ld_A;
  665. }
  666. else if (src1->IsAddrOpnd())
  667. {
  668. Assert(defInstr->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
  669. }
  670. else if (src1->IsMemRefOpnd())
  671. {
  672. Assert(this->IsFloatConst() || this->IsSimd128Const());
  673. }
  674. else
  675. {
  676. AssertMsg(UNREACHED, "Invalid const value");
  677. }
  678. return src1;
  679. }
  680. BailoutConstantValue StackSym::GetConstValueForBailout() const
  681. {
  682. Assert(this->IsConst());
  683. IR::Instr *defInstr = this->m_instrDef;
  684. IR::Opnd *src1 = defInstr->GetSrc1();
  685. return src1->GetConstValue();
  686. }
  687. // SIMD_JS
  688. StackSym *
  689. StackSym::GetSimd128EquivSym(IRType type, Func *func)
  690. {
  691. switch (type)
  692. {
  693. case TySimd128F4:
  694. return this->GetSimd128F4EquivSym(func);
  695. break;
  696. case TySimd128I4:
  697. return this->GetSimd128I4EquivSym(func);
  698. break;
  699. case TySimd128I16:
  700. return this->GetSimd128I16EquivSym(func);
  701. break;
  702. case TySimd128D2:
  703. return this->GetSimd128D2EquivSym(func);
  704. break;
  705. default:
  706. Assert(UNREACHED);
  707. return nullptr;
  708. }
  709. }
  710. StackSym *
  711. StackSym::GetSimd128F4EquivSym(Func *func)
  712. {
  713. return this->GetTypeEquivSym(TySimd128F4, func);
  714. }
  715. StackSym *
  716. StackSym::GetSimd128I4EquivSym(Func *func)
  717. {
  718. return this->GetTypeEquivSym(TySimd128I4, func);
  719. }
  720. StackSym *
  721. StackSym::GetSimd128I16EquivSym(Func *func)
  722. {
  723. return this->GetTypeEquivSym(TySimd128I16, func);
  724. }
  725. StackSym *
  726. StackSym::GetSimd128D2EquivSym(Func *func)
  727. {
  728. return this->GetTypeEquivSym(TySimd128D2, func);
  729. }
  730. StackSym *
  731. StackSym::GetFloat64EquivSym(Func *func)
  732. {
  733. return this->GetTypeEquivSym(TyFloat64, func);
  734. }
  735. StackSym *
  736. StackSym::GetInt32EquivSym(Func *func)
  737. {
  738. return this->GetTypeEquivSym(TyInt32, func);
  739. }
  740. StackSym *
  741. StackSym::GetVarEquivSym(Func *func)
  742. {
  743. return this->GetTypeEquivSym(TyVar, func);
  744. }
  745. StackSym *
  746. StackSym::GetVarEquivSym_NoCreate()
  747. {
  748. return this->GetTypeEquivSym_NoCreate(TyVar);
  749. }
  750. StackSym const *
  751. StackSym::GetVarEquivSym_NoCreate() const
  752. {
  753. return this->GetTypeEquivSym_NoCreate(TyVar);
  754. }
  755. StackSym *
  756. StackSym::GetTypeEquivSym(IRType type, Func *func)
  757. {
  758. StackSym *sym = this->GetTypeEquivSym_NoCreate(type);
  759. if (sym != nullptr)
  760. {
  761. return sym;
  762. }
  763. // Don't allocate if func wasn't passed in.
  764. if (func == nullptr)
  765. {
  766. return nullptr;
  767. }
  768. if (this->HasByteCodeRegSlot())
  769. {
  770. sym = StackSym::New(func->m_symTable->NewID(), type,
  771. this->GetByteCodeRegSlot(), this->GetByteCodeFunc());
  772. }
  773. else
  774. {
  775. sym = StackSym::New(type, func);
  776. }
  777. sym->m_equivNext = this->m_equivNext;
  778. this->m_equivNext = sym;
  779. if (type != TyVar)
  780. {
  781. sym->m_isTypeSpec = true;
  782. }
  783. return sym;
  784. }
  785. StackSym *
  786. StackSym::GetTypeEquivSym_NoCreate(IRType type)
  787. {
  788. return const_cast<StackSym*>(static_cast<const StackSym*>(this)->GetTypeEquivSym_NoCreate(type));
  789. }
  790. StackSym const *
  791. StackSym::GetTypeEquivSym_NoCreate(IRType type) const
  792. {
  793. Assert(this->m_type != type);
  794. StackSym *sym = this->m_equivNext;
  795. int i = 1;
  796. while (sym != this)
  797. {
  798. Assert(i <= 5); // circular of at most 6 syms : var, f64, i32, simd128I4, simd128F4, simd128D2
  799. if (sym->m_type == type)
  800. {
  801. return sym;
  802. }
  803. sym = sym->m_equivNext;
  804. i++;
  805. }
  806. return nullptr;
  807. }
  808. StackSym *StackSym::GetVarEquivStackSym_NoCreate(Sym *const sym)
  809. {
  810. return const_cast<StackSym*>(GetVarEquivStackSym_NoCreate((Sym const * const)sym));
  811. }
  812. StackSym const *StackSym::GetVarEquivStackSym_NoCreate(Sym const * const sym)
  813. {
  814. Assert(sym);
  815. if(!sym->IsStackSym())
  816. {
  817. return nullptr;
  818. }
  819. StackSym const *stackSym = sym->AsStackSym();
  820. if(stackSym->IsTypeSpec())
  821. {
  822. stackSym = stackSym->GetVarEquivSym_NoCreate();
  823. }
  824. return stackSym;
  825. }
  826. ///----------------------------------------------------------------------------
  827. ///
  828. /// PropertySym::New
  829. ///
  830. /// Creates a PropertySym
  831. ///
  832. ///----------------------------------------------------------------------------
  833. PropertySym *
  834. PropertySym::New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
  835. {
  836. StackSym * stackSym;
  837. stackSym = func->m_symTable->FindStackSym(stackSymID);
  838. AssertMsg(stackSym != nullptr, "Adding propertySym to non-existing stackSym... Can this happen??");
  839. return PropertySym::New(stackSym, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
  840. }
  841. PropertySym *
  842. PropertySym::New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
  843. {
  844. PropertySym * propertySym;
  845. propertySym = JitAnewZ(func->m_alloc, PropertySym);
  846. propertySym->m_func = func;
  847. propertySym->m_id = func->m_symTable->NewID();
  848. propertySym->m_kind = SymKindProperty;
  849. propertySym->m_propertyId = propertyId;
  850. propertyIdIndex = (uint)-1;
  851. inlineCacheIndex = (uint)-1;
  852. propertySym->m_propertyIdIndex = propertyIdIndex;
  853. propertySym->m_inlineCacheIndex = inlineCacheIndex;
  854. Assert(propertyIdIndex == (uint)-1 || inlineCacheIndex == (uint)-1);
  855. propertySym->m_loadInlineCacheIndex = (uint)-1;
  856. propertySym->m_loadInlineCacheFunc = nullptr;
  857. propertySym->m_fieldKind = fieldKind;
  858. propertySym->m_stackSym = stackSym;
  859. propertySym->m_propertyEquivSet = nullptr;
  860. // Add to list
  861. func->m_symTable->Add(propertySym);
  862. // Keep track of all the property we use from this sym so we can invalidate
  863. // the value in glob opt
  864. ObjectSymInfo * objectSymInfo = stackSym->EnsureObjectInfo(func);
  865. propertySym->m_nextInStackSymList = objectSymInfo->m_propertySymList;
  866. objectSymInfo->m_propertySymList = propertySym;
  867. return propertySym;
  868. }
  869. ///----------------------------------------------------------------------------
  870. ///
  871. /// PropertySym::FindOrCreate
  872. ///
  873. /// Look for a PropertySym with the given ID/propertyId.
  874. ///
  875. ///----------------------------------------------------------------------------
  876. PropertySym *
  877. PropertySym::Find(SymID stackSymID, int32 propertyId, Func *func)
  878. {
  879. return func->m_symTable->FindPropertySym(stackSymID, propertyId);
  880. }
  881. ///----------------------------------------------------------------------------
  882. ///
  883. /// PropertySym::FindOrCreate
  884. ///
  885. /// Look for a PropertySym with the given ID/propertyId. If not found,
  886. /// create it.
  887. ///
  888. ///----------------------------------------------------------------------------
  889. PropertySym *
  890. PropertySym::FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
  891. {
  892. PropertySym * propertySym;
  893. propertySym = Find(stackSymID, propertyId, func);
  894. if (propertySym)
  895. {
  896. return propertySym;
  897. }
  898. return PropertySym::New(stackSymID, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
  899. }
  900. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  901. ///----------------------------------------------------------------------------
  902. ///
  903. /// Sym::Dump
  904. ///
  905. ///----------------------------------------------------------------------------
  906. void
  907. Sym::Dump(IRDumpFlags flags, const ValueType valueType) const
  908. {
  909. bool const AsmDumpMode = flags & IRDumpFlags_AsmDumpMode;
  910. bool const SimpleForm = !!(flags & IRDumpFlags_SimpleForm);
  911. if (AsmDumpMode)
  912. {
  913. if (this->IsStackSym() && this->AsStackSym()->IsArgSlotSym())
  914. {
  915. Output::Print(_u("arg "));
  916. }
  917. else if (this->IsStackSym() && this->AsStackSym()->IsParamSlotSym())
  918. {
  919. Output::Print(_u("param "));
  920. }
  921. }
  922. else if (this->IsStackSym())
  923. {
  924. StackSym const *stackSym = this->AsStackSym();
  925. if (stackSym->IsArgSlotSym())
  926. {
  927. if (stackSym->m_isInlinedArgSlot)
  928. {
  929. Output::Print(_u("iarg%d"), stackSym->GetArgSlotNum());
  930. }
  931. else
  932. {
  933. Output::Print(_u("arg%d"), stackSym->GetArgSlotNum());
  934. }
  935. Output::Print(_u("(s%d)"), m_id);
  936. }
  937. else if (stackSym->IsParamSlotSym())
  938. {
  939. if (stackSym->IsImplicitParamSym())
  940. {
  941. switch (stackSym->GetParamSlotNum())
  942. {
  943. case 1:
  944. Output::Print(_u("callInfo"));
  945. break;
  946. case 2:
  947. Output::Print(_u("funcInfo"));
  948. break;
  949. case 3:
  950. Output::Print(_u("genObj"));
  951. break;
  952. case 4:
  953. Output::Print(_u("genFrame"));
  954. break;
  955. default:
  956. Output::Print(_u("implPrm%d"), stackSym->GetParamSlotNum());
  957. }
  958. }
  959. else
  960. {
  961. Output::Print(_u("prm%d"), stackSym->GetParamSlotNum());
  962. }
  963. }
  964. else
  965. {
  966. Output::Print(_u("s%d"), m_id);
  967. if (Js::Configuration::Global.flags.Debug && stackSym->HasByteCodeRegSlot())
  968. {
  969. if (!JITManager::GetJITManager()->IsOOPJITEnabled())
  970. {
  971. Js::FunctionBody* functionBody = (Js::FunctionBody*)stackSym->GetByteCodeFunc()->GetJITFunctionBody()->GetAddr();
  972. if (functionBody->GetPropertyIdOnRegSlotsContainer())
  973. {
  974. if (functionBody->IsNonTempLocalVar(stackSym->GetByteCodeRegSlot()))
  975. {
  976. uint index = stackSym->GetByteCodeRegSlot() - stackSym->GetByteCodeFunc()->GetJITFunctionBody()->GetConstCount();
  977. Js::PropertyId propertyId = functionBody->GetPropertyIdOnRegSlotsContainer()->propertyIdsForRegSlots[index];
  978. Output::Print(_u("(%s)"), stackSym->GetByteCodeFunc()->GetInProcThreadContext()->GetPropertyRecord(propertyId)->GetBuffer());
  979. }
  980. }
  981. }
  982. }
  983. if (stackSym->IsVar())
  984. {
  985. if (stackSym->HasObjectTypeSym() && !SimpleForm)
  986. {
  987. Output::Print(_u("<s%d>"), stackSym->GetObjectTypeSym()->m_id);
  988. }
  989. }
  990. else
  991. {
  992. StackSym const *varSym = stackSym->GetVarEquivSym_NoCreate();
  993. if (varSym)
  994. {
  995. Output::Print(_u("(s%d)"), varSym->m_id);
  996. }
  997. }
  998. if (!SimpleForm)
  999. {
  1000. if (stackSym->m_builtInIndex != Js::BuiltinFunction::None)
  1001. {
  1002. Output::Print(_u("[ffunc]"));
  1003. }
  1004. }
  1005. IR::Opnd::DumpValueType(valueType);
  1006. }
  1007. }
  1008. else if (this->IsPropertySym())
  1009. {
  1010. PropertySym const *propertySym = this->AsPropertySym();
  1011. if (!SimpleForm)
  1012. {
  1013. Output::Print(_u("s%d("), m_id);
  1014. }
  1015. switch (propertySym->m_fieldKind)
  1016. {
  1017. case PropertyKindData:
  1018. propertySym->m_stackSym->Dump(flags, valueType);
  1019. if (JITManager::GetJITManager()->IsOOPJITEnabled())
  1020. {
  1021. Output::Print(_u("->#%d"), propertySym->m_propertyId);
  1022. }
  1023. else
  1024. {
  1025. Js::PropertyRecord const* fieldName = propertySym->m_func->GetInProcThreadContext()->GetPropertyRecord(propertySym->m_propertyId);
  1026. Output::Print(_u("->%s"), fieldName->GetBuffer());
  1027. }
  1028. break;
  1029. case PropertyKindSlots:
  1030. case PropertyKindSlotArray:
  1031. propertySym->m_stackSym->Dump(flags, valueType);
  1032. Output::Print(_u("[%d]"), propertySym->m_propertyId);
  1033. break;
  1034. case PropertyKindLocalSlots:
  1035. propertySym->m_stackSym->Dump(flags, valueType);
  1036. Output::Print(_u("l[%d]"), propertySym->m_propertyId);
  1037. break;
  1038. default:
  1039. AssertMsg(0, "Unknown field kind");
  1040. break;
  1041. }
  1042. if (!SimpleForm)
  1043. {
  1044. Output::Print(_u(")"));
  1045. }
  1046. }
  1047. }
  1048. void
  1049. Sym::Dump(const ValueType valueType) const
  1050. {
  1051. this->Dump(IRDumpFlags_None, valueType);
  1052. }
  1053. void
  1054. Sym::DumpSimple() const
  1055. {
  1056. this->Dump(IRDumpFlags_SimpleForm);
  1057. }
  1058. #endif // DBG_DUMP