1// Copyright 2015 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// Test embedded constant pool builder code.
6
7#include "src/v8.h"
8
9#include "src/assembler.h"
10#include "test/cctest/cctest.h"
11
12using namespace v8::internal;
13
14const ConstantPoolEntry::Type kPtrType = ConstantPoolEntry::INTPTR;
15const ConstantPoolEntry::Type kDblType = ConstantPoolEntry::DOUBLE;
16const ConstantPoolEntry::Access kRegAccess = ConstantPoolEntry::REGULAR;
17const ConstantPoolEntry::Access kOvflAccess = ConstantPoolEntry::OVERFLOWED;
18
19const int kReachBits = 6;  // Use reach of 64-bytes to test overflow.
20const int kReach = 1 << kReachBits;
21
22
23TEST(ConstantPoolPointers) {
24  ConstantPoolBuilder builder(kReachBits, kReachBits);
25  const int kRegularCount = kReach / kPointerSize;
26  ConstantPoolEntry::Access access;
27  int pos = 0;
28  intptr_t value = 0;
29  bool sharing_ok = true;
30
31  CHECK(builder.IsEmpty());
32  while (builder.NextAccess(kPtrType) == kRegAccess) {
33    access = builder.AddEntry(pos++, value++, sharing_ok);
34    CHECK_EQ(access, kRegAccess);
35  }
36  CHECK(!builder.IsEmpty());
37  CHECK_EQ(pos, kRegularCount);
38
39  access = builder.AddEntry(pos, value, sharing_ok);
40  CHECK_EQ(access, kOvflAccess);
41}
42
43
44TEST(ConstantPoolDoubles) {
45  ConstantPoolBuilder builder(kReachBits, kReachBits);
46  const int kRegularCount = kReach / kDoubleSize;
47  ConstantPoolEntry::Access access;
48  int pos = 0;
49  double value = 0.0;
50
51  CHECK(builder.IsEmpty());
52  while (builder.NextAccess(kDblType) == kRegAccess) {
53    access = builder.AddEntry(pos++, value);
54    value += 0.5;
55    CHECK_EQ(access, kRegAccess);
56  }
57  CHECK(!builder.IsEmpty());
58  CHECK_EQ(pos, kRegularCount);
59
60  access = builder.AddEntry(pos, value);
61  CHECK_EQ(access, kOvflAccess);
62}
63
64
65TEST(ConstantPoolMixedTypes) {
66  ConstantPoolBuilder builder(kReachBits, kReachBits);
67  const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) +
68                             ((kPointerSize < kDoubleSize) ? 1 : 0));
69  ConstantPoolEntry::Type type = kPtrType;
70  ConstantPoolEntry::Access access;
71  int pos = 0;
72  intptr_t ptrValue = 0;
73  double dblValue = 0.0;
74  bool sharing_ok = true;
75
76  CHECK(builder.IsEmpty());
77  while (builder.NextAccess(type) == kRegAccess) {
78    if (type == kPtrType) {
79      access = builder.AddEntry(pos++, ptrValue++, sharing_ok);
80      type = kDblType;
81    } else {
82      access = builder.AddEntry(pos++, dblValue);
83      dblValue += 0.5;
84      type = kPtrType;
85    }
86    CHECK_EQ(access, kRegAccess);
87  }
88  CHECK(!builder.IsEmpty());
89  CHECK_EQ(pos, kRegularCount);
90
91  access = builder.AddEntry(pos++, ptrValue, sharing_ok);
92  CHECK_EQ(access, kOvflAccess);
93  access = builder.AddEntry(pos, dblValue);
94  CHECK_EQ(access, kOvflAccess);
95}
96
97
98TEST(ConstantPoolMixedReach) {
99  const int ptrReachBits = kReachBits + 2;
100  const int ptrReach = 1 << ptrReachBits;
101  const int dblReachBits = kReachBits;
102  const int dblReach = kReach;
103  const int dblRegularCount =
104      Min(dblReach / kDoubleSize, ptrReach / (kDoubleSize + kPointerSize));
105  const int ptrRegularCount =
106      ((ptrReach - (dblRegularCount * (kDoubleSize + kPointerSize))) /
107       kPointerSize) +
108      dblRegularCount;
109  ConstantPoolBuilder builder(ptrReachBits, dblReachBits);
110  ConstantPoolEntry::Access access;
111  int pos = 0;
112  intptr_t ptrValue = 0;
113  double dblValue = 0.0;
114  bool sharing_ok = true;
115  int ptrCount = 0;
116  int dblCount = 0;
117
118  CHECK(builder.IsEmpty());
119  while (builder.NextAccess(kDblType) == kRegAccess) {
120    access = builder.AddEntry(pos++, dblValue);
121    dblValue += 0.5;
122    dblCount++;
123    CHECK_EQ(access, kRegAccess);
124
125    access = builder.AddEntry(pos++, ptrValue++, sharing_ok);
126    ptrCount++;
127    CHECK_EQ(access, kRegAccess);
128  }
129  CHECK(!builder.IsEmpty());
130  CHECK_EQ(dblCount, dblRegularCount);
131
132  while (ptrCount < ptrRegularCount) {
133    access = builder.AddEntry(pos++, dblValue);
134    dblValue += 0.5;
135    CHECK_EQ(access, kOvflAccess);
136
137    access = builder.AddEntry(pos++, ptrValue++, sharing_ok);
138    ptrCount++;
139    CHECK_EQ(access, kRegAccess);
140  }
141  CHECK_EQ(builder.NextAccess(kPtrType), kOvflAccess);
142
143  access = builder.AddEntry(pos++, ptrValue, sharing_ok);
144  CHECK_EQ(access, kOvflAccess);
145  access = builder.AddEntry(pos, dblValue);
146  CHECK_EQ(access, kOvflAccess);
147}
148
149
150TEST(ConstantPoolSharing) {
151  ConstantPoolBuilder builder(kReachBits, kReachBits);
152  const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) +
153                             ((kPointerSize < kDoubleSize) ? 1 : 0));
154  ConstantPoolEntry::Access access;
155
156  CHECK(builder.IsEmpty());
157
158  ConstantPoolEntry::Type type = kPtrType;
159  int pos = 0;
160  intptr_t ptrValue = 0;
161  double dblValue = 0.0;
162  bool sharing_ok = true;
163  while (builder.NextAccess(type) == kRegAccess) {
164    if (type == kPtrType) {
165      access = builder.AddEntry(pos++, ptrValue++, sharing_ok);
166      type = kDblType;
167    } else {
168      access = builder.AddEntry(pos++, dblValue);
169      dblValue += 0.5;
170      type = kPtrType;
171    }
172    CHECK_EQ(access, kRegAccess);
173  }
174  CHECK(!builder.IsEmpty());
175  CHECK_EQ(pos, kRegularCount);
176
177  type = kPtrType;
178  ptrValue = 0;
179  dblValue = 0.0;
180  while (pos < kRegularCount * 2) {
181    if (type == kPtrType) {
182      access = builder.AddEntry(pos++, ptrValue++, sharing_ok);
183      type = kDblType;
184    } else {
185      access = builder.AddEntry(pos++, dblValue);
186      dblValue += 0.5;
187      type = kPtrType;
188    }
189    CHECK_EQ(access, kRegAccess);
190  }
191
192  access = builder.AddEntry(pos++, ptrValue, sharing_ok);
193  CHECK_EQ(access, kOvflAccess);
194  access = builder.AddEntry(pos, dblValue);
195  CHECK_EQ(access, kOvflAccess);
196}
197
198
199TEST(ConstantPoolNoSharing) {
200  ConstantPoolBuilder builder(kReachBits, kReachBits);
201  const int kRegularCount = (((kReach / (kDoubleSize + kPointerSize)) * 2) +
202                             ((kPointerSize < kDoubleSize) ? 1 : 0));
203  ConstantPoolEntry::Access access;
204
205  CHECK(builder.IsEmpty());
206
207  ConstantPoolEntry::Type type = kPtrType;
208  int pos = 0;
209  intptr_t ptrValue = 0;
210  double dblValue = 0.0;
211  bool sharing_ok = false;
212  while (builder.NextAccess(type) == kRegAccess) {
213    if (type == kPtrType) {
214      access = builder.AddEntry(pos++, ptrValue++, sharing_ok);
215      type = kDblType;
216    } else {
217      access = builder.AddEntry(pos++, dblValue);
218      dblValue += 0.5;
219      type = kPtrType;
220    }
221    CHECK_EQ(access, kRegAccess);
222  }
223  CHECK(!builder.IsEmpty());
224  CHECK_EQ(pos, kRegularCount);
225
226  type = kPtrType;
227  ptrValue = 0;
228  dblValue = 0.0;
229  sharing_ok = true;
230  while (pos < kRegularCount * 2) {
231    if (type == kPtrType) {
232      access = builder.AddEntry(pos++, ptrValue++, sharing_ok);
233      type = kDblType;
234      CHECK_EQ(access, kOvflAccess);
235    } else {
236      access = builder.AddEntry(pos++, dblValue);
237      dblValue += 0.5;
238      type = kPtrType;
239      CHECK_EQ(access, kRegAccess);
240    }
241  }
242
243  access = builder.AddEntry(pos++, ptrValue, sharing_ok);
244  CHECK_EQ(access, kOvflAccess);
245  access = builder.AddEntry(pos, dblValue);
246  CHECK_EQ(access, kOvflAccess);
247}
248