summaryrefslogtreecommitdiff
path: root/js/src/jit/StupidAllocator.h
blob: 96c17e03f38f02e06161357a1a9ad16e2dfa5d12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * 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/. */

#ifndef jit_StupidAllocator_h
#define jit_StupidAllocator_h

#include "jit/RegisterAllocator.h"

// Simple register allocator that only carries registers within basic blocks.

namespace js {
namespace jit {

class StupidAllocator : public RegisterAllocator
{
    static const uint32_t MAX_REGISTERS = AnyRegister::Total;
    static const uint32_t MISSING_ALLOCATION = UINT32_MAX;

    struct AllocatedRegister {
        AnyRegister reg;

        // The type of the value in the register.
        LDefinition::Type type;

        // Virtual register this physical reg backs, or MISSING_ALLOCATION.
        uint32_t vreg;

        // id of the instruction which most recently used this register.
        uint32_t age;

        // Whether the physical register is not synced with the backing stack slot.
        bool dirty;

        void set(uint32_t vreg, LInstruction* ins = nullptr, bool dirty = false) {
            this->vreg = vreg;
            this->age = ins ? ins->id() : 0;
            this->dirty = dirty;
        }
    };

    // Active allocation for the current code position.
    mozilla::Array<AllocatedRegister, MAX_REGISTERS> registers;
    uint32_t registerCount;

    // Type indicating an index into registers.
    typedef uint32_t RegisterIndex;

    // Information about each virtual register.
    Vector<LDefinition*, 0, SystemAllocPolicy> virtualRegisters;

  public:
    StupidAllocator(MIRGenerator* mir, LIRGenerator* lir, LIRGraph& graph)
      : RegisterAllocator(mir, lir, graph)
    {
    }

    [[nodiscard]] bool go();

  private:
    [[nodiscard]] bool init();

    void syncForBlockEnd(LBlock* block, LInstruction* ins);
    void allocateForInstruction(LInstruction* ins);
    void allocateForDefinition(LInstruction* ins, LDefinition* def);

    LAllocation* stackLocation(uint32_t vreg);

    RegisterIndex registerIndex(AnyRegister reg);

    AnyRegister ensureHasRegister(LInstruction* ins, uint32_t vreg);
    RegisterIndex allocateRegister(LInstruction* ins, uint32_t vreg);

    void syncRegister(LInstruction* ins, RegisterIndex index);
    void evictRegister(LInstruction* ins, RegisterIndex index);
    void evictAliasedRegister(LInstruction* ins, RegisterIndex index);
    void loadRegister(LInstruction* ins, uint32_t vreg, RegisterIndex index, LDefinition::Type type);

    RegisterIndex findExistingRegister(uint32_t vreg);

    bool allocationRequiresRegister(const LAllocation* alloc, AnyRegister reg);
    bool registerIsReserved(LInstruction* ins, AnyRegister reg);
};

} // namespace jit
} // namespace js

#endif /* jit_StupidAllocator_h */