The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-global-handles.cc @ f230a1cf

History | View | Annotate | Download (13.4 KB)

1
// Copyright 2013 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include "global-handles.h"
29

    
30
#include "cctest.h"
31

    
32
using namespace v8::internal;
33
using v8::UniqueId;
34

    
35

    
36
static List<Object*> skippable_objects;
37
static List<Object*> can_skip_called_objects;
38

    
39

    
40
static bool CanSkipCallback(Heap* heap, Object** pointer) {
41
  can_skip_called_objects.Add(*pointer);
42
  return skippable_objects.Contains(*pointer);
43
}
44

    
45

    
46
static void ResetCanSkipData() {
47
  skippable_objects.Clear();
48
  can_skip_called_objects.Clear();
49
}
50

    
51

    
52
class TestRetainedObjectInfo : public v8::RetainedObjectInfo {
53
 public:
54
  TestRetainedObjectInfo() : has_been_disposed_(false) {}
55

    
56
  bool has_been_disposed() { return has_been_disposed_; }
57

    
58
  virtual void Dispose() {
59
    ASSERT(!has_been_disposed_);
60
    has_been_disposed_ = true;
61
  }
62

    
63
  virtual bool IsEquivalent(v8::RetainedObjectInfo* other) {
64
    return other == this;
65
  }
66

    
67
  virtual intptr_t GetHash() { return 0; }
68

    
69
  virtual const char* GetLabel() { return "whatever"; }
70

    
71
 private:
72
  bool has_been_disposed_;
73
};
74

    
75

    
76
class TestObjectVisitor : public ObjectVisitor {
77
 public:
78
  virtual void VisitPointers(Object** start, Object** end) {
79
    for (Object** o = start; o != end; ++o)
80
      visited.Add(*o);
81
  }
82

    
83
  List<Object*> visited;
84
};
85

    
86

    
87
TEST(IterateObjectGroupsOldApi) {
88
  CcTest::InitializeVM();
89
  GlobalHandles* global_handles = CcTest::i_isolate()->global_handles();
90
  Heap* heap = CcTest::heap();
91
  v8::HandleScope handle_scope(CcTest::isolate());
92

    
93
  Handle<Object> g1s1 =
94
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
95
  Handle<Object> g1s2 =
96
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
97

    
98
  Handle<Object> g2s1 =
99
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
100
  Handle<Object> g2s2 =
101
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
102

    
103
  TestRetainedObjectInfo info1;
104
  TestRetainedObjectInfo info2;
105
  {
106
    Object** g1_objects[] = { g1s1.location(), g1s2.location() };
107
    Object** g2_objects[] = { g2s1.location(), g2s2.location() };
108

    
109
    global_handles->AddObjectGroup(g1_objects, 2, &info1);
110
    global_handles->AddObjectGroup(g2_objects, 2, &info2);
111
  }
112

    
113
  // Iterate the object groups. First skip all.
114
  {
115
    ResetCanSkipData();
116
    skippable_objects.Add(*g1s1.location());
117
    skippable_objects.Add(*g1s2.location());
118
    skippable_objects.Add(*g2s1.location());
119
    skippable_objects.Add(*g2s2.location());
120
    TestObjectVisitor visitor;
121
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);
122

    
123
    // CanSkipCallback was called for all objects.
124
    ASSERT(can_skip_called_objects.length() == 4);
125
    ASSERT(can_skip_called_objects.Contains(*g1s1.location()));
126
    ASSERT(can_skip_called_objects.Contains(*g1s2.location()));
127
    ASSERT(can_skip_called_objects.Contains(*g2s1.location()));
128
    ASSERT(can_skip_called_objects.Contains(*g2s2.location()));
129

    
130
    // Nothing was visited.
131
    ASSERT(visitor.visited.length() == 0);
132
    ASSERT(!info1.has_been_disposed());
133
    ASSERT(!info2.has_been_disposed());
134
  }
135

    
136
  // Iterate again, now only skip the second object group.
137
  {
138
    ResetCanSkipData();
139
    // The first grough should still be visited, since only one object is
140
    // skipped.
141
    skippable_objects.Add(*g1s1.location());
142
    skippable_objects.Add(*g2s1.location());
143
    skippable_objects.Add(*g2s2.location());
144
    TestObjectVisitor visitor;
145
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);
146

    
147
    // CanSkipCallback was called for all objects.
148
    ASSERT(can_skip_called_objects.length() == 3 ||
149
           can_skip_called_objects.length() == 4);
150
    ASSERT(can_skip_called_objects.Contains(*g1s2.location()));
151
    ASSERT(can_skip_called_objects.Contains(*g2s1.location()));
152
    ASSERT(can_skip_called_objects.Contains(*g2s2.location()));
153

    
154
    // The first group was visited.
155
    ASSERT(visitor.visited.length() == 2);
156
    ASSERT(visitor.visited.Contains(*g1s1.location()));
157
    ASSERT(visitor.visited.Contains(*g1s2.location()));
158
    ASSERT(info1.has_been_disposed());
159
    ASSERT(!info2.has_been_disposed());
160
  }
161

    
162
  // Iterate again, don't skip anything.
163
  {
164
    ResetCanSkipData();
165
    TestObjectVisitor visitor;
166
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);
167

    
168
    // CanSkipCallback was called for all objects.
169
    ASSERT(can_skip_called_objects.length() == 1);
170
    ASSERT(can_skip_called_objects.Contains(*g2s1.location()) ||
171
           can_skip_called_objects.Contains(*g2s2.location()));
172

    
173
    // The second group was visited.
174
    ASSERT(visitor.visited.length() == 2);
175
    ASSERT(visitor.visited.Contains(*g2s1.location()));
176
    ASSERT(visitor.visited.Contains(*g2s2.location()));
177
    ASSERT(info2.has_been_disposed());
178
  }
179
}
180

    
181

    
182
TEST(IterateObjectGroups) {
183
  CcTest::InitializeVM();
184
  GlobalHandles* global_handles = CcTest::i_isolate()->global_handles();
185
  Heap* heap = CcTest::heap();
186

    
187
  v8::HandleScope handle_scope(CcTest::isolate());
188

    
189
  Handle<Object> g1s1 =
190
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
191
  Handle<Object> g1s2 =
192
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
193

    
194
  Handle<Object> g2s1 =
195
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
196
  Handle<Object> g2s2 =
197
    global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
198

    
199
  TestRetainedObjectInfo info1;
200
  TestRetainedObjectInfo info2;
201
  global_handles->SetObjectGroupId(g2s1.location(), UniqueId(2));
202
  global_handles->SetObjectGroupId(g2s2.location(), UniqueId(2));
203
  global_handles->SetRetainedObjectInfo(UniqueId(2), &info2);
204
  global_handles->SetObjectGroupId(g1s1.location(), UniqueId(1));
205
  global_handles->SetObjectGroupId(g1s2.location(), UniqueId(1));
206
  global_handles->SetRetainedObjectInfo(UniqueId(1), &info1);
207

    
208
  // Iterate the object groups. First skip all.
209
  {
210
    ResetCanSkipData();
211
    skippable_objects.Add(*g1s1.location());
212
    skippable_objects.Add(*g1s2.location());
213
    skippable_objects.Add(*g2s1.location());
214
    skippable_objects.Add(*g2s2.location());
215
    TestObjectVisitor visitor;
216
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);
217

    
218
    // CanSkipCallback was called for all objects.
219
    ASSERT(can_skip_called_objects.length() == 4);
220
    ASSERT(can_skip_called_objects.Contains(*g1s1.location()));
221
    ASSERT(can_skip_called_objects.Contains(*g1s2.location()));
222
    ASSERT(can_skip_called_objects.Contains(*g2s1.location()));
223
    ASSERT(can_skip_called_objects.Contains(*g2s2.location()));
224

    
225
    // Nothing was visited.
226
    ASSERT(visitor.visited.length() == 0);
227
    ASSERT(!info1.has_been_disposed());
228
    ASSERT(!info2.has_been_disposed());
229
  }
230

    
231
  // Iterate again, now only skip the second object group.
232
  {
233
    ResetCanSkipData();
234
    // The first grough should still be visited, since only one object is
235
    // skipped.
236
    skippable_objects.Add(*g1s1.location());
237
    skippable_objects.Add(*g2s1.location());
238
    skippable_objects.Add(*g2s2.location());
239
    TestObjectVisitor visitor;
240
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);
241

    
242
    // CanSkipCallback was called for all objects.
243
    ASSERT(can_skip_called_objects.length() == 3 ||
244
           can_skip_called_objects.length() == 4);
245
    ASSERT(can_skip_called_objects.Contains(*g1s2.location()));
246
    ASSERT(can_skip_called_objects.Contains(*g2s1.location()));
247
    ASSERT(can_skip_called_objects.Contains(*g2s2.location()));
248

    
249
    // The first group was visited.
250
    ASSERT(visitor.visited.length() == 2);
251
    ASSERT(visitor.visited.Contains(*g1s1.location()));
252
    ASSERT(visitor.visited.Contains(*g1s2.location()));
253
    ASSERT(info1.has_been_disposed());
254
    ASSERT(!info2.has_been_disposed());
255
  }
256

    
257
  // Iterate again, don't skip anything.
258
  {
259
    ResetCanSkipData();
260
    TestObjectVisitor visitor;
261
    global_handles->IterateObjectGroups(&visitor, &CanSkipCallback);
262

    
263
    // CanSkipCallback was called for all objects.
264
    ASSERT(can_skip_called_objects.length() == 1);
265
    ASSERT(can_skip_called_objects.Contains(*g2s1.location()) ||
266
           can_skip_called_objects.Contains(*g2s2.location()));
267

    
268
    // The second group was visited.
269
    ASSERT(visitor.visited.length() == 2);
270
    ASSERT(visitor.visited.Contains(*g2s1.location()));
271
    ASSERT(visitor.visited.Contains(*g2s2.location()));
272
    ASSERT(info2.has_been_disposed());
273
  }
274
}
275

    
276

    
277
TEST(ImplicitReferences) {
278
  CcTest::InitializeVM();
279
  GlobalHandles* global_handles = CcTest::i_isolate()->global_handles();
280
  Heap* heap = CcTest::heap();
281

    
282
  v8::HandleScope handle_scope(CcTest::isolate());
283

    
284
  Handle<Object> g1s1 =
285
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
286
  Handle<Object> g1c1 =
287
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
288
  Handle<Object> g1c2 =
289
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
290

    
291

    
292
  Handle<Object> g2s1 =
293
      global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
294
  Handle<Object> g2s2 =
295
    global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
296
  Handle<Object> g2c1 =
297
    global_handles->Create(heap->AllocateFixedArray(1)->ToObjectChecked());
298

    
299
  global_handles->SetObjectGroupId(g1s1.location(), UniqueId(1));
300
  global_handles->SetObjectGroupId(g2s1.location(), UniqueId(2));
301
  global_handles->SetObjectGroupId(g2s2.location(), UniqueId(2));
302
  global_handles->SetReferenceFromGroup(UniqueId(1), g1c1.location());
303
  global_handles->SetReferenceFromGroup(UniqueId(1), g1c2.location());
304
  global_handles->SetReferenceFromGroup(UniqueId(2), g2c1.location());
305

    
306
  List<ImplicitRefGroup*>* implicit_refs =
307
      global_handles->implicit_ref_groups();
308
  USE(implicit_refs);
309
  ASSERT(implicit_refs->length() == 2);
310
  ASSERT(implicit_refs->at(0)->parent ==
311
         reinterpret_cast<HeapObject**>(g1s1.location()));
312
  ASSERT(implicit_refs->at(0)->length == 2);
313
  ASSERT(implicit_refs->at(0)->children[0] == g1c1.location());
314
  ASSERT(implicit_refs->at(0)->children[1] == g1c2.location());
315
  ASSERT(implicit_refs->at(1)->parent ==
316
         reinterpret_cast<HeapObject**>(g2s1.location()));
317
  ASSERT(implicit_refs->at(1)->length == 1);
318
  ASSERT(implicit_refs->at(1)->children[0] == g2c1.location());
319
}
320

    
321

    
322
TEST(EternalHandles) {
323
  CcTest::InitializeVM();
324
  Isolate* isolate = CcTest::i_isolate();
325
  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
326
  EternalHandles* eternal_handles = isolate->eternal_handles();
327

    
328
  // Create a number of handles that will not be on a block boundary
329
  const int kArrayLength = 2048-1;
330
  int indices[kArrayLength];
331
  v8::Eternal<v8::Value> eternals[kArrayLength];
332

    
333
  CHECK_EQ(0, eternal_handles->NumberOfHandles());
334
  for (int i = 0; i < kArrayLength; i++) {
335
    indices[i] = -1;
336
    HandleScope scope(isolate);
337
    v8::Local<v8::Object> object = v8::Object::New();
338
    object->Set(i, v8::Integer::New(i, v8_isolate));
339
    // Create with internal api
340
    eternal_handles->Create(
341
        isolate, *v8::Utils::OpenHandle(*object), &indices[i]);
342
    // Create with external api
343
    CHECK(eternals[i].IsEmpty());
344
    eternals[i].Set(v8_isolate, object);
345
    CHECK(!eternals[i].IsEmpty());
346
  }
347

    
348
  isolate->heap()->CollectAllAvailableGarbage();
349

    
350
  for (int i = 0; i < kArrayLength; i++) {
351
    for (int j = 0; j < 2; j++) {
352
      HandleScope scope(isolate);
353
      v8::Local<v8::Value> local;
354
      if (j == 0) {
355
        // Test internal api
356
        local = v8::Utils::ToLocal(eternal_handles->Get(indices[i]));
357
      } else {
358
        // Test external api
359
        local = eternals[i].Get(v8_isolate);
360
      }
361
      v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(local);
362
      v8::Local<v8::Value> value = object->Get(i);
363
      CHECK(value->IsInt32());
364
      CHECK_EQ(i, value->Int32Value());
365
    }
366
  }
367

    
368
  CHECK_EQ(2*kArrayLength, eternal_handles->NumberOfHandles());
369

    
370
  // Create an eternal via the constructor
371
  {
372
    HandleScope scope(isolate);
373
    v8::Local<v8::Object> object = v8::Object::New();
374
    v8::Eternal<v8::Object> eternal(v8_isolate, object);
375
    CHECK(!eternal.IsEmpty());
376
    CHECK(object == eternal.Get(v8_isolate));
377
  }
378

    
379
  CHECK_EQ(2*kArrayLength + 1, eternal_handles->NumberOfHandles());
380
}