CodeBlock.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright 2014 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include "Common/Common.h"
  6. #include "Common/MemoryUtil.h"
  7. // Everything that needs to generate code should inherit from this.
  8. // You get memory management for free, plus, you can use all emitter functions without
  9. // having to prefix them with gen-> or something similar.
  10. // Example implementation:
  11. // class JIT : public CodeBlock<ARMXEmitter> {}
  12. template<class T> class CodeBlock : public T, NonCopyable
  13. {
  14. private:
  15. // A privately used function to set the executable RAM space to something invalid.
  16. // For debugging usefulness it should be used to set the RAM to a host specific breakpoint instruction
  17. virtual void PoisonMemory() = 0;
  18. protected:
  19. u8 *region;
  20. size_t region_size;
  21. public:
  22. CodeBlock() : region(nullptr), region_size(0) {}
  23. virtual ~CodeBlock() { if (region) FreeCodeSpace(); }
  24. // Call this before you generate any code.
  25. void AllocCodeSpace(int size, bool need_low = true)
  26. {
  27. region_size = size;
  28. region = (u8*)AllocateExecutableMemory(region_size, need_low);
  29. T::SetCodePtr(region);
  30. }
  31. // Always clear code space with breakpoints, so that if someone accidentally executes
  32. // uninitialized, it just breaks into the debugger.
  33. void ClearCodeSpace()
  34. {
  35. PoisonMemory();
  36. ResetCodePtr();
  37. }
  38. // Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
  39. void FreeCodeSpace()
  40. {
  41. FreeMemoryPages(region, region_size);
  42. region = nullptr;
  43. region_size = 0;
  44. }
  45. bool IsInSpace(u8 *ptr) const
  46. {
  47. return (ptr >= region) && (ptr < (region + region_size));
  48. }
  49. // Cannot currently be undone. Will write protect the entire code region.
  50. // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
  51. void WriteProtect()
  52. {
  53. WriteProtectMemory(region, region_size, true);
  54. }
  55. void ResetCodePtr()
  56. {
  57. T::SetCodePtr(region);
  58. }
  59. size_t GetSpaceLeft() const
  60. {
  61. return region_size - (T::GetCodePtr() - region);
  62. }
  63. };