Region.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. #pragma once
  6. enum RegionType : BYTE
  7. {
  8. RegionTypeInvalid,
  9. RegionTypeRoot,
  10. RegionTypeTry,
  11. RegionTypeCatch,
  12. RegionTypeFinally
  13. };
  14. class Region
  15. {
  16. public:
  17. Region() : type(RegionTypeInvalid),
  18. parent(NULL), matchingTryRegion(nullptr), matchingCatchRegion(nullptr), matchingFinallyOnExceptRegion(nullptr), matchingFinallyOnNoExceptRegion(nullptr), selfOrFirstTryAncestor(nullptr),
  19. start(NULL), end(NULL),
  20. writeThroughSymbolsSet(nullptr),
  21. ehBailoutData(nullptr), bailoutReturnThunkLabel(nullptr), returnThunkEmitted(false),
  22. exceptionObjectSym(nullptr) {}
  23. static Region * New(RegionType, Region *, Func *);
  24. public:
  25. inline RegionType GetType() const { return this->type; }
  26. inline void SetType(RegionType type) { this->type = type; }
  27. inline Region * GetParent() const { return this->parent; }
  28. inline void SetParent(Region* parent) { this->parent = parent; }
  29. inline Region * GetMatchingTryRegion() const { return this->matchingTryRegion; }
  30. inline void SetMatchingTryRegion(Region* tryRegion) { this->matchingTryRegion = tryRegion; }
  31. inline Region * GetMatchingCatchRegion() const { return this->matchingCatchRegion; }
  32. inline void SetMatchingCatchRegion(Region* catchRegion) { this->matchingCatchRegion = catchRegion; }
  33. inline Region * GetMatchingFinallyRegion(bool isExcept) const
  34. {
  35. return isExcept ? this->matchingFinallyOnExceptRegion : this->matchingFinallyOnNoExceptRegion;
  36. }
  37. inline void SetMatchingFinallyRegion(Region* finallyRegion, bool isExcept)
  38. {
  39. if (isExcept)
  40. {
  41. this->matchingFinallyOnExceptRegion = finallyRegion;
  42. }
  43. else
  44. {
  45. this->matchingFinallyOnNoExceptRegion = finallyRegion;
  46. }
  47. }
  48. bool IsNonExceptingFinally()
  49. {
  50. return (this->GetType() == RegionTypeFinally && this->GetMatchingTryRegion()->GetMatchingFinallyRegion(false) == this);
  51. }
  52. inline IR::Instr * GetStart() const { return this->start; }
  53. inline void SetStart(IR::Instr * instr) { this->start = instr; }
  54. inline IR::Instr * GetEnd() const { return this->end; }
  55. inline void SetEnd(IR::Instr * instr) { this->end = instr; }
  56. inline IR::LabelInstr * GetBailoutReturnThunkLabel() const { return this->bailoutReturnThunkLabel; }
  57. inline StackSym * GetExceptionObjectSym() const { return this->exceptionObjectSym; }
  58. inline void SetExceptionObjectSym(StackSym * sym) { this->exceptionObjectSym = sym; }
  59. void AllocateEHBailoutData(Func * func, IR::Instr * tryInstr);
  60. Region * GetSelfOrFirstTryAncestor();
  61. Region * GetFirstAncestorOfNonExceptingFinallyParent();
  62. Region * GetFirstAncestorOfNonExceptingFinally();
  63. bool CheckWriteThroughSym(StackSym * sym);
  64. private:
  65. RegionType type;
  66. Region * parent;
  67. Region * matchingTryRegion;
  68. Region * matchingCatchRegion;
  69. Region * matchingFinallyOnExceptRegion;
  70. Region * matchingFinallyOnNoExceptRegion;
  71. // We need to mark a non-expecting finally region we execute in the JIT, as in EH region.
  72. // We can bailout from the non excepting EH region, in that case we need ehBailoutData to reconstruct eh frames in the interpreter
  73. Region * selfOrFirstTryAncestor; // = self, if try region, otherwise
  74. // = first try ancestor
  75. IR::Instr * start;
  76. IR::Instr * end;
  77. StackSym * exceptionObjectSym;
  78. IR::LabelInstr * bailoutReturnThunkLabel;
  79. // bailoutReturnThunkLabel is the Label denoting start of return thunk for this region.
  80. // The JIT'ed code of a function having EH may have multiple frames on the stack, pertaining to the JIT'ed code and the TryCatch helper.
  81. // After a bailout in an EH region, we want to jump to the epilog of the function, but we have to do this via a series of returns (to clear out the frames on the stack).
  82. // To achieve this, post bailout, we jump to the return thunk of that region, which loads the appropriate return address into eax and executes a RET.
  83. // This has the effect of returning that address to the TryCatch helper, which, in turn, returns it to its caller JIT'ed code.
  84. // Non-top-level EH regions return the address of their parent's return thunk, and top level EH regions return the address
  85. // where the return value from a bailout is loaded into eax (restoreReturnValueFromBailoutLabel in EHBailoutPatchUp::Emit).
  86. // (Control should go to a return thunk only in case of a bailout from an EH region.)
  87. public:
  88. BVSparse<JitArenaAllocator> * writeThroughSymbolsSet;
  89. Js::EHBailoutData * ehBailoutData;
  90. bool returnThunkEmitted;
  91. };