| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
| * vim: set ts=8 sts=4 et sw=4 tw=99: |
| */ |
| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| #include "jit/RegisterSets.h" |
| |
| #include "jsapi-tests/tests.h" |
| |
| using namespace js; |
| using namespace js::jit; |
| |
| static bool |
| CoPrime(size_t a, size_t b) |
| { |
| if (b <= 1) |
| return a == 1 || b == 1; |
| return CoPrime(b, a % b); |
| } |
| |
| // This macros are use to iterave over all registers in a large number of |
| // non-looping sequences, which does not rely on the getFirst / getLast |
| // functions. |
| #define BEGIN_INDEX_WALK(RegTotal) \ |
| static const size_t Total = RegTotal; \ |
| for (size_t walk = 1; walk < RegTotal; walk += 2) { \ |
| if (!CoPrime(RegTotal, walk)) \ |
| continue; \ |
| for (size_t start = 0; start < RegTotal; start++) { \ |
| size_t index = start; |
| |
| #define END_INDEX_WALK \ |
| } \ |
| } |
| |
| #define FOR_ALL_REGISTERS(Register, reg) \ |
| do { \ |
| Register reg = Register::FromCode(index); |
| |
| #define END_FOR_ALL_REGISTERS \ |
| index = (index + walk) % Total; \ |
| } while(index != start) |
| |
| BEGIN_TEST(testJitRegisterSet_GPR) |
| { |
| BEGIN_INDEX_WALK(Registers::Total) |
| |
| LiveGeneralRegisterSet liveRegs; |
| AllocatableGeneralRegisterSet pool(GeneralRegisterSet::All()); |
| CHECK(liveRegs.empty()); |
| CHECK(pool.set() == GeneralRegisterSet::All()); |
| |
| FOR_ALL_REGISTERS(Register, reg) { |
| |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| if (pool.has(reg)) { |
| CHECK(!liveRegs.has(reg)); |
| pool.take(reg); |
| liveRegs.add(reg); |
| CHECK(liveRegs.has(reg)); |
| CHECK(!pool.has(reg)); |
| } |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| |
| } END_FOR_ALL_REGISTERS; |
| |
| CHECK(pool.empty()); |
| |
| FOR_ALL_REGISTERS(Register, reg) { |
| |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| if (liveRegs.has(reg)) { |
| CHECK(!pool.has(reg)); |
| liveRegs.take(reg); |
| pool.add(reg); |
| CHECK(pool.has(reg)); |
| CHECK(!liveRegs.has(reg)); |
| } |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| |
| } END_FOR_ALL_REGISTERS; |
| |
| CHECK(liveRegs.empty()); |
| CHECK(pool.set() == GeneralRegisterSet::All()); |
| |
| END_INDEX_WALK |
| return true; |
| } |
| END_TEST(testJitRegisterSet_GPR) |
| |
| BEGIN_TEST(testJitRegisterSet_FPU) |
| { |
| BEGIN_INDEX_WALK(FloatRegisters::Total) |
| |
| LiveFloatRegisterSet liveRegs; |
| AllocatableFloatRegisterSet pool(FloatRegisterSet::All()); |
| CHECK(liveRegs.empty()); |
| CHECK(pool.set() == FloatRegisterSet::All()); |
| |
| FOR_ALL_REGISTERS(FloatRegister, reg) { |
| |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| if (pool.has(reg)) { |
| CHECK(!liveRegs.has(reg)); |
| pool.take(reg); |
| liveRegs.add(reg); |
| CHECK(liveRegs.has(reg)); |
| CHECK(!pool.has(reg)); |
| } |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| |
| } END_FOR_ALL_REGISTERS; |
| |
| CHECK(pool.empty()); |
| |
| FOR_ALL_REGISTERS(FloatRegister, reg) { |
| |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| if (liveRegs.has(reg)) { |
| CHECK(!pool.has(reg)); |
| liveRegs.take(reg); |
| pool.add(reg); |
| CHECK(pool.has(reg)); |
| CHECK(!liveRegs.has(reg)); |
| } |
| CHECK(!pool.has(reg) || !liveRegs.has(reg)); |
| |
| } END_FOR_ALL_REGISTERS; |
| |
| CHECK(liveRegs.empty()); |
| CHECK(pool.set() == FloatRegisterSet::All()); |
| |
| END_INDEX_WALK |
| return true; |
| } |
| END_TEST(testJitRegisterSet_FPU) |