1// Copyright 2018 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_CONSTANT_POOL_H_
6#define V8_CONSTANT_POOL_H_
7
8#include <map>
9
10#include "src/double.h"
11#include "src/globals.h"
12#include "src/label.h"
13#include "src/reloc-info.h"
14
15namespace v8 {
16namespace internal {
17
18// -----------------------------------------------------------------------------
19// Constant pool support
20
21class ConstantPoolEntry {
22 public:
23 ConstantPoolEntry() = default;
24 ConstantPoolEntry(int position, intptr_t value, bool sharing_ok,
25 RelocInfo::Mode rmode = RelocInfo::NONE)
26 : position_(position),
27 merged_index_(sharing_ok ? SHARING_ALLOWED : SHARING_PROHIBITED),
28 value_(value),
29 rmode_(rmode) {}
30 ConstantPoolEntry(int position, Double value,
31 RelocInfo::Mode rmode = RelocInfo::NONE)
32 : position_(position),
33 merged_index_(SHARING_ALLOWED),
34 value64_(value.AsUint64()),
35 rmode_(rmode) {}
36
37 int position() const { return position_; }
38 bool sharing_ok() const { return merged_index_ != SHARING_PROHIBITED; }
39 bool is_merged() const { return merged_index_ >= 0; }
40 int merged_index() const {
41 DCHECK(is_merged());
42 return merged_index_;
43 }
44 void set_merged_index(int index) {
45 DCHECK(sharing_ok());
46 merged_index_ = index;
47 DCHECK(is_merged());
48 }
49 int offset() const {
50 DCHECK_GE(merged_index_, 0);
51 return merged_index_;
52 }
53 void set_offset(int offset) {
54 DCHECK_GE(offset, 0);
55 merged_index_ = offset;
56 }
57 intptr_t value() const { return value_; }
58 uint64_t value64() const { return value64_; }
59 RelocInfo::Mode rmode() const { return rmode_; }
60
61 enum Type { INTPTR, DOUBLE, NUMBER_OF_TYPES };
62
63 static int size(Type type) {
64 return (type == INTPTR) ? kSystemPointerSize : kDoubleSize;
65 }
66
67 enum Access { REGULAR, OVERFLOWED };
68
69 private:
70 int position_;
71 int merged_index_;
72 union {
73 intptr_t value_;
74 uint64_t value64_;
75 };
76 // TODO(leszeks): The way we use this, it could probably be packed into
77 // merged_index_ if size is a concern.
78 RelocInfo::Mode rmode_;
79 enum { SHARING_PROHIBITED = -2, SHARING_ALLOWED = -1 };
80};
81
82#if defined(V8_TARGET_ARCH_PPC)
83
84// -----------------------------------------------------------------------------
85// Embedded constant pool support
86
87class ConstantPoolBuilder {
88 public:
89 ConstantPoolBuilder(int ptr_reach_bits, int double_reach_bits);
90
91#ifdef DEBUG
92 ~ConstantPoolBuilder() {
93 // Unused labels to prevent DCHECK failures.
94 emitted_label_.Unuse();
95 emitted_label_.UnuseNear();
96 }
97#endif
98
99 // Add pointer-sized constant to the embedded constant pool
100 ConstantPoolEntry::Access AddEntry(int position, intptr_t value,
101 bool sharing_ok) {
102 ConstantPoolEntry entry(position, value, sharing_ok);
103 return AddEntry(entry, ConstantPoolEntry::INTPTR);
104 }
105
106 // Add double constant to the embedded constant pool
107 ConstantPoolEntry::Access AddEntry(int position, Double value) {
108 ConstantPoolEntry entry(position, value);
109 return AddEntry(entry, ConstantPoolEntry::DOUBLE);
110 }
111
112 // Add double constant to the embedded constant pool
113 ConstantPoolEntry::Access AddEntry(int position, double value) {
114 return AddEntry(position, Double(value));
115 }
116
117 // Previews the access type required for the next new entry to be added.
118 ConstantPoolEntry::Access NextAccess(ConstantPoolEntry::Type type) const;
119
120 bool IsEmpty() {
121 return info_[ConstantPoolEntry::INTPTR].entries.empty() &&
122 info_[ConstantPoolEntry::INTPTR].shared_entries.empty() &&
123 info_[ConstantPoolEntry::DOUBLE].entries.empty() &&
124 info_[ConstantPoolEntry::DOUBLE].shared_entries.empty();
125 }
126
127 // Emit the constant pool. Invoke only after all entries have been
128 // added and all instructions have been emitted.
129 // Returns position of the emitted pool (zero implies no constant pool).
130 int Emit(Assembler* assm);
131
132 // Returns the label associated with the start of the constant pool.
133 // Linking to this label in the function prologue may provide an
134 // efficient means of constant pool pointer register initialization
135 // on some architectures.
136 inline Label* EmittedPosition() { return &emitted_label_; }
137
138 private:
139 ConstantPoolEntry::Access AddEntry(ConstantPoolEntry& entry,
140 ConstantPoolEntry::Type type);
141 void EmitSharedEntries(Assembler* assm, ConstantPoolEntry::Type type);
142 void EmitGroup(Assembler* assm, ConstantPoolEntry::Access access,
143 ConstantPoolEntry::Type type);
144
145 struct PerTypeEntryInfo {
146 PerTypeEntryInfo() : regular_count(0), overflow_start(-1) {}
147 bool overflow() const {
148 return (overflow_start >= 0 &&
149 overflow_start < static_cast<int>(entries.size()));
150 }
151 int regular_reach_bits;
152 int regular_count;
153 int overflow_start;
154 std::vector<ConstantPoolEntry> entries;
155 std::vector<ConstantPoolEntry> shared_entries;
156 };
157
158 Label emitted_label_; // Records pc_offset of emitted pool
159 PerTypeEntryInfo info_[ConstantPoolEntry::NUMBER_OF_TYPES];
160};
161
162#endif // defined(V8_TARGET_ARCH_PPC)
163
164} // namespace internal
165} // namespace v8
166
167#endif // V8_CONSTANT_POOL_H_
168