ByteCodeDumper.cpp 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
  4. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  5. //-------------------------------------------------------------------------------------------------------
  6. #include "RuntimeByteCodePch.h"
  7. #if DBG_DUMP
  8. #if DBG
  9. // Parser Includes
  10. #include "RegexCommon.h"
  11. #include "DebugWriter.h"
  12. #include "RegexPattern.h"
  13. #endif
  14. namespace Js
  15. {
  16. // Pre-order recursive dump, head first, then children.
  17. void ByteCodeDumper::DumpRecursively(FunctionBody* dumpFunction)
  18. {
  19. dumpFunction->EnsureDeserialized();
  20. ByteCodeDumper::Dump(dumpFunction);
  21. for (uint i = 0; i < dumpFunction->GetNestedCount(); i ++)
  22. {
  23. dumpFunction->GetNestedFunctionForExecution(i);
  24. ByteCodeDumper::DumpRecursively(dumpFunction->GetNestedFunc(i)->GetFunctionBody());
  25. }
  26. }
  27. void ByteCodeDumper::Dump(FunctionBody* dumpFunction)
  28. {
  29. ByteCodeReader reader;
  30. reader.Create(dumpFunction);
  31. StatementReader<FunctionBody::StatementMapList> statementReader;
  32. statementReader.Create(dumpFunction);
  33. dumpFunction->DumpFullFunctionName();
  34. Output::Print(_u(" ("));
  35. ArgSlot inParamCount = dumpFunction->GetInParamsCount();
  36. for (ArgSlot paramIndex = 0; paramIndex < inParamCount; paramIndex++)
  37. {
  38. if (paramIndex > 0)
  39. {
  40. Output::Print(_u(", "));
  41. }
  42. Output::Print(_u("In%hu"), paramIndex);
  43. }
  44. Output::Print(_u(") "));
  45. Output::Print(_u("(size: %d [%d])\n"), dumpFunction->GetByteCodeCount(), dumpFunction->GetByteCodeWithoutLDACount());
  46. #if defined(DBG) || defined(ENABLE_DEBUG_CONFIG_OPTIONS)
  47. if (dumpFunction->IsInDebugMode())
  48. {
  49. Output::Print(_u("[Bytecode was generated for debug mode]\n"));
  50. }
  51. #endif
  52. #if DBG
  53. if (dumpFunction->IsReparsed())
  54. {
  55. Output::Print(_u("[A reparse is being done]\n"));
  56. }
  57. #endif
  58. Output::Print(
  59. _u(" %u locals (%u temps from R%u), %u inline cache\n"),
  60. dumpFunction->GetLocalsCount(),
  61. dumpFunction->GetTempCount(),
  62. dumpFunction->GetFirstTmpReg(),
  63. dumpFunction->GetInlineCacheCount());
  64. uint32 statementIndex = 0;
  65. ByteCodeDumper::DumpConstantTable(dumpFunction);
  66. ByteCodeDumper::DumpImplicitArgIns(dumpFunction);
  67. while (true)
  68. {
  69. while (statementReader.AtStatementBoundary(&reader))
  70. {
  71. dumpFunction->PrintStatementSourceLine(statementIndex);
  72. statementIndex = statementReader.MoveNextStatementBoundary();
  73. }
  74. uint byteOffset = reader.GetCurrentOffset();
  75. LayoutSize layoutSize;
  76. OpCode op = reader.ReadOp(layoutSize);
  77. if (op == OpCode::EndOfBlock)
  78. {
  79. Assert(reader.GetCurrentOffset() == dumpFunction->GetByteCode()->GetLength());
  80. break;
  81. }
  82. Output::Print(_u(" %04x %2s"), byteOffset, layoutSize == LargeLayout? _u("L-") : layoutSize == MediumLayout? _u("M-") : _u(""));
  83. DumpOp(op, layoutSize, reader, dumpFunction);
  84. if (Js::Configuration::Global.flags.Verbose)
  85. {
  86. int layoutStart = byteOffset + 2; // Account fo the prefix op
  87. int endByteOffset = reader.GetCurrentOffset();
  88. Output::SkipToColumn(70);
  89. if (layoutSize == LargeLayout)
  90. {
  91. Output::Print(_u("%02X "),
  92. op > Js::OpCode::MaxByteSizedOpcodes?
  93. Js::OpCode::ExtendedLargeLayoutPrefix : Js::OpCode::LargeLayoutPrefix);
  94. }
  95. else if (layoutSize == MediumLayout)
  96. {
  97. Output::Print(_u("%02X "),
  98. op > Js::OpCode::MaxByteSizedOpcodes?
  99. Js::OpCode::ExtendedMediumLayoutPrefix : Js::OpCode::MediumLayoutPrefix);
  100. }
  101. else
  102. {
  103. Assert(layoutSize == SmallLayout);
  104. if (op > Js::OpCode::MaxByteSizedOpcodes)
  105. {
  106. Output::Print(_u("%02X "), Js::OpCode::ExtendedOpcodePrefix);
  107. }
  108. else
  109. {
  110. Output::Print(_u(" "));
  111. layoutStart--; // don't have a prefix
  112. }
  113. }
  114. Output::Print(_u("%02x"), (byte)op);
  115. for (int i = layoutStart; i < endByteOffset; i++)
  116. {
  117. Output::Print(_u(" %02x"), reader.GetRawByte(i));
  118. }
  119. }
  120. Output::Print(_u("\n"));
  121. }
  122. if (statementReader.AtStatementBoundary(&reader))
  123. {
  124. dumpFunction->PrintStatementSourceLine(statementIndex);
  125. statementIndex = statementReader.MoveNextStatementBoundary();
  126. }
  127. Output::Print(_u("\n"));
  128. Output::Flush();
  129. }
  130. void ByteCodeDumper::DumpConstantTable(FunctionBody *dumpFunction)
  131. {
  132. Output::Print(_u(" Constant Table:\n ======== =====\n "));
  133. uint count = dumpFunction->GetConstantCount();
  134. for (RegSlot reg = FunctionBody::FirstRegSlot; reg < count; reg++)
  135. {
  136. DumpReg(reg);
  137. Var varConst = dumpFunction->GetConstantVar(reg);
  138. Assert(varConst != nullptr);
  139. if (TaggedInt::Is(varConst))
  140. {
  141. #if ENABLE_NATIVE_CODEGEN
  142. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::LdC_A_I4));
  143. #else
  144. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  145. #endif
  146. DumpI4(TaggedInt::ToInt32(varConst));
  147. }
  148. else if (varConst == (Js::Var)&Js::NullFrameDisplay)
  149. {
  150. #if ENABLE_NATIVE_CODEGEN
  151. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::LdNullDisplay));
  152. #else
  153. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  154. Output::Print(_u(" (NullDisplay)"));
  155. #endif
  156. }
  157. else if (varConst == (Js::Var)&Js::StrictNullFrameDisplay)
  158. {
  159. #if ENABLE_NATIVE_CODEGEN
  160. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::LdStrictNullDisplay));
  161. #else
  162. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  163. Output::Print(_u(" (StrictNullDisplay)"));
  164. #endif
  165. }
  166. else
  167. {
  168. switch (JavascriptOperators::GetTypeId(varConst))
  169. {
  170. case Js::TypeIds_Undefined:
  171. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  172. Output::Print(_u(" (undefined)"));
  173. break;
  174. case Js::TypeIds_Null:
  175. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  176. Output::Print(_u(" (null)"));
  177. break;
  178. case Js::TypeIds_Boolean:
  179. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(
  180. VarTo<JavascriptBoolean>(varConst)->GetValue() ? OpCode::LdTrue : OpCode::LdFalse));
  181. break;
  182. case Js::TypeIds_Number:
  183. #if ENABLE_NATIVE_CODEGEN
  184. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::LdC_A_R8));
  185. #else
  186. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  187. #endif
  188. Output::Print(_u("%G"), JavascriptNumber::GetValue(varConst));
  189. break;
  190. case Js::TypeIds_BigInt:
  191. #if ENABLE_NATIVE_CODEGEN
  192. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::BigIntLiteral));
  193. #else
  194. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  195. #endif
  196. break;
  197. case Js::TypeIds_String:
  198. #if ENABLE_NATIVE_CODEGEN
  199. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::LdStr));
  200. #else
  201. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  202. #endif
  203. Output::Print(_u(" (\"%s\")%s"), VarTo<JavascriptString>(varConst)->GetSz(), Js::VarIs<Js::PropertyString>(varConst) ? _u(" [prop]") : _u(""));
  204. break;
  205. case Js::TypeIds_GlobalObject:
  206. #if ENABLE_NATIVE_CODEGEN
  207. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::LdRoot));
  208. #else
  209. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  210. #endif
  211. break;
  212. case Js::TypeIds_ModuleRoot:
  213. #if ENABLE_NATIVE_CODEGEN
  214. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::LdModuleRoot));
  215. #else
  216. Output::Print(_u("%-10s"), OpCodeUtil::GetOpCodeName(OpCode::Ld_A));
  217. #endif
  218. DumpI4(dumpFunction->GetModuleID());
  219. break;
  220. case Js::TypeIds_ES5Array:
  221. // ES5Array objects in the constant table are always string template callsite objects.
  222. // If we later put other ES5Array objects in the constant table, we'll need another way
  223. // to decide the constant type.
  224. Output::Print(_u("%-10s"), _u("LdStringTemplate"));
  225. Output::Print(_u(" (\"%s\")"), dumpFunction->GetScriptContext()->GetLibrary()->GetStringTemplateCallsiteObjectKey(varConst));
  226. break;
  227. default:
  228. AssertMsg(UNREACHED, "Unexpected object type in DumpConstantTable");
  229. break;
  230. }
  231. }
  232. Output::Print(_u("\n "));
  233. }
  234. Output::Print(_u("\n"));
  235. }
  236. void ByteCodeDumper::DumpImplicitArgIns(FunctionBody * dumpFunction)
  237. {
  238. if (dumpFunction->GetInParamsCount() <= 1 || !dumpFunction->GetHasImplicitArgIns())
  239. {
  240. return;
  241. }
  242. Output::Print(_u(" Implicit Arg Ins:\n ======== === ===\n "));
  243. for (RegSlot reg = 1;
  244. reg < dumpFunction->GetInParamsCount(); reg++)
  245. {
  246. DumpReg((RegSlot)(reg + dumpFunction->GetConstantCount() - 1));
  247. // DisableJIT-TODO: Should this entire function be ifdefed?
  248. #if ENABLE_NATIVE_CODEGEN
  249. Output::Print(_u("%-11s"), OpCodeUtil::GetOpCodeName(Js::OpCode::ArgIn_A));
  250. #endif
  251. Output::Print(_u("In%d\n "), reg);
  252. }
  253. if (dumpFunction->GetHasRestParameter())
  254. {
  255. DumpReg(dumpFunction->GetRestParamRegSlot());
  256. #if ENABLE_NATIVE_CODEGEN
  257. Output::Print(_u("%-11s"), OpCodeUtil::GetOpCodeName(Js::OpCode::ArgIn_Rest));
  258. #endif
  259. Output::Print(_u("In%d\n "), dumpFunction->GetInParamsCount());
  260. }
  261. Output::Print(_u("\n"));
  262. }
  263. void ByteCodeDumper::DumpU4(uint32 value)
  264. {
  265. Output::Print(_u(" uint:%u "), value);
  266. }
  267. void ByteCodeDumper::DumpI4(int value)
  268. {
  269. Output::Print(_u(" int:%d "), value);
  270. }
  271. void ByteCodeDumper::DumpI8(int64 value)
  272. {
  273. Output::Print(_u(" int64:%lld "), value);
  274. }
  275. void ByteCodeDumper::DumpU2(ushort value)
  276. {
  277. Output::Print(_u(" ushort:%d "), value);
  278. }
  279. void ByteCodeDumper::DumpOffset(int byteOffset, ByteCodeReader const& reader)
  280. {
  281. Output::Print(_u(" x:%04x (%4d) "), reader.GetCurrentOffset() + byteOffset, byteOffset);
  282. }
  283. void ByteCodeDumper::DumpAddr(void* addr)
  284. {
  285. Output::Print(_u(" addr:%04x "), addr);
  286. }
  287. void ByteCodeDumper::DumpR4(float value)
  288. {
  289. Output::Print(_u(" float:%g "), value);
  290. }
  291. void ByteCodeDumper::DumpR8(double value)
  292. {
  293. Output::Print(_u(" double:%g "), value);
  294. }
  295. void ByteCodeDumper::DumpReg(RegSlot registerID)
  296. {
  297. Output::Print(_u(" R%d "), (int) registerID);
  298. }
  299. void ByteCodeDumper::DumpReg(RegSlot_TwoByte registerID)
  300. {
  301. Output::Print(_u(" R%d "), (int) registerID);
  302. }
  303. void ByteCodeDumper::DumpReg(RegSlot_OneByte registerID)
  304. {
  305. Output::Print(_u(" R%d "), (int) registerID);
  306. }
  307. void ByteCodeDumper::DumpProfileId(uint id)
  308. {
  309. Output::Print(_u(" <%d> "), id);
  310. }
  311. void ByteCodeDumper::DumpEmpty(OpCode op, const unaligned OpLayoutEmpty * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  312. {
  313. switch (op)
  314. {
  315. case OpCode::CommitScope:
  316. {
  317. const Js::PropertyIdArray *propIds = dumpFunction->GetFormalsPropIdArray();
  318. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  319. Output::Print(_u(" %d ["), propIds->count);
  320. for (uint i = 0; i < propIds->count && i < 3; i++)
  321. {
  322. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(propIds->elements[i]);
  323. if (i != 0)
  324. {
  325. Output::Print(_u(", "));
  326. }
  327. Output::Print(_u("%s"), pPropertyName->GetBuffer());
  328. }
  329. Output::Print(_u("]"));
  330. break;
  331. }
  332. }
  333. }
  334. template <class T>
  335. void ByteCodeDumper::DumpCallI(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  336. {
  337. if (data->Return != Constants::NoRegister)
  338. {
  339. DumpReg((RegSlot)data->Return);
  340. Output::Print(_u("="));
  341. }
  342. Output::Print(_u(" R%d(ArgCount: %d)"), data->Function, data->ArgCount);
  343. }
  344. template <class T>
  345. void ByteCodeDumper::DumpCallIExtended(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  346. {
  347. DumpCallI(op, data, dumpFunction, reader);
  348. if (data->Options & Js::CallIExtended_SpreadArgs)
  349. {
  350. const Js::AuxArray<uint32> *arr = reader.ReadAuxArray<uint32>(data->SpreadAuxOffset, dumpFunction);
  351. Output::Print(_u(" spreadArgs ["), arr->count);
  352. for (uint i = 0; i < arr->count; i++)
  353. {
  354. if (i > 10)
  355. {
  356. Output::Print(_u(", ..."));
  357. break;
  358. }
  359. if (i != 0)
  360. {
  361. Output::Print(_u(", "));
  362. }
  363. Output::Print(_u("%u"), arr->elements[i]);
  364. }
  365. Output::Print(_u("]"));
  366. }
  367. }
  368. template <class T>
  369. void ByteCodeDumper::DumpCallIFlags(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  370. {
  371. DumpCallI(op, data, dumpFunction, reader);
  372. Output::Print(_u(" <%04x> "), data->callFlags);
  373. }
  374. template <class T>
  375. void ByteCodeDumper::DumpCallIExtendedFlags(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  376. {
  377. DumpCallIFlags(op, data, dumpFunction, reader);
  378. if (data->Options & Js::CallIExtended_SpreadArgs)
  379. {
  380. const Js::AuxArray<uint32> *arr = reader.ReadAuxArray<uint32>(data->SpreadAuxOffset, dumpFunction);
  381. Output::Print(_u(" spreadArgs ["), arr->count);
  382. for (uint i = 0; i < arr->count; i++)
  383. {
  384. if (i > 10)
  385. {
  386. Output::Print(_u(", ..."));
  387. break;
  388. }
  389. if (i != 0)
  390. {
  391. Output::Print(_u(", "));
  392. }
  393. Output::Print(_u("%u"), arr->elements[i]);
  394. }
  395. Output::Print(_u("]"));
  396. }
  397. }
  398. template <class T>
  399. void ByteCodeDumper::DumpCallIExtendedFlagsWithICIndex(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  400. {
  401. DumpCallIFlags(op, data, dumpFunction, reader);
  402. DumpCallIWithICIndex(op, data, dumpFunction, reader);
  403. if (data->Options & Js::CallIExtended_SpreadArgs)
  404. {
  405. const Js::AuxArray<uint32> *arr = reader.ReadAuxArray<uint32>(data->SpreadAuxOffset, dumpFunction);
  406. Output::Print(_u(" spreadArgs ["), arr->count);
  407. for (uint i = 0; i < arr->count; i++)
  408. {
  409. if (i > 10)
  410. {
  411. Output::Print(_u(", ..."));
  412. break;
  413. }
  414. if (i != 0)
  415. {
  416. Output::Print(_u(", "));
  417. }
  418. Output::Print(_u("%u"), arr->elements[i]);
  419. }
  420. Output::Print(_u("]"));
  421. }
  422. }
  423. template <class T>
  424. void ByteCodeDumper::DumpCallIWithICIndex(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  425. {
  426. DumpCallI(op, data, dumpFunction, reader);
  427. Output::Print(_u(" <%d> "), data->inlineCacheIndex);
  428. }
  429. template <class T>
  430. void ByteCodeDumper::DumpCallIFlagsWithICIndex(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  431. {
  432. DumpCallI(op, data, dumpFunction, reader);
  433. Output::Print(_u(" <%d> "), data->inlineCacheIndex);
  434. Output::Print(_u(" <%d> "), data->callFlags);
  435. }
  436. template <class T>
  437. void ByteCodeDumper::DumpCallIExtendedWithICIndex(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  438. {
  439. DumpCallIWithICIndex(op, data, dumpFunction, reader);
  440. if (data->Options & Js::CallIExtended_SpreadArgs)
  441. {
  442. const Js::AuxArray<uint32> *arr = reader.ReadAuxArray<uint32>(data->SpreadAuxOffset, dumpFunction);
  443. Output::Print(_u(" spreadArgs ["), arr->count);
  444. for (uint i=0; i < arr->count; i++)
  445. {
  446. if (i > 10)
  447. {
  448. Output::Print(_u(", ..."));
  449. break;
  450. }
  451. if (i != 0)
  452. {
  453. Output::Print(_u(", "));
  454. }
  455. Output::Print(_u("%u"), arr->elements[i]);
  456. }
  457. Output::Print(_u("]"));
  458. }
  459. }
  460. template <class T>
  461. void ByteCodeDumper::DumpElementI(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  462. {
  463. switch (op)
  464. {
  465. case OpCode::ProfiledLdElemI_A:
  466. case OpCode::LdElemI_A:
  467. case OpCode::LdMethodElem:
  468. case OpCode::TypeofElem:
  469. {
  470. Output::Print(_u(" R%d = R%d[R%d]"), data->Value, data->Instance, data->Element);
  471. break;
  472. }
  473. case OpCode::ProfiledStElemI_A:
  474. case OpCode::ProfiledStElemI_A_Strict:
  475. case OpCode::StElemI_A:
  476. case OpCode::StElemI_A_Strict:
  477. case OpCode::InitSetElemI:
  478. case OpCode::InitGetElemI:
  479. case OpCode::InitComputedProperty:
  480. case OpCode::InitClassMemberComputedName:
  481. case OpCode::InitClassMemberGetComputedName:
  482. case OpCode::InitClassMemberSetComputedName:
  483. {
  484. Output::Print(_u(" R%d[R%d] = R%d"), data->Instance, data->Element, data->Value);
  485. break;
  486. }
  487. case OpCode::DeleteElemI_A:
  488. case OpCode::DeleteElemIStrict_A:
  489. {
  490. Output::Print(_u(" R%d[R%d]"), data->Instance, data->Element);
  491. break;
  492. }
  493. default:
  494. {
  495. AssertMsg(false, "Unknown OpCode for OpLayoutElementI");
  496. break;
  497. }
  498. }
  499. }
  500. template <class T>
  501. void ByteCodeDumper::DumpReg2Int1(OpCode op, const unaligned T* data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  502. {
  503. switch (op)
  504. {
  505. case OpCode::LdThis:
  506. case OpCode::ProfiledLdThis:
  507. Output::Print(_u(" R%d = R%d, %d"), data->R0, data->R1, data->C1);
  508. break;
  509. case OpCode::LdIndexedFrameDisplay:
  510. Output::Print(_u(" R%d = [%d], R%d "), data->R0, data->C1, data->R1);
  511. break;
  512. case OpCode::GetCachedFunc:
  513. DumpReg(data->R0);
  514. Output::Print(_u("= func("));
  515. DumpReg(data->R1);
  516. Output::Print(_u(","));
  517. DumpI4(data->C1);
  518. Output::Print(_u(")"));
  519. break;
  520. default:
  521. AssertMsg(false, "Unknown OpCode for OpLayoutReg2Int1");
  522. break;
  523. }
  524. }
  525. template <class T>
  526. void ByteCodeDumper::DumpElementScopedU(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  527. {
  528. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  529. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  530. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  531. switch (op)
  532. {
  533. case OpCode::LdElemUndefScoped:
  534. {
  535. Output::Print(_u(" %s = undefined, R%d"), pPropertyName->GetBuffer(), Js::FunctionBody::RootObjectRegSlot);
  536. break;
  537. }
  538. case OpCode::InitUndeclConsoleLetFld:
  539. case OpCode::InitUndeclConsoleConstFld:
  540. {
  541. Output::Print(_u(" %s = undefined"), pPropertyName->GetBuffer());
  542. break;
  543. }
  544. default:
  545. {
  546. AssertMsg(false, "Unknown OpCode for ElementScopedU");
  547. break;
  548. }
  549. }
  550. }
  551. template <class T>
  552. void ByteCodeDumper::DumpElementU(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  553. {
  554. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  555. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  556. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  557. switch (op)
  558. {
  559. case OpCode::LdElemUndef:
  560. {
  561. Output::Print(_u(" R%d.%s = undefined"), data->Instance, pPropertyName->GetBuffer());
  562. break;
  563. }
  564. // TODO: Change InitUndeclLetFld and InitUndeclConstFld to ElementU layout
  565. // case OpCode::InitUndeclLetFld:
  566. // case OpCode::InitUndeclConstFld:
  567. // {
  568. // PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(data->PropertyIndex);
  569. // Output::Print(_u(" R%d.%s"), data->Instance, pPropertyName->GetBuffer());
  570. // break;
  571. // }
  572. case OpCode::ClearAttributes:
  573. {
  574. Output::Print(_u(" R%d.%s.writable/enumerable/configurable = 0"), data->Instance, pPropertyName->GetBuffer());
  575. break;
  576. }
  577. case OpCode::DeleteLocalFld:
  578. case OpCode::DeleteLocalFld_ReuseLoc:
  579. Output::Print(_u(" R%d = %s "), data->Instance, pPropertyName->GetBuffer());
  580. break;
  581. case OpCode::StLocalFuncExpr:
  582. Output::Print(_u(" %s = R%d"), pPropertyName->GetBuffer(), data->Instance);
  583. break;
  584. default:
  585. {
  586. AssertMsg(false, "Unknown OpCode for ElementU");
  587. break;
  588. }
  589. }
  590. }
  591. template <class T>
  592. void ByteCodeDumper::DumpElementRootU(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  593. {
  594. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  595. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  596. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  597. switch (op)
  598. {
  599. case OpCode::InitUndeclRootLetFld:
  600. case OpCode::InitUndeclRootConstFld:
  601. case OpCode::EnsureNoRootFld:
  602. case OpCode::EnsureNoRootRedeclFld:
  603. {
  604. Output::Print(_u(" root.%s"), pPropertyName->GetBuffer());
  605. break;
  606. }
  607. case OpCode::EnsureCanDeclGloFunc:
  608. {
  609. Output::Print(_u(" root.%s"), pPropertyName->GetBuffer());
  610. break;
  611. }
  612. case OpCode::LdLocalElemUndef:
  613. {
  614. Output::Print(_u(" %s = undefined"), pPropertyName->GetBuffer());
  615. break;
  616. }
  617. default:
  618. {
  619. AssertMsg(false, "Unknown OpCode for ElementRootU");
  620. break;
  621. }
  622. }
  623. }
  624. template <class T>
  625. void ByteCodeDumper::DumpElementScopedC(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  626. {
  627. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  628. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  629. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  630. switch (op)
  631. {
  632. case OpCode::ScopedEnsureNoRedeclFld:
  633. case OpCode::ScopedDeleteFld:
  634. case OpCode::ScopedDeleteFldStrict:
  635. {
  636. Output::Print(_u(" %s, R%d"), pPropertyName->GetBuffer(), data->Value);
  637. break;
  638. }
  639. case OpCode::ScopedInitFunc:
  640. {
  641. Output::Print(_u(" %s = R%d, R%d"), pPropertyName->GetBuffer(), data->Value,
  642. Js::FunctionBody::RootObjectRegSlot);
  643. break;
  644. }
  645. default:
  646. {
  647. AssertMsg(false, "Unknown OpCode for OpLayoutElementScopedC");
  648. break;
  649. }
  650. }
  651. }
  652. template <class T>
  653. void ByteCodeDumper::DumpElementC(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  654. {
  655. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  656. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  657. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  658. switch (op)
  659. {
  660. case OpCode::DeleteFld:
  661. case OpCode::DeleteFld_ReuseLoc:
  662. case OpCode::DeleteRootFld:
  663. case OpCode::DeleteFldStrict:
  664. case OpCode::DeleteRootFldStrict:
  665. {
  666. Output::Print(_u(" R%d.%s"), data->Instance, pPropertyName->GetBuffer());
  667. break;
  668. }
  669. case OpCode::InitSetFld:
  670. case OpCode::InitGetFld:
  671. case OpCode::InitClassMemberGet:
  672. case OpCode::InitClassMemberSet:
  673. {
  674. Output::Print(_u(" R%d.%s = (Set/Get) R%d"), data->Instance, pPropertyName->GetBuffer(),
  675. data->Value);
  676. break;
  677. }
  678. case OpCode::StFuncExpr:
  679. case OpCode::InitProto:
  680. {
  681. Output::Print(_u(" R%d.%s = R%d"), data->Instance, pPropertyName->GetBuffer(),
  682. data->Value);
  683. break;
  684. }
  685. default:
  686. {
  687. AssertMsg(false, "Unknown OpCode for OpLayoutElementC");
  688. break;
  689. }
  690. }
  691. }
  692. template <class T>
  693. void ByteCodeDumper::DumpElementScopedC2(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  694. {
  695. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  696. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  697. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  698. switch (op)
  699. {
  700. case OpCode::ScopedLdInst:
  701. {
  702. Output::Print(_u(" R%d, R%d = %s"), data->Value, data->Value2, pPropertyName->GetBuffer());
  703. break;
  704. }
  705. default:
  706. {
  707. AssertMsg(false, "Unknown OpCode for OpLayoutElementScopedC2");
  708. break;
  709. }
  710. }
  711. }
  712. template <class T>
  713. void ByteCodeDumper::DumpElementC2(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  714. {
  715. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  716. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  717. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  718. switch (op)
  719. {
  720. case OpCode::LdSuperFld:
  721. {
  722. Output::Print(_u(" R%d = R%d(this=R%d).%s #%d"), data->Value, data->Instance, data->Value2,
  723. pPropertyName->GetBuffer(), data->PropertyIdIndex);
  724. break;
  725. }
  726. case OpCode::ProfiledLdSuperFld:
  727. {
  728. Output::Print(_u(" R%d = R%d(this=R%d).%s #%d"), data->Value, data->Instance, data->Value2,
  729. pPropertyName->GetBuffer(), data->PropertyIdIndex);
  730. DumpProfileId(data->PropertyIdIndex);
  731. break;
  732. }
  733. case OpCode::StSuperFld:
  734. case OpCode::StSuperFldStrict:
  735. {
  736. Output::Print(_u(" R%d.%s(this=R%d) = R%d #%d"), data->Instance, pPropertyName->GetBuffer(),
  737. data->Value2, data->Value, data->PropertyIdIndex);
  738. break;
  739. }
  740. case OpCode::ProfiledStSuperFld:
  741. case OpCode::ProfiledStSuperFldStrict:
  742. {
  743. Output::Print(_u(" R%d.%s(this=R%d) = R%d #%d"), data->Instance, pPropertyName->GetBuffer(),
  744. data->Value2, data->Value, data->PropertyIdIndex);
  745. DumpProfileId(data->PropertyIdIndex);
  746. break;
  747. }
  748. default:
  749. {
  750. AssertMsg(false, "Unknown OpCode for OpLayoutElementC2");
  751. break;
  752. }
  753. }
  754. }
  755. template <class T>
  756. void ByteCodeDumper::DumpReg1Unsigned1(OpCode op, const unaligned T* data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  757. {
  758. switch (op)
  759. {
  760. case OpCode::InvalCachedScope:
  761. #if ENABLE_NATIVE_CODEGEN
  762. case OpCode::NewScopeSlots:
  763. #endif
  764. Output::Print(_u(" R%u[%u]"), data->R0, data->C1);
  765. break;
  766. case OpCode::NewRegEx:
  767. {
  768. DumpReg(data->R0);
  769. #if DBG
  770. Output::Print(_u("="));
  771. UnifiedRegex::DebugWriter w;
  772. dumpFunction->GetLiteralRegex(data->C1)->Print(&w);
  773. #else
  774. Output::Print(_u("=<regex>"));
  775. #endif
  776. break;
  777. }
  778. case OpCode::InitForInEnumerator:
  779. {
  780. DumpReg(data->R0);
  781. DumpU4(data->C1);
  782. break;
  783. }
  784. case OpCode::NewPropIdArrForCompProps:
  785. {
  786. Output::Print(_u(" R%u = [%u] "), data->R0, data->C1);
  787. break;
  788. }
  789. default:
  790. DumpReg(data->R0);
  791. Output::Print(_u("="));
  792. DumpU4(data->C1);
  793. break;
  794. };
  795. }
  796. template <class T>
  797. void ByteCodeDumper::DumpElementSlot(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  798. {
  799. switch (op)
  800. {
  801. case OpCode::NewInnerStackScFunc:
  802. case OpCode::NewInnerScFunc:
  803. case OpCode::NewInnerScGenFunc:
  804. {
  805. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  806. Output::Print(_u(" R%d = env:R%d, %s()"), data->Value, data->Instance,
  807. pfuncActual->EnsureDeserialized()->GetDisplayName());
  808. break;
  809. }
  810. case OpCode::NewScFuncHomeObj:
  811. case OpCode::NewScGenFuncHomeObj:
  812. {
  813. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  814. Output::Print(_u(" R%d = hmo:R%d, %s()"), data->Value, data->Instance,
  815. pfuncActual->EnsureDeserialized()->GetDisplayName());
  816. break;
  817. }
  818. #if ENABLE_NATIVE_CODEGEN
  819. case OpCode::StSlot:
  820. case OpCode::StSlotChkUndecl:
  821. #endif
  822. case OpCode::StObjSlot:
  823. case OpCode::StObjSlotChkUndecl:
  824. case OpCode::StPropIdArrFromVar:
  825. Output::Print(_u(" R%d[%d] = R%d "),data->Instance,data->SlotIndex,data->Value);
  826. break;
  827. case OpCode::LdSlot:
  828. #if ENABLE_NATIVE_CODEGEN
  829. case OpCode::LdSlotArr:
  830. #endif
  831. case OpCode::LdObjSlot:
  832. Output::Print(_u(" R%d = R%d[%d] "),data->Value,data->Instance,data->SlotIndex);
  833. break;
  834. default:
  835. {
  836. AssertMsg(false, "Unknown OpCode for OpLayoutElementSlot");
  837. break;
  838. }
  839. }
  840. }
  841. template <class T>
  842. void ByteCodeDumper::DumpElementSlotI1(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  843. {
  844. switch (op)
  845. {
  846. case OpCode::StLocalSlot:
  847. case OpCode::StParamSlot:
  848. case OpCode::StLocalObjSlot:
  849. case OpCode::StParamObjSlot:
  850. case OpCode::StLocalSlotChkUndecl:
  851. case OpCode::StParamSlotChkUndecl:
  852. case OpCode::StLocalObjSlotChkUndecl:
  853. case OpCode::StParamObjSlotChkUndecl:
  854. Output::Print(_u(" [%d] = R%d "),data->SlotIndex, data->Value);
  855. break;
  856. case OpCode::LdLocalSlot:
  857. case OpCode::LdParamSlot:
  858. case OpCode::LdEnvObj:
  859. case OpCode::LdEnvObj_ReuseLoc:
  860. case OpCode::LdLocalObjSlot:
  861. case OpCode::LdParamObjSlot:
  862. Output::Print(_u(" R%d = [%d] "), data->Value, data->SlotIndex);
  863. break;
  864. case OpCode::NewScFunc:
  865. case OpCode::NewStackScFunc:
  866. case OpCode::NewScGenFunc:
  867. {
  868. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  869. Output::Print(_u(" R%d = %s()"), data->Value,
  870. pfuncActual->EnsureDeserialized()->GetDisplayName());
  871. break;
  872. }
  873. default:
  874. {
  875. AssertMsg(false, "Unknown OpCode for OpLayoutElementSlotI1");
  876. break;
  877. }
  878. }
  879. }
  880. template <class T>
  881. void ByteCodeDumper::DumpElementSlotI2(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  882. {
  883. switch (op)
  884. {
  885. case OpCode::StInnerSlot:
  886. case OpCode::StInnerSlotChkUndecl:
  887. case OpCode::StInnerObjSlot:
  888. case OpCode::StInnerObjSlotChkUndecl:
  889. case OpCode::StEnvSlot:
  890. case OpCode::StEnvObjSlot:
  891. case OpCode::StEnvSlotChkUndecl:
  892. case OpCode::StEnvObjSlotChkUndecl:
  893. case OpCode::StModuleSlot:
  894. Output::Print(_u(" [%d][%d] = R%d "),data->SlotIndex1, data->SlotIndex2, data->Value);
  895. break;
  896. case OpCode::LdInnerSlot:
  897. case OpCode::LdInnerObjSlot:
  898. case OpCode::LdEnvSlot:
  899. case OpCode::LdEnvObjSlot:
  900. case OpCode::LdModuleSlot:
  901. Output::Print(_u(" R%d = [%d][%d] "),data->Value, data->SlotIndex1, data->SlotIndex2);
  902. break;
  903. default:
  904. {
  905. AssertMsg(false, "Unknown OpCode for OpLayoutElementSlotI2");
  906. break;
  907. }
  908. }
  909. }
  910. template <class T>
  911. void ByteCodeDumper::DumpElementSlotI3(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  912. {
  913. switch (op)
  914. {
  915. case OpCode::NewInnerScFuncHomeObj:
  916. case OpCode::NewInnerScGenFuncHomeObj:
  917. {
  918. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  919. Output::Print(_u(" R%d = env:R%d hmo: R%d, %s()"), data->Value, data->Instance, data->HomeObj,
  920. pfuncActual->EnsureDeserialized()->GetDisplayName());
  921. break;
  922. }
  923. default:
  924. {
  925. AssertMsg(false, "Unknown OpCode for OpLayoutElementSlotI3");
  926. break;
  927. }
  928. }
  929. }
  930. template <class T>
  931. void ByteCodeDumper::DumpElementP(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  932. {
  933. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  934. PropertyId propertyId = dumpFunction->GetPropertyIdFromCacheId(data->inlineCacheIndex);
  935. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(propertyId);
  936. switch (op)
  937. {
  938. case OpCode::ScopedLdFldForTypeOf:
  939. case OpCode::ScopedLdFld:
  940. Output::Print(_u(" R%d = %s, R%d #%d"), data->Value, pPropertyName->GetBuffer(),
  941. Js::FunctionBody::RootObjectRegSlot, data->inlineCacheIndex);
  942. break;
  943. case OpCode::ScopedStFld:
  944. case OpCode::ConsoleScopedStFld:
  945. case OpCode::ScopedStFldStrict:
  946. case OpCode::ConsoleScopedStFldStrict:
  947. Output::Print(_u(" %s = R%d, R%d #%d"), pPropertyName->GetBuffer(), data->Value,
  948. Js::FunctionBody::RootObjectRegSlot, data->inlineCacheIndex);
  949. break;
  950. case OpCode::LdLocalFld:
  951. case OpCode::LdLocalFld_ReuseLoc:
  952. Output::Print(_u(" R%d = %s #%d"), data->Value, pPropertyName->GetBuffer(), data->inlineCacheIndex);
  953. break;
  954. case OpCode::ProfiledLdLocalFld:
  955. case OpCode::ProfiledLdLocalFld_ReuseLoc:
  956. Output::Print(_u(" R%d = %s #%d"), data->Value, pPropertyName->GetBuffer(), data->inlineCacheIndex);
  957. DumpProfileId(data->inlineCacheIndex);
  958. break;
  959. case OpCode::StLocalFld:
  960. case OpCode::InitLocalFld:
  961. case OpCode::InitLocalLetFld:
  962. case OpCode::InitUndeclLocalLetFld:
  963. case OpCode::InitUndeclLocalConstFld:
  964. Output::Print(_u(" %s = R%d #%d"), pPropertyName->GetBuffer(), data->Value, data->inlineCacheIndex);
  965. break;
  966. case OpCode::ProfiledStLocalFld:
  967. case OpCode::ProfiledInitLocalFld:
  968. Output::Print(_u(" %s = R%d #%d"), pPropertyName->GetBuffer(), data->Value, data->inlineCacheIndex);
  969. DumpProfileId(data->inlineCacheIndex);
  970. break;
  971. default:
  972. {
  973. AssertMsg(false, "Unknown OpCode for OpLayoutElementP");
  974. break;
  975. }
  976. }
  977. }
  978. template <class T>
  979. void ByteCodeDumper::DumpElementPIndexed(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  980. {
  981. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  982. PropertyId propertyId = dumpFunction->GetPropertyIdFromCacheId(data->inlineCacheIndex);
  983. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(propertyId);
  984. switch (op)
  985. {
  986. case OpCode::InitInnerFld:
  987. case OpCode::InitInnerLetFld:
  988. case OpCode::InitUndeclLetFld:
  989. case OpCode::InitUndeclConstFld:
  990. Output::Print(_u(" [%d].%s = R%d #%d"), data->scopeIndex, pPropertyName->GetBuffer(), data->Value, data->inlineCacheIndex);
  991. break;
  992. default:
  993. {
  994. AssertMsg(false, "Unknown OpCode for OpLayoutElementPIndexed");
  995. break;
  996. }
  997. }
  998. }
  999. template <class T>
  1000. void ByteCodeDumper::DumpElementCP(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  1001. {
  1002. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  1003. PropertyId propertyId = dumpFunction->GetPropertyIdFromCacheId(data->inlineCacheIndex);
  1004. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(propertyId);
  1005. switch (op)
  1006. {
  1007. case OpCode::LdLen_A:
  1008. case OpCode::LdFldForTypeOf:
  1009. case OpCode::LdFld:
  1010. case OpCode::LdFld_ReuseLoc:
  1011. case OpCode::LdFldForCallApplyTarget:
  1012. case OpCode::LdMethodFld:
  1013. case OpCode::ScopedLdMethodFld:
  1014. {
  1015. Output::Print(_u(" R%d = R%d.%s #%d"), data->Value, data->Instance,
  1016. pPropertyName->GetBuffer(), data->inlineCacheIndex);
  1017. break;
  1018. }
  1019. case OpCode::InitFld:
  1020. case OpCode::InitLetFld:
  1021. case OpCode::InitConstFld:
  1022. case OpCode::StFld:
  1023. case OpCode::StFldStrict:
  1024. case OpCode::InitClassMember:
  1025. {
  1026. Output::Print(_u(" R%d.%s = R%d #%d"), data->Instance, pPropertyName->GetBuffer(),
  1027. data->Value, data->inlineCacheIndex);
  1028. break;
  1029. }
  1030. case OpCode::ProfiledLdFldForTypeOf:
  1031. case OpCode::ProfiledLdFld:
  1032. case OpCode::ProfiledLdFld_ReuseLoc:
  1033. case OpCode::ProfiledLdFldForCallApplyTarget:
  1034. case OpCode::ProfiledLdMethodFld:
  1035. {
  1036. Output::Print(_u(" R%d = R%d.%s #%d"), data->Value, data->Instance,
  1037. pPropertyName->GetBuffer(), data->inlineCacheIndex);
  1038. DumpProfileId(data->inlineCacheIndex);
  1039. break;
  1040. }
  1041. case OpCode::ProfiledInitFld:
  1042. case OpCode::ProfiledStFld:
  1043. case OpCode::ProfiledStFldStrict:
  1044. {
  1045. Output::Print(_u(" R%d.%s = R%d #%d"), data->Instance, pPropertyName->GetBuffer(),
  1046. data->Value, data->inlineCacheIndex);
  1047. DumpProfileId(data->inlineCacheIndex);
  1048. break;
  1049. }
  1050. default:
  1051. {
  1052. AssertMsg(false, "Unknown OpCode for OpLayoutElementCP");
  1053. break;
  1054. }
  1055. }
  1056. }
  1057. template <class T>
  1058. void ByteCodeDumper::DumpElementRootCP(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  1059. {
  1060. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  1061. PropertyId propertyId = dumpFunction->GetPropertyIdFromCacheId(data->inlineCacheIndex);
  1062. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(propertyId);
  1063. switch (op)
  1064. {
  1065. case OpCode::LdRootFld:
  1066. case OpCode::LdRootMethodFld:
  1067. case OpCode::LdRootFldForTypeOf:
  1068. {
  1069. Output::Print(_u(" R%d = root.%s #%d"), data->Value,
  1070. pPropertyName->GetBuffer(), data->inlineCacheIndex);
  1071. break;
  1072. }
  1073. case OpCode::InitRootFld:
  1074. case OpCode::InitRootLetFld:
  1075. case OpCode::InitRootConstFld:
  1076. case OpCode::StRootFld:
  1077. case OpCode::StRootFldStrict:
  1078. {
  1079. Output::Print(_u(" root.%s = R%d #%d"), pPropertyName->GetBuffer(),
  1080. data->Value, data->inlineCacheIndex);
  1081. break;
  1082. }
  1083. case OpCode::ProfiledLdRootFld:
  1084. case OpCode::ProfiledLdRootFldForTypeOf:
  1085. case OpCode::ProfiledLdRootMethodFld:
  1086. {
  1087. Output::Print(_u(" R%d = root.%s #%d"), data->Value,
  1088. pPropertyName->GetBuffer(), data->inlineCacheIndex);
  1089. DumpProfileId(data->inlineCacheIndex);
  1090. break;
  1091. }
  1092. case OpCode::ProfiledInitRootFld:
  1093. case OpCode::ProfiledStRootFld:
  1094. case OpCode::ProfiledStRootFldStrict:
  1095. {
  1096. Output::Print(_u(" root.%s = R%d #%d"), pPropertyName->GetBuffer(),
  1097. data->Value, data->inlineCacheIndex);
  1098. DumpProfileId(data->inlineCacheIndex);
  1099. break;
  1100. }
  1101. default:
  1102. {
  1103. AssertMsg(false, "Unknown OpCode for OpLayoutElementRootCP");
  1104. break;
  1105. }
  1106. }
  1107. }
  1108. template <class T>
  1109. void ByteCodeDumper::DumpElementUnsigned1(OpCode op, const unaligned T * data, Js::FunctionBody * dumpFunction, ByteCodeReader& reader)
  1110. {
  1111. switch (op)
  1112. {
  1113. case OpCode::StArrItemC_CI4:
  1114. case OpCode::StArrItemI_CI4:
  1115. case OpCode::StArrSegItem_CI4:
  1116. case OpCode::StArrInlineItem_CI4:
  1117. Output::Print(_u(" R%d["), data->Instance);
  1118. DumpI4(data->Element);
  1119. Output::Print(_u("] = R%d"), data->Value);
  1120. break;
  1121. default:
  1122. AssertMsg(false, "Unknown OpCode for OpLayoutElementUnsigned1");
  1123. break;
  1124. }
  1125. }
  1126. template <class T>
  1127. void ByteCodeDumper::DumpArg(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1128. {
  1129. switch (op)
  1130. {
  1131. case OpCode::ProfiledArgOut_A:
  1132. case OpCode::ArgOut_A:
  1133. case OpCode::ArgOut_ANonVar:
  1134. {
  1135. Output::Print(_u(" Out%d ="), (int) data->Arg);
  1136. DumpReg(data->Reg);
  1137. break;
  1138. }
  1139. default:
  1140. {
  1141. AssertMsg(false, "Unknown OpCode for OpLayoutArg");
  1142. break;
  1143. }
  1144. }
  1145. }
  1146. template <class T>
  1147. void ByteCodeDumper::DumpArgNoSrc(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1148. {
  1149. switch (op)
  1150. {
  1151. case Js::OpCode::ArgOut_Env:
  1152. {
  1153. Output::Print(_u(" Out%d "), (int) data->Arg);
  1154. break;
  1155. }
  1156. default:
  1157. {
  1158. AssertMsg(false, "Unknown OpCode for OpLayoutArgNoSrc");
  1159. break;
  1160. }
  1161. }
  1162. }
  1163. void
  1164. ByteCodeDumper::DumpStartCall(OpCode op, const unaligned OpLayoutStartCall * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1165. {
  1166. Assert(op == OpCode::StartCall );
  1167. Output::Print(_u(" ArgCount: %d"), data->ArgCount);
  1168. }
  1169. template <class T> void
  1170. ByteCodeDumper::DumpUnsigned1(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1171. {
  1172. DumpU4(data->C1);
  1173. }
  1174. template <class T> void
  1175. ByteCodeDumper::DumpReg1(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1176. {
  1177. DumpReg(data->R0);
  1178. }
  1179. template <class T> void
  1180. ByteCodeDumper::DumpReg2(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1181. {
  1182. DumpReg(data->R0);
  1183. DumpReg(data->R1);
  1184. }
  1185. template <class T> void
  1186. ByteCodeDumper::DumpReg3(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1187. {
  1188. switch (op)
  1189. {
  1190. case OpCode::NewInnerScopeSlots:
  1191. Output::Print(_u(" [%d], %d, %d "), data->R0, data->R1, data->R2);
  1192. break;
  1193. default:
  1194. DumpReg(data->R0);
  1195. DumpReg(data->R1);
  1196. DumpReg(data->R2);
  1197. break;
  1198. }
  1199. }
  1200. template <class T> void
  1201. ByteCodeDumper::DumpReg3C(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1202. {
  1203. switch (op)
  1204. {
  1205. case OpCode::IsInst:
  1206. Output::Print(_u("R%d = R%d instanceof R%d #%d"),
  1207. data->R0, data->R1, data->R2, data->inlineCacheIndex);
  1208. break;
  1209. default:
  1210. AssertMsg(false, "Unknown OpCode for OpLayoutReg3C");
  1211. }
  1212. }
  1213. template <class T> void
  1214. ByteCodeDumper::DumpReg4(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1215. {
  1216. DumpReg(data->R0);
  1217. DumpReg(data->R1);
  1218. DumpReg(data->R2);
  1219. DumpReg(data->R3);
  1220. }
  1221. template <class T> void
  1222. ByteCodeDumper::DumpReg2U(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1223. {
  1224. switch (op)
  1225. {
  1226. case Js::OpCode::InitBaseClass:
  1227. {
  1228. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  1229. Output::Print(_u(" R%d, R%d = %s()"), data->R0, data->R1, pfuncActual->EnsureDeserialized()->GetDisplayName());
  1230. break;
  1231. }
  1232. default:
  1233. DumpReg(data->R0);
  1234. DumpReg(data->R1);
  1235. break;
  1236. }
  1237. }
  1238. template <class T> void
  1239. ByteCodeDumper::DumpReg2B1(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1240. {
  1241. DumpReg(data->R0);
  1242. DumpReg(data->R1);
  1243. DumpI4(data->B2);
  1244. }
  1245. template <class T> void
  1246. ByteCodeDumper::DumpReg3B1(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1247. {
  1248. DumpReg(data->R0);
  1249. DumpReg(data->R1);
  1250. DumpReg(data->R2);
  1251. DumpI4(data->B3);
  1252. }
  1253. template <class T> void
  1254. ByteCodeDumper::DumpReg3U(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1255. {
  1256. switch (op)
  1257. {
  1258. case Js::OpCode::InitInnerBaseClass:
  1259. {
  1260. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  1261. Output::Print(_u(" R%d, R%d = %s(), env:R%d"), data->R0, data->R1, pfuncActual->EnsureDeserialized()->GetDisplayName(), data->R2);
  1262. break;
  1263. }
  1264. default:
  1265. AssertMsg(false, "Unknown Reg3U opcode");
  1266. break;
  1267. }
  1268. }
  1269. template <class T> void
  1270. ByteCodeDumper::DumpReg4U(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1271. {
  1272. switch (op)
  1273. {
  1274. case Js::OpCode::InitClass:
  1275. {
  1276. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  1277. Output::Print(_u(" R%d, R%d = R%d, R%d, %s()"), data->R0, data->R1, data->R2, data->R3,
  1278. pfuncActual->EnsureDeserialized()->GetDisplayName());
  1279. break;
  1280. }
  1281. default:
  1282. AssertMsg(false, "Unknown Reg4U opcode");
  1283. break;
  1284. }
  1285. }
  1286. template <class T> void
  1287. ByteCodeDumper::DumpReg5(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1288. {
  1289. DumpReg(data->R0);
  1290. DumpReg(data->R1);
  1291. DumpReg(data->R2);
  1292. DumpReg(data->R3);
  1293. DumpReg(data->R4);
  1294. }
  1295. template <class T> void
  1296. ByteCodeDumper::DumpReg5U(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1297. {
  1298. switch (op)
  1299. {
  1300. case Js::OpCode::InitInnerClass:
  1301. {
  1302. FunctionProxy* pfuncActual = dumpFunction->GetNestedFunctionProxy((uint)data->SlotIndex);
  1303. Output::Print(_u(" R%d, R%d = R%d, R%d, %s(), env:R%d"), data->R0, data->R1, data->R2, data->R3,
  1304. pfuncActual->EnsureDeserialized()->GetDisplayName(), data->R4);
  1305. break;
  1306. }
  1307. default:
  1308. AssertMsg(false, "Unknown Reg5U opcode");
  1309. break;
  1310. }
  1311. }
  1312. void
  1313. ByteCodeDumper::DumpW1(OpCode op, const unaligned OpLayoutW1 * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1314. {
  1315. DumpU2(data->C1);
  1316. }
  1317. void
  1318. ByteCodeDumper::DumpAuxNoReg(OpCode op, const unaligned OpLayoutAuxNoReg * playout, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1319. {
  1320. switch (op)
  1321. {
  1322. case Js::OpCode::InitCachedFuncs:
  1323. {
  1324. const Js::FuncInfoArray *arr = reader.ReadAuxArray<FuncInfoEntry>(playout->Offset, dumpFunction);
  1325. Output::Print(_u(" %d ["), arr->count);
  1326. for (uint i = 0; i < arr->count && i < 3; i++)
  1327. {
  1328. Js::ParseableFunctionInfo *info = dumpFunction->GetNestedFunctionForExecution(arr->elements[i].nestedIndex);
  1329. if (i != 0)
  1330. {
  1331. Output::Print(_u(", "));
  1332. }
  1333. Output::Print(_u("%s"), info->GetDisplayName());
  1334. }
  1335. Output::Print(_u("]"));
  1336. break;
  1337. }
  1338. default:
  1339. AssertMsg(false, "Unknown OpCode for OpLayoutType::AuxNoReg");
  1340. break;
  1341. }
  1342. }
  1343. void
  1344. ByteCodeDumper::DumpAuxiliary(OpCode op, const unaligned OpLayoutAuxiliary * playout, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1345. {
  1346. switch (op)
  1347. {
  1348. case OpCode::NewScObjectLiteral:
  1349. case OpCode::LdPropIds:
  1350. {
  1351. const Js::PropertyIdArray *propIds = reader.ReadPropertyIdArray(playout->Offset, dumpFunction);
  1352. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  1353. DumpReg(playout->R0);
  1354. Output::Print(_u("= %d ["), propIds->count);
  1355. for (uint i=0; i< propIds->count && i < 3; i++)
  1356. {
  1357. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(propIds->elements[i]);
  1358. if (i != 0)
  1359. {
  1360. Output::Print(_u(", "));
  1361. }
  1362. Output::Print(_u("%s"), pPropertyName->GetBuffer());
  1363. }
  1364. if (propIds->count >= 3)
  1365. {
  1366. Output::Print(_u(", ..."));
  1367. }
  1368. Output::Print(_u("], LiteralId %d"), playout->C1);
  1369. break;
  1370. }
  1371. case OpCode::StArrSegItem_A:
  1372. {
  1373. const Js::VarArray *vars = reader.ReadAuxArray<Var>(playout->Offset, dumpFunction);
  1374. DumpReg(playout->R0);
  1375. Output::Print(_u("= %d ["), vars->count);
  1376. uint i=0;
  1377. for (; i<vars->count && i < 3; i++)
  1378. {
  1379. if (i != 0)
  1380. {
  1381. Output::Print(_u(", "));
  1382. }
  1383. Output::Print(_u("%d"), vars->elements[i]);
  1384. }
  1385. if (i != vars->count)
  1386. {
  1387. Output::Print(_u(", ..."));
  1388. }
  1389. Output::Print(_u("]"));
  1390. break;
  1391. }
  1392. case OpCode::NewScIntArray:
  1393. {
  1394. const Js::AuxArray<int32> *intArray = reader.ReadAuxArray<int32>(playout->Offset, dumpFunction);
  1395. Output::Print(_u(" R%d = %d ["), playout->R0, intArray->count);
  1396. uint i;
  1397. for (i = 0; i<intArray->count && i < 3; i++)
  1398. {
  1399. if (i != 0)
  1400. {
  1401. Output::Print(_u(", "));
  1402. }
  1403. Output::Print(_u("%d"), intArray->elements[i]);
  1404. }
  1405. if (i != intArray->count)
  1406. {
  1407. Output::Print(_u(", ..."));
  1408. }
  1409. Output::Print(_u("]"));
  1410. break;
  1411. }
  1412. case OpCode::NewScFltArray:
  1413. {
  1414. const Js::AuxArray<double> *dblArray = reader.ReadAuxArray<double>(playout->Offset, dumpFunction);
  1415. Output::Print(_u(" R%d = %d ["), playout->R0, dblArray->count);
  1416. uint i;
  1417. for (i = 0; i<dblArray->count && i < 3; i++)
  1418. {
  1419. if (i != 0)
  1420. {
  1421. Output::Print(_u(", "));
  1422. }
  1423. Output::Print(_u("%f"), dblArray->elements[i]);
  1424. }
  1425. if (i != dblArray->count)
  1426. {
  1427. Output::Print(_u(", ..."));
  1428. }
  1429. Output::Print(_u("]"));
  1430. break;
  1431. }
  1432. case OpCode::NewScObject_A:
  1433. {
  1434. const Js::VarArrayVarCount *vars = reader.ReadVarArrayVarCount(playout->Offset, dumpFunction);
  1435. DumpReg(playout->R0);
  1436. int count = Js::TaggedInt::ToInt32(vars->count);
  1437. Output::Print(_u("= %d ["), count);
  1438. int i=0;
  1439. for (; i<count && i < 3; i++)
  1440. {
  1441. if (i != 0)
  1442. {
  1443. Output::Print(_u(", "));
  1444. }
  1445. if (TaggedInt::Is(vars->elements[i]))
  1446. {
  1447. Output::Print(_u("%d"), TaggedInt::ToInt32(vars->elements[i]));
  1448. }
  1449. else if (JavascriptNumber::Is(vars->elements[i]))
  1450. {
  1451. Output::Print(_u("%g"), JavascriptNumber::GetValue(vars->elements[i]));
  1452. }
  1453. else
  1454. {
  1455. Assert(false);
  1456. }
  1457. }
  1458. if (i != count)
  1459. {
  1460. Output::Print(_u(", ..."));
  1461. }
  1462. Output::Print(_u("]"));
  1463. break;
  1464. }
  1465. default:
  1466. AssertMsg(false, "Unknown OpCode for OpLayoutType::Auxiliary");
  1467. break;
  1468. }
  1469. }
  1470. void
  1471. ByteCodeDumper::DumpReg2Aux(OpCode op, const unaligned OpLayoutReg2Aux * playout, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1472. {
  1473. switch (op)
  1474. {
  1475. case Js::OpCode::SpreadArrayLiteral:
  1476. {
  1477. const Js::AuxArray<uint32> *arr = reader.ReadAuxArray<uint32>(playout->Offset, dumpFunction);
  1478. Output::Print(_u(" R%u <- R%u, %u spreadArgs ["), playout->R0, playout->R1, arr->count);
  1479. for (uint i = 0; i < arr->count; i++)
  1480. {
  1481. if (i > 10)
  1482. {
  1483. Output::Print(_u(", ..."));
  1484. break;
  1485. }
  1486. if (i != 0)
  1487. {
  1488. Output::Print(_u(", "));
  1489. }
  1490. Output::Print(_u("%u"), arr->elements[i]);
  1491. }
  1492. Output::Print(_u("]"));
  1493. break;
  1494. }
  1495. default:
  1496. AssertMsg(false, "Unknown OpCode for OpLayoutType::Reg2Aux");
  1497. break;
  1498. }
  1499. }
  1500. #ifdef BYTECODE_BRANCH_ISLAND
  1501. void ByteCodeDumper::DumpBrLong(OpCode op, const unaligned OpLayoutBrLong* data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1502. {
  1503. DumpOffset(data->RelativeJumpOffset, reader);
  1504. }
  1505. #endif
  1506. void ByteCodeDumper::DumpBr(OpCode op, const unaligned OpLayoutBr * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1507. {
  1508. DumpOffset(data->RelativeJumpOffset, reader);
  1509. }
  1510. void ByteCodeDumper::DumpBrS(OpCode op, const unaligned OpLayoutBrS * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1511. {
  1512. DumpOffset(data->RelativeJumpOffset, reader);
  1513. DumpI4(data->val);
  1514. }
  1515. template <class T>
  1516. void ByteCodeDumper::DumpBrReg1(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1517. {
  1518. DumpOffset(data->RelativeJumpOffset, reader);
  1519. DumpReg(data->R1);
  1520. }
  1521. template <class T>
  1522. void ByteCodeDumper::DumpBrReg1Unsigned1(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1523. {
  1524. DumpOffset(data->RelativeJumpOffset, reader);
  1525. DumpReg(data->R1);
  1526. DumpU4(data->C2);
  1527. }
  1528. template <class T>
  1529. void ByteCodeDumper::DumpBrReg2(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1530. {
  1531. DumpOffset(data->RelativeJumpOffset, reader);
  1532. DumpReg(data->R1);
  1533. DumpReg(data->R2);
  1534. }
  1535. void ByteCodeDumper::DumpBrProperty(OpCode op, const unaligned OpLayoutBrProperty * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1536. {
  1537. DumpOffset(data->RelativeJumpOffset, reader);
  1538. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  1539. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  1540. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  1541. Output::Print(_u("R%d.%s"), data->Instance, pPropertyName->GetBuffer());
  1542. }
  1543. void ByteCodeDumper::DumpBrLocalProperty(OpCode op, const unaligned OpLayoutBrLocalProperty * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1544. {
  1545. DumpOffset(data->RelativeJumpOffset, reader);
  1546. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  1547. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  1548. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  1549. Output::Print(_u("%s"), pPropertyName->GetBuffer());
  1550. }
  1551. void ByteCodeDumper::DumpBrEnvProperty(OpCode op, const unaligned OpLayoutBrEnvProperty * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
  1552. {
  1553. DumpOffset(data->RelativeJumpOffset, reader);
  1554. ScriptContext* scriptContext = dumpFunction->GetScriptContext();
  1555. PropertyRecord const * pPropertyName = scriptContext->GetPropertyName(
  1556. dumpFunction->GetReferencedPropertyId(data->PropertyIdIndex));
  1557. Output::Print(_u("[%d].%s"), data->SlotIndex, pPropertyName->GetBuffer());
  1558. }
  1559. void ByteCodeDumper::DumpOp(OpCode op, LayoutSize layoutSize, ByteCodeReader& reader, FunctionBody* dumpFunction)
  1560. {
  1561. Output::Print(_u("%-20s"), OpCodeUtil::GetOpCodeName(op));
  1562. OpLayoutType nType = OpCodeUtil::GetOpCodeLayout(op);
  1563. switch (layoutSize * OpLayoutType::Count + nType)
  1564. {
  1565. #define LAYOUT_TYPE(layout) \
  1566. case OpLayoutType::layout: \
  1567. Assert(layoutSize == SmallLayout); \
  1568. Dump##layout(op, reader.layout(), dumpFunction, reader); \
  1569. break;
  1570. #define LAYOUT_SCHEMA(type, layout) \
  1571. case type##Layout * OpLayoutType::Count + OpLayoutType::layout: \
  1572. Dump##layout(op, reader.layout##_##type(), dumpFunction, reader); \
  1573. break
  1574. #define LAYOUT_TYPE_WMS(layout) \
  1575. LAYOUT_SCHEMA(Small, layout); \
  1576. LAYOUT_SCHEMA(Medium, layout); \
  1577. LAYOUT_SCHEMA(Large, layout);
  1578. #define LAYOUT_TYPE_PROFILED_WMS(layout) \
  1579. LAYOUT_TYPE_WMS(Profiled##layout) \
  1580. LAYOUT_TYPE_WMS(layout)
  1581. #include "LayoutTypes.h"
  1582. default:
  1583. {
  1584. AssertMsg(false, "Unknown OpLayout");
  1585. break;
  1586. }
  1587. }
  1588. }
  1589. } // namespace Js
  1590. #endif