ByteCodeDumper.cpp 58 KB

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