1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef jit_Safepoints_h
8 #define jit_Safepoints_h
9 
10 #include <stddef.h>
11 #include <stdint.h>
12 
13 #include "jit/BitSet.h"
14 #include "jit/CompactBuffer.h"
15 #include "jit/RegisterSets.h"
16 
17 namespace js {
18 namespace jit {
19 
20 class CodeLocationLabel;
21 class IonScript;
22 class SafepointIndex;
23 struct SafepointSlotEntry;
24 class TempAllocator;
25 
26 class LAllocation;
27 class LSafepoint;
28 
29 static const uint32_t INVALID_SAFEPOINT_OFFSET = uint32_t(-1);
30 
31 class SafepointWriter {
32   CompactBufferWriter stream_;
33   BitSet frameSlots_;
34   BitSet argumentSlots_;
35 
36  public:
37   explicit SafepointWriter(uint32_t slotCount, uint32_t argumentCount);
38   [[nodiscard]] bool init(TempAllocator& alloc);
39 
40  private:
41   // A safepoint entry is written in the order these functions appear.
42   uint32_t startEntry();
43 
44   void writeOsiCallPointOffset(uint32_t osiPointOffset);
45   void writeGcRegs(LSafepoint* safepoint);
46   void writeGcSlots(LSafepoint* safepoint);
47 
48   void writeSlotsOrElementsSlots(LSafepoint* safepoint);
49 
50 #ifdef JS_PUNBOX64
51   void writeValueSlots(LSafepoint* safepoint);
52 #else
53   void writeNunboxParts(LSafepoint* safepoint);
54 #endif
55 
56   void endEntry();
57 
58  public:
59   void encode(LSafepoint* safepoint);
60 
size()61   size_t size() const { return stream_.length(); }
buffer()62   const uint8_t* buffer() const { return stream_.buffer(); }
oom()63   bool oom() const { return stream_.oom(); }
64 };
65 
66 class SafepointReader {
67   CompactBufferReader stream_;
68   uint32_t frameSlots_;
69   uint32_t argumentSlots_;
70   uint32_t currentSlotChunk_;
71   bool currentSlotsAreStack_;
72   uint32_t nextSlotChunkNumber_;
73   uint32_t osiCallPointOffset_;
74   GeneralRegisterSet gcSpills_;
75   GeneralRegisterSet valueSpills_;
76   GeneralRegisterSet slotsOrElementsSpills_;
77   GeneralRegisterSet allGprSpills_;
78   FloatRegisterSet allFloatSpills_;
79   uint32_t nunboxSlotsRemaining_;
80   uint32_t slotsOrElementsSlotsRemaining_;
81 
82  private:
83   void advanceFromGcRegs();
84   void advanceFromGcSlots();
85   void advanceFromNunboxOrValueSlots();
86   [[nodiscard]] bool getSlotFromBitmap(SafepointSlotEntry* entry);
87 
88  public:
89   SafepointReader(IonScript* script, const SafepointIndex* si);
90 
91   static CodeLocationLabel InvalidationPatchPoint(IonScript* script,
92                                                   const SafepointIndex* si);
93 
osiCallPointOffset()94   uint32_t osiCallPointOffset() const { return osiCallPointOffset_; }
gcSpills()95   LiveGeneralRegisterSet gcSpills() const {
96     return LiveGeneralRegisterSet(gcSpills_);
97   }
slotsOrElementsSpills()98   LiveGeneralRegisterSet slotsOrElementsSpills() const {
99     return LiveGeneralRegisterSet(slotsOrElementsSpills_);
100   }
valueSpills()101   LiveGeneralRegisterSet valueSpills() const {
102     return LiveGeneralRegisterSet(valueSpills_);
103   }
allGprSpills()104   LiveGeneralRegisterSet allGprSpills() const {
105     return LiveGeneralRegisterSet(allGprSpills_);
106   }
allFloatSpills()107   LiveFloatRegisterSet allFloatSpills() const {
108     return LiveFloatRegisterSet(allFloatSpills_);
109   }
110   uint32_t osiReturnPointOffset() const;
111 
112   // Returns true if a slot was read, false if there are no more slots.
113   [[nodiscard]] bool getGcSlot(SafepointSlotEntry* entry);
114 
115   // Returns true if a slot was read, false if there are no more value slots.
116   [[nodiscard]] bool getValueSlot(SafepointSlotEntry* entry);
117 
118   // Returns true if a nunbox slot was read, false if there are no more
119   // nunbox slots.
120   [[nodiscard]] bool getNunboxSlot(LAllocation* type, LAllocation* payload);
121 
122   // Returns true if a slot was read, false if there are no more slots.
123   [[nodiscard]] bool getSlotsOrElementsSlot(SafepointSlotEntry* entry);
124 };
125 
126 }  // namespace jit
127 }  // namespace js
128 
129 #endif /* jit_Safepoints_h */
130