// File: obliviousram[P]PathOHeap/src/JobForStatisticalSimulation.cpp
// Function: JobForStatisticalSimulation::run()
void JobForStatisticalSimulation::run() {
  int bucket_size = 2;
  int num_blocks = pow(2, 20);
  const int frequency = 500000;

  std::array<std::byte, Block::BLOCK_SIZE> sample_data;
  sample_data.fill(std::byte{0xa});

  UntrustedStorageInterface* storage = new ServerStorage();
  RandForOHeapInterface* random = new RandomForOHeap();
  OHeapInterface* oheap = new OHeapReadPathEviction(storage, random, bucket_size, num_blocks, false);

  std::cout << "Warming up" << std::endl;
  // do inserts until heap is full, then increaseKeys
  
  // as with Job2, need to keep around leaves and ts
  auto leaves = std::vector<int>();
  auto ts = std::vector<int>();

  for (int i = 1; i <= 3000000; i++) {
    if (i <= num_blocks) {
      std::pair<int, int> leaf_t = oheap->insertBlock(i, sample_data);
      leaves.push_back(leaf_t.first);
      ts.push_back(leaf_t.second);
    } else {
      std::pair<int, int> leaf_t = oheap->increaseKey(leaves.at(i % num_blocks), ts.at(i % num_blocks));
      leaves.at(i % num_blocks) = leaf_t.first;
      ts.at(i % num_blocks) = leaf_t.second;
    }

    if (i % frequency == 0) {
      std::cout << "Accesses made: " << i << std::endl;
    }
  }

  std::cout << "Start recording..." << std::endl;

  int max_stash_size = 0;
  auto histogram = std::unordered_map<int, int>();
  int stash_size;

  for (int i = 1; i <= 500000000; i++) {
    std::pair<int, int> leaf_t = oheap->increaseKey(leaves.at(i % num_blocks), ts.at(i % num_blocks));
    leaves.at(i % num_blocks) = leaf_t.first;
    ts.at(i % num_blocks) = leaf_t.second;

    stash_size = oheap->getStashSize();
    if (histogram.find(stash_size) != histogram.end()) {
      histogram[stash_size]++;
    } else {
      histogram[stash_size] = 1;
    }

    max_stash_size = (stash_size > max_stash_size) ? stash_size : max_stash_size;
    
    if (i % frequency == 0) {
      std::cout << "Accesses made (after warmup): " << i << std::endl;

      for (int i = 0; i <= max_stash_size; i++) {
        if (histogram.find(i) != histogram.end()) {
          std::cout << i << "," << histogram[i] << std::endl;
        } else {
          std::cout << i << ",0" << std::endl;
        }
      }
    }
  }

  delete oheap;
  delete random;
  delete storage;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2b0, %rsp            # imm = 0x2B0
movl $0x2, -0x4(%rbp)
movsd 0xaa0e(%rip), %xmm0     # 0x100e8
movsd 0xaac6(%rip), %xmm1     # 0x101a8
callq 0x2290
cvttsd2si %xmm0, %eax
movl %eax, -0x8(%rbp)
movl $0x7a120, -0xc(%rbp)    # imm = 0x7A120
movb $0xa, -0x2d(%rbp)
leaq -0x2c(%rbp), %rdi
leaq -0x2d(%rbp), %rsi
callq 0x2920
movl $0x28, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x148(%rbp)
callq 0xd5a0
jmp 0x5724
movq -0x148(%rbp), %rax
movq %rax, -0x38(%rbp)
movl $0x20, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x150(%rbp)
callq 0xd200
jmp 0x574d
movq -0x150(%rbp), %rax
movq %rax, -0x50(%rbp)
movl $0x58, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x158(%rbp)
movq -0x38(%rbp), %rsi
movq -0x50(%rbp), %rdx
movl -0x4(%rbp), %ecx
movl -0x8(%rbp), %r8d
xorl %r9d, %r9d
callq 0x7970
jmp 0x5788
movq -0x158(%rbp), %rax
movq %rax, -0x58(%rbp)
movq 0x12836(%rip), %rdi     # 0x17fd0
leaq 0xaa13(%rip), %rsi      # 0x101b4
callq 0x2180
movq %rax, %rdi
movq 0x12800(%rip), %rsi     # 0x17fb0
callq 0x21b0
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x20f0
leaq -0x70(%rbp), %rdi
callq 0x4bf0
leaq -0x88(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x20f0
leaq -0x88(%rbp), %rdi
callq 0x4bf0
movl $0x1, -0x8c(%rbp)
cmpl $0x2dc6c0, -0x8c(%rbp)  # imm = 0x2DC6C0
jg 0x5a99
movl -0x8c(%rbp), %eax
cmpl -0x8(%rbp), %eax
jg 0x5911
movq -0x58(%rbp), %rdi
movl -0x8c(%rbp), %esi
movups -0x2c(%rbp), %xmm0
movups -0x1c(%rbp), %xmm1
movaps %xmm1, -0xb0(%rbp)
movaps %xmm0, -0xc0(%rbp)
movq (%rdi), %rax
movq 0x8(%rax), %rax
movaps -0xc0(%rbp), %xmm0
movaps -0xb0(%rbp), %xmm1
movq %rsp, %rcx
movups %xmm1, 0x10(%rcx)
movups %xmm0, (%rcx)
callq *%rax
movq %rax, -0x160(%rbp)
jmp 0x5860
movq -0x160(%rbp), %rax
movq %rax, -0x94(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x94(%rbp), %rsi
callq 0x4c10
jmp 0x5880
leaq -0x90(%rbp), %rsi
leaq -0x88(%rbp), %rdi
callq 0x4c10
jmp 0x5895
jmp 0x5a22
movq -0x148(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
movl $0x28, %esi
callq 0x21a0
jmp 0x5fbc
movq -0x150(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
movl $0x20, %esi
callq 0x21a0
jmp 0x5fbc
movq -0x158(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
movl $0x58, %esi
callq 0x21a0
jmp 0x5fbc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
jmp 0x5fa7
movq -0x58(%rbp), %rax
movq %rax, -0x170(%rbp)
movl -0x8c(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x70(%rbp), %rdi
callq 0x4c80
movq %rax, -0x168(%rbp)
jmp 0x593d
movq -0x168(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x17c(%rbp)
movl -0x8c(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x88(%rbp), %rdi
callq 0x4c80
movq %rax, -0x178(%rbp)
jmp 0x5970
movl -0x17c(%rbp), %esi
movq -0x170(%rbp), %rdi
movq -0x178(%rbp), %rax
movslq (%rax), %rdx
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
movq %rax, -0x188(%rbp)
jmp 0x5999
movq -0x188(%rbp), %rax
movq %rax, -0xc8(%rbp)
movl -0xc8(%rbp), %eax
movl %eax, -0x194(%rbp)
movl -0x8c(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x70(%rbp), %rdi
callq 0x4c80
movq %rax, -0x190(%rbp)
jmp 0x59d4
movq -0x190(%rbp), %rax
movl -0x194(%rbp), %ecx
movl %ecx, (%rax)
movl -0xc4(%rbp), %eax
movl %eax, -0x1a4(%rbp)
movl -0x8c(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x88(%rbp), %rdi
callq 0x4c80
movq %rax, -0x1a0(%rbp)
jmp 0x5a13
movq -0x1a0(%rbp), %rax
movl -0x1a4(%rbp), %ecx
movl %ecx, (%rax)
movl -0x8c(%rbp), %eax
movl $0x7a120, %ecx          # imm = 0x7A120
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x5a83
movq 0x12594(%rip), %rdi     # 0x17fd0
leaq 0xa77c(%rip), %rsi      # 0x101bf
callq 0x2180
movq %rax, -0x1b0(%rbp)
jmp 0x5a51
movq -0x1b0(%rbp), %rdi
movl -0x8c(%rbp), %esi
callq 0x2280
movq %rax, -0x1b8(%rbp)
jmp 0x5a6c
movq -0x1b8(%rbp), %rdi
movq 0x12536(%rip), %rsi     # 0x17fb0
callq 0x21b0
jmp 0x5a81
jmp 0x5a83
jmp 0x5a85
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x57f7
movq 0x12530(%rip), %rdi     # 0x17fd0
leaq 0xa728(%rip), %rsi      # 0x101cf
callq 0x2180
movq %rax, -0x1c0(%rbp)
jmp 0x5ab5
movq -0x1c0(%rbp), %rdi
movq 0x124ed(%rip), %rsi     # 0x17fb0
callq 0x21b0
jmp 0x5aca
movl $0x0, -0xcc(%rbp)
leaq -0x108(%rbp), %rdi
xorl %esi, %esi
movl $0x38, %edx
callq 0x20f0
leaq -0x108(%rbp), %rdi
callq 0x5fd0
movl $0x1, -0x110(%rbp)
cmpl $0x1dcd6500, -0x110(%rbp) # imm = 0x1DCD6500
jg 0x5f17
movq -0x58(%rbp), %rax
movq %rax, -0x1d0(%rbp)
movl -0x110(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x70(%rbp), %rdi
callq 0x4c80
movq %rax, -0x1c8(%rbp)
jmp 0x5b39
movq -0x1c8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x1dc(%rbp)
movl -0x110(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x88(%rbp), %rdi
callq 0x4c80
movq %rax, -0x1d8(%rbp)
jmp 0x5b6c
movl -0x1dc(%rbp), %esi
movq -0x1d0(%rbp), %rdi
movq -0x1d8(%rbp), %rax
movslq (%rax), %rdx
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
movq %rax, -0x1e8(%rbp)
jmp 0x5b95
movq -0x1e8(%rbp), %rax
movq %rax, -0x118(%rbp)
movl -0x118(%rbp), %eax
movl %eax, -0x1f4(%rbp)
movl -0x110(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x70(%rbp), %rdi
callq 0x4c80
movq %rax, -0x1f0(%rbp)
jmp 0x5bd0
movq -0x1f0(%rbp), %rax
movl -0x1f4(%rbp), %ecx
movl %ecx, (%rax)
movl -0x114(%rbp), %eax
movl %eax, -0x204(%rbp)
movl -0x110(%rbp), %eax
movl -0x8(%rbp), %ecx
cltd
idivl %ecx
movslq %edx, %rsi
leaq -0x88(%rbp), %rdi
callq 0x4c80
movq %rax, -0x200(%rbp)
jmp 0x5c0f
movq -0x200(%rbp), %rax
movl -0x204(%rbp), %ecx
movl %ecx, (%rax)
movq -0x58(%rbp), %rdi
movq (%rdi), %rax
movq 0x40(%rax), %rax
callq *%rax
movl %eax, -0x208(%rbp)
jmp 0x5c33
movl -0x208(%rbp), %eax
movl %eax, -0x10c(%rbp)
leaq -0x108(%rbp), %rdi
leaq -0x10c(%rbp), %rsi
callq 0x6020
movq %rax, -0x210(%rbp)
jmp 0x5c5b
movq -0x210(%rbp), %rax
movq %rax, -0x120(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x6050
movq %rax, -0x128(%rbp)
leaq -0x120(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x5ff0
testb $0x1, %al
jne 0x5c95
jmp 0x5cde
leaq -0x108(%rbp), %rdi
leaq -0x10c(%rbp), %rsi
callq 0x6080
movq %rax, -0x218(%rbp)
jmp 0x5cb1
movq -0x218(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
jmp 0x5d07
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x60b0
jmp 0x5fa7
leaq -0x108(%rbp), %rdi
leaq -0x10c(%rbp), %rsi
callq 0x6080
movq %rax, -0x220(%rbp)
jmp 0x5cfa
movq -0x220(%rbp), %rax
movl $0x1, (%rax)
movl -0x10c(%rbp), %eax
cmpl -0xcc(%rbp), %eax
jle 0x5d23
movl -0x10c(%rbp), %eax
movl %eax, -0x224(%rbp)
jmp 0x5d2f
movl -0xcc(%rbp), %eax
movl %eax, -0x224(%rbp)
movl -0x224(%rbp), %eax
movl %eax, -0xcc(%rbp)
movl -0x110(%rbp), %eax
movl $0x7a120, %ecx          # imm = 0x7A120
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x5f01
movq 0x12277(%rip), %rdi     # 0x17fd0
leaq 0xa482(%rip), %rsi      # 0x101e2
callq 0x2180
movq %rax, -0x230(%rbp)
jmp 0x5d6e
movq -0x230(%rbp), %rdi
movl -0x110(%rbp), %esi
callq 0x2280
movq %rax, -0x238(%rbp)
jmp 0x5d89
movq -0x238(%rbp), %rdi
movq 0x12219(%rip), %rsi     # 0x17fb0
callq 0x21b0
jmp 0x5d9e
movl $0x0, -0x12c(%rbp)
movl -0x12c(%rbp), %eax
cmpl -0xcc(%rbp), %eax
jg 0x5eff
leaq -0x108(%rbp), %rdi
leaq -0x12c(%rbp), %rsi
callq 0x6020
movq %rax, -0x240(%rbp)
jmp 0x5dd6
movq -0x240(%rbp), %rax
movq %rax, -0x138(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x6050
movq %rax, -0x140(%rbp)
leaq -0x138(%rbp), %rdi
leaq -0x140(%rbp), %rsi
callq 0x5ff0
testb $0x1, %al
jne 0x5e13
jmp 0x5e9b
movl -0x12c(%rbp), %esi
movq 0x121b0(%rip), %rdi     # 0x17fd0
callq 0x2280
movq %rax, -0x248(%rbp)
jmp 0x5e2e
movq -0x248(%rbp), %rdi
leaq 0xa3c5(%rip), %rsi      # 0x10201
callq 0x2180
movq %rax, -0x250(%rbp)
jmp 0x5e4a
leaq -0x108(%rbp), %rdi
leaq -0x12c(%rbp), %rsi
callq 0x6080
movq %rax, -0x258(%rbp)
jmp 0x5e66
movq -0x250(%rbp), %rdi
movq -0x258(%rbp), %rax
movl (%rax), %esi
callq 0x2280
movq %rax, -0x260(%rbp)
jmp 0x5e84
movq -0x260(%rbp), %rdi
movq 0x1211e(%rip), %rsi     # 0x17fb0
callq 0x21b0
jmp 0x5e99
jmp 0x5ee9
movl -0x12c(%rbp), %esi
movq 0x12128(%rip), %rdi     # 0x17fd0
callq 0x2280
movq %rax, -0x268(%rbp)
jmp 0x5eb6
movq -0x268(%rbp), %rdi
leaq 0xa33f(%rip), %rsi      # 0x10203
callq 0x2180
movq %rax, -0x270(%rbp)
jmp 0x5ed2
movq -0x270(%rbp), %rdi
movq 0x120d0(%rip), %rsi     # 0x17fb0
callq 0x21b0
jmp 0x5ee7
jmp 0x5ee9
jmp 0x5eeb
movl -0x12c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x12c(%rbp)
jmp 0x5da8
jmp 0x5f01
jmp 0x5f03
movl -0x110(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x110(%rbp)
jmp 0x5afd
movq -0x58(%rbp), %rax
movq %rax, -0x278(%rbp)
cmpq $0x0, %rax
je 0x5f39
movq -0x278(%rbp), %rdi
movl $0x8, %esi
callq 0x21a0
movq -0x50(%rbp), %rax
movq %rax, -0x280(%rbp)
cmpq $0x0, %rax
je 0x5f5b
movq -0x280(%rbp), %rdi
movl $0x8, %esi
callq 0x21a0
movq -0x38(%rbp), %rax
movq %rax, -0x288(%rbp)
cmpq $0x0, %rax
je 0x5f7d
movq -0x288(%rbp), %rdi
movl $0x8, %esi
callq 0x21a0
leaq -0x108(%rbp), %rdi
callq 0x60b0
leaq -0x88(%rbp), %rdi
callq 0x4cc0
leaq -0x70(%rbp), %rdi
callq 0x4cc0
addq $0x2b0, %rsp            # imm = 0x2B0
popq %rbp
retq
leaq -0x88(%rbp), %rdi
callq 0x4cc0
leaq -0x70(%rbp), %rdi
callq 0x4cc0
movq -0x40(%rbp), %rdi
callq 0x22a0
nopw %cs:(%rax,%rax)
nop