1. // memory manager. shares pages across many basic blocks.
    
  2. #include <vector>
    
  3. 
    
  4. using std::vector;
    
  5. 
    
  6. 
    
  7. // Provides blocks
    
  8. class MM {
    
  9. public:
    
  10.     MM() {
    
  11.         PAGE_SIZE_ = getpagesize();
    
  12.     }
    
  13. 
    
  14.     // alloc into a page aligned buffer or fail.
    
  15.     void alloc(void** output, int bytes) {
    
  16.         if (page_capacity_ < bytes) {
    
  17.             new_page(bytes);
    
  18.         }
    
  19.         (*output) = (void*)page_offset_;
    
  20.         page_offset_ += bytes;
    
  21.         page_capacity_ -= bytes;
    
  22.             
    
  23.     }
    
  24. private:
    
  25.     void new_page(int requested) {
    
  26.         int bytes = requested < PAGE_SIZE_ ? PAGE_SIZE_ : requested;
    
  27.         if (posix_memalign((void**)&page_, PAGE_SIZE_, bytes) != 0) {
    
  28.             puts("memalign failed");
    
  29.             exit(1);
    
  30.         }
    
  31.         if (page_ < 0) {
    
  32.             perror("memalign fail: ");
    
  33.             exit(1);
    
  34.         }
    
  35.         // NOTE: not w^x friendly, pages are both
    
  36.         // writable and executable.
    
  37.         if (mprotect((void*)page_, bytes, PROT_EXEC | PROT_READ | PROT_WRITE) < 0) {
    
  38.             perror("failed to mprotect");
    
  39.             exit(1);
    
  40.         }
    
  41.         page_capacity_ = bytes;
    
  42.         page_offset_ = page_;
    
  43.     }
    
  44. 
    
  45.     int PAGE_SIZE_;
    
  46.     char* page_ = nullptr;
    
  47.     char* page_offset_ = nullptr;
    
  48.     int page_capacity_ = 0;
    
  49. 
    
  50. };