// File: obliviousram[P]PathOHeap/src/OHeapReadPathEviction.cpp
// Function: OHeapReadPathEviction::OHeapReadPathEviction(UntrustedStorageInterface*, RandForOHeapInterface*, int, int, bool)
OHeapReadPathEviction::OHeapReadPathEviction(UntrustedStorageInterface* storage,
    RandForOHeapInterface* rand_gen, int bucket_size, int num_blocks, bool type_hiding_security)
    : storage(storage), rand_gen(rand_gen), bucket_size(bucket_size), num_blocks(num_blocks),
      type_hiding_security(type_hiding_security) {
  this->num_levels = ceil(log2(num_blocks)) + 1;
  this->num_buckets = pow(2, num_levels) - 1;
  if (this->num_buckets*this->bucket_size < this->num_blocks) {  // potential precision loss
    throw std::runtime_error("Not enough space for the acutal number of blocks.");
  }
  this->num_leaves = pow(2, num_levels - 1);
  this->t = 0;
  
  std::cout << "Initializing OHeap with " << this->num_levels << " levels, " <<
      this->num_blocks << " blocks, " << this->num_buckets << " buckets" << std::endl;

  Bucket::resetState();
  Bucket::setMaxSize(bucket_size);
  this->rand_gen->setBound(num_leaves);
  this->storage->setCapacity(num_buckets);
  
  this->stash = std::vector<Block>();

  Bucket init_bkt = Bucket();
  for (int i = 0; i < bucket_size; i++) {
    init_bkt.addBlock(Block());
  }

  for (int i = 0; i < num_buckets; i++) {
    this->storage->writeBucket(i, Bucket(init_bkt));
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1a0, %rsp            # imm = 0x1A0
movb %r9b, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movl %r8d, -0x20(%rbp)
andb $0x1, %al
movb %al, -0x21(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x140(%rbp)
callq 0x9a40
movq -0x140(%rbp), %rdi
leaq 0x101ac(%rip), %rax     # 0x17b60
addq $0x10, %rax
movq %rax, (%rdi)
movl -0x1c(%rbp), %eax
movl %eax, 0x8(%rdi)
movl -0x20(%rbp), %eax
movl %eax, 0x14(%rdi)
movb -0x21(%rbp), %al
andb $0x1, %al
movb %al, 0x28(%rdi)
movq -0x10(%rbp), %rax
movq %rax, 0x30(%rdi)
movq -0x18(%rbp), %rax
movq %rax, 0x38(%rdi)
addq $0x40, %rdi
movq %rdi, -0x148(%rbp)
callq 0x3000
cvtsi2sdl -0x20(%rbp), %xmm0
callq 0x22c0
callq 0x2040
movq -0x140(%rbp), %rax
movsd 0x87fb(%rip), %xmm1     # 0x10208
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
movl %ecx, 0xc(%rax)
cvtsi2sdl 0xc(%rax), %xmm1
movsd 0x86c3(%rip), %xmm0     # 0x100e8
callq 0x2290
movq -0x140(%rbp), %rcx
movsd 0x87cf(%rip), %xmm1     # 0x10208
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x18(%rcx)
movl 0x18(%rcx), %eax
imull 0x8(%rcx), %eax
cmpl 0x14(%rcx), %eax
jge 0x7ac2
movl $0x10, %edi
callq 0x20d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x150(%rbp)
leaq 0x87a2(%rip), %rsi      # 0x10210
callq 0x20b0
jmp 0x7a75
movq -0x150(%rbp), %rdi
movq 0x1056d(%rip), %rsi     # 0x17ff0
movq 0x10536(%rip), %rdx     # 0x17fc0
callq 0x2270
jmp 0x7da7
movq -0x150(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
callq 0x2130
jmp 0x7d92
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0x7d92
movq -0x140(%rbp), %rax
movl 0xc(%rax), %eax
decl %eax
cvtsi2sd %eax, %xmm1
movsd 0x860e(%rip), %xmm0     # 0x100e8
callq 0x2290
movq -0x140(%rbp), %rax
cvttsd2si %xmm0, %ecx
movl %ecx, 0x10(%rax)
movq $0x0, 0x20(%rax)
movq 0x104d4(%rip), %rdi     # 0x17fd0
leaq 0x873f(%rip), %rsi      # 0x10242
callq 0x2180
movq %rax, -0x158(%rbp)
jmp 0x7b11
movq -0x158(%rbp), %rdi
movq -0x140(%rbp), %rax
movl 0xc(%rax), %esi
callq 0x2280
movq %rax, -0x160(%rbp)
jmp 0x7b30
movq -0x160(%rbp), %rdi
leaq 0x871d(%rip), %rsi      # 0x1025b
callq 0x2180
movq %rax, -0x168(%rbp)
jmp 0x7b4c
movq -0x168(%rbp), %rdi
movq -0x140(%rbp), %rax
movl 0x14(%rax), %esi
callq 0x2280
movq %rax, -0x170(%rbp)
jmp 0x7b6b
movq -0x170(%rbp), %rdi
leaq 0x86ec(%rip), %rsi      # 0x10265
callq 0x2180
movq %rax, -0x178(%rbp)
jmp 0x7b87
movq -0x178(%rbp), %rdi
movq -0x140(%rbp), %rax
movl 0x18(%rax), %esi
callq 0x2280
movq %rax, -0x180(%rbp)
jmp 0x7ba6
movq -0x180(%rbp), %rdi
leaq 0x86bb(%rip), %rsi      # 0x1026f
callq 0x2180
movq %rax, -0x188(%rbp)
jmp 0x7bc2
movq -0x188(%rbp), %rdi
movq 0x103e0(%rip), %rsi     # 0x17fb0
callq 0x21b0
jmp 0x7bd7
callq 0x2ff0
jmp 0x7bde
movl -0x1c(%rbp), %edi
callq 0x2f60
jmp 0x7be8
movq -0x140(%rbp), %rax
movq 0x38(%rax), %rdi
movl 0x10(%rax), %esi
movq (%rdi), %rax
movq 0x8(%rax), %rax
callq *%rax
jmp 0x7c01
movq -0x140(%rbp), %rax
movq 0x30(%rax), %rdi
movl 0x18(%rax), %esi
movq (%rdi), %rax
movq (%rax), %rax
callq *%rax
jmp 0x7c19
xorps %xmm0, %xmm0
movaps %xmm0, -0x50(%rbp)
movq $0x0, -0x40(%rbp)
leaq -0x50(%rbp), %rdi
movq %rdi, -0x190(%rbp)
callq 0x3000
movq -0x140(%rbp), %rdi
movq -0x190(%rbp), %rsi
addq $0x40, %rdi
callq 0x9a60
movq -0x190(%rbp), %rdi
callq 0x3020
leaq -0xa0(%rbp), %rdi
callq 0x2cf0
jmp 0x7c69
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x7cc5
leaq -0xe0(%rbp), %rdi
callq 0x26b0
jmp 0x7c8c
leaq -0xa0(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x2db0
jmp 0x7ca1
jmp 0x7ca3
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x7c73
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0x7d86
movl $0x0, -0xe4(%rbp)
movq -0x140(%rbp), %rcx
movl -0xe4(%rbp), %eax
cmpl 0x18(%rcx), %eax
jge 0x7d71
movq -0x140(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x1a0(%rbp)
movl -0xe4(%rbp), %eax
movl %eax, -0x194(%rbp)
leaq -0x138(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x9a90
jmp 0x7d18
movl -0x194(%rbp), %esi
movq -0x1a0(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
leaq -0x138(%rbp), %rdx
callq *%rax
jmp 0x7d37
leaq -0x138(%rbp), %rdi
callq 0x9ae0
movl -0xe4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe4(%rbp)
jmp 0x7ccf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x138(%rbp), %rdi
callq 0x9ae0
jmp 0x7d86
leaq -0xa0(%rbp), %rdi
callq 0x9ae0
addq $0x1a0, %rsp            # imm = 0x1A0
popq %rbp
retq
leaq -0xa0(%rbp), %rdi
callq 0x9ae0
movq -0x148(%rbp), %rdi
callq 0x3020
movq -0x30(%rbp), %rdi
callq 0x22a0
nopw (%rax,%rax)