def test_get(self): self.assertEqual("00000", UUID_TICKETS.get()) self.assertEqual("label_00000", LABEL_TICKETS.get()) self.assertEqual("ireg_00000", INT_REGISTER_TICKETS.get()) self.assertEqual("freg_00000", FLOAT_REGISTER_TICKETS.get()) self.assertEqual("00001", UUID_TICKETS.get()) self.assertEqual("label_00001", LABEL_TICKETS.get()) self.assertEqual("ireg_00001", INT_REGISTER_TICKETS.get()) self.assertEqual("freg_00001", FLOAT_REGISTER_TICKETS.get())
def test_overrun_of_spill_memory_fails(self): with self.assertRaises(OutOfSpillMemoryException): # 6 is precisely enough to run out of spill memory pseudo_registers = [ INT_REGISTER_TICKETS.get() for _ in range(0, 6) ] for pseudo_register in pseudo_registers: self.register_use_table.acquire(pseudo_register)
def test_register_spill(self): pseudo_registers = [INT_REGISTER_TICKETS.get() for _ in range(0, 3)] self.register_use_table.acquire(pseudo_registers[0]) self.register_use_table.acquire(pseudo_registers[1]) self.assertSequenceEqual([], self.register_use_table.available_registers, 'the registers should be used up') expected_result = {'register': mips.T0, 'code': [assembler.SW(mips.T0, assembler.offset_label_immediate(SPILL_MEM_LABEL, 0))]} result = self.register_use_table.acquire(pseudo_registers[2]) self.assertEqual(expected_result, result)
def test_spill_recovery(self): pseudo_registers = [INT_REGISTER_TICKETS.get() for _ in range(0, 3)] self.register_use_table.acquire(pseudo_registers[0]) self.register_use_table.acquire(pseudo_registers[1]) self.assertSequenceEqual([], self.register_use_table.available_registers, 'the registers should be used up') expected_result = {'register': mips.T0, 'code': [assembler.SW(mips.T0, assembler.offset_label_immediate(SPILL_MEM_LABEL, 0))]} result = self.register_use_table.acquire(pseudo_registers[2]) self.assertEqual(expected_result, result) # recovering a spilled register's value from memory should not only get the register, but also provide the # mips code that swaps the values for the temporaries using the spill memory expected_result = {'register': mips.T1, 'code': [assembler.SW(mips.T1, assembler.offset_label_immediate(SPILL_MEM_LABEL, 4)), assembler.LW(mips.T1, assembler.offset_label_immediate(SPILL_MEM_LABEL, 0))]} result = self.register_use_table.acquire(pseudo_registers[0]) self.assertEqual(expected_result, result)
def test_single_register_use(self): pseudo_register = INT_REGISTER_TICKETS.get() self.assertFalse(pseudo_register in self.register_use_table.lru_cache) result = self.register_use_table.acquire(pseudo_register) expected_result = {'register': mips.T0, 'code': []} self.assertEqual(expected_result, result, 'register $t0 should have been returned and no code required') # since no spilling occurred, we should get the same register back with no code needed result = self.register_use_table.acquire(pseudo_register) self.assertEqual(expected_result, result, 'register $t0 should have been returned and no code required') self.register_use_table.release(pseudo_register) self.assertFalse(pseudo_register in self.register_use_table.lru_cache) self.assertSequenceEqual([mips.T1, mips.T0], self.register_use_table.available_registers)
def test_register_spill(self): pseudo_registers = [INT_REGISTER_TICKETS.get() for _ in range(0, 3)] self.register_use_table.acquire(pseudo_registers[0]) self.register_use_table.acquire(pseudo_registers[1]) self.assertSequenceEqual([], self.register_use_table.available_registers, 'the registers should be used up') expected_result = { 'register': mips.T0, 'code': [ assembler.SW( mips.T0, assembler.offset_label_immediate(SPILL_MEM_LABEL, 0)) ] } result = self.register_use_table.acquire(pseudo_registers[2]) self.assertEqual(expected_result, result)
def test_spill_recovery(self): pseudo_registers = [INT_REGISTER_TICKETS.get() for _ in range(0, 3)] self.register_use_table.acquire(pseudo_registers[0]) self.register_use_table.acquire(pseudo_registers[1]) self.assertSequenceEqual([], self.register_use_table.available_registers, 'the registers should be used up') expected_result = { 'register': mips.T0, 'code': [ assembler.SW( mips.T0, assembler.offset_label_immediate(SPILL_MEM_LABEL, 0)) ] } result = self.register_use_table.acquire(pseudo_registers[2]) self.assertEqual(expected_result, result) # recovering a spilled register's value from memory should not only get the register, but also provide the # mips code that swaps the values for the temporaries using the spill memory expected_result = { 'register': mips.T1, 'code': [ assembler.SW( mips.T1, assembler.offset_label_immediate(SPILL_MEM_LABEL, 4)), assembler.LW( mips.T1, assembler.offset_label_immediate(SPILL_MEM_LABEL, 0)) ] } result = self.register_use_table.acquire(pseudo_registers[0]) self.assertEqual(expected_result, result)
def test_single_register_use(self): pseudo_register = INT_REGISTER_TICKETS.get() self.assertFalse(pseudo_register in self.register_use_table.lru_cache) result = self.register_use_table.acquire(pseudo_register) expected_result = {'register': mips.T0, 'code': []} self.assertEqual( expected_result, result, 'register $t0 should have been returned and no code required') # since no spilling occurred, we should get the same register back with no code needed result = self.register_use_table.acquire(pseudo_register) self.assertEqual( expected_result, result, 'register $t0 should have been returned and no code required') self.register_use_table.release(pseudo_register) self.assertFalse(pseudo_register in self.register_use_table.lru_cache) self.assertSequenceEqual([mips.T1, mips.T0], self.register_use_table.available_registers)
def test_overrun_of_spill_memory_fails(self): with self.assertRaises(OutOfSpillMemoryException): # 6 is precisely enough to run out of spill memory pseudo_registers = [INT_REGISTER_TICKETS.get() for _ in range(0, 6)] for pseudo_register in pseudo_registers: self.register_use_table.acquire(pseudo_register)