OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
| 28 #include <map> |
| 29 #include <vector> |
| 30 |
28 #include "global-handles.h" | 31 #include "global-handles.h" |
29 | 32 |
30 #include "cctest.h" | 33 #include "cctest.h" |
31 | 34 |
32 using namespace v8::internal; | 35 using namespace v8::internal; |
33 using v8::UniqueId; | 36 using v8::UniqueId; |
34 | 37 |
35 | 38 |
36 static List<Object*> skippable_objects; | 39 static List<Object*> skippable_objects; |
37 static List<Object*> can_skip_called_objects; | 40 static List<Object*> can_skip_called_objects; |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 ASSERT(implicit_refs->at(0)->parent == | 311 ASSERT(implicit_refs->at(0)->parent == |
309 reinterpret_cast<HeapObject**>(g1s1.location())); | 312 reinterpret_cast<HeapObject**>(g1s1.location())); |
310 ASSERT(implicit_refs->at(0)->length == 2); | 313 ASSERT(implicit_refs->at(0)->length == 2); |
311 ASSERT(implicit_refs->at(0)->children[0] == g1c1.location()); | 314 ASSERT(implicit_refs->at(0)->children[0] == g1c1.location()); |
312 ASSERT(implicit_refs->at(0)->children[1] == g1c2.location()); | 315 ASSERT(implicit_refs->at(0)->children[1] == g1c2.location()); |
313 ASSERT(implicit_refs->at(1)->parent == | 316 ASSERT(implicit_refs->at(1)->parent == |
314 reinterpret_cast<HeapObject**>(g2s1.location())); | 317 reinterpret_cast<HeapObject**>(g2s1.location())); |
315 ASSERT(implicit_refs->at(1)->length == 1); | 318 ASSERT(implicit_refs->at(1)->length == 1); |
316 ASSERT(implicit_refs->at(1)->children[0] == g2c1.location()); | 319 ASSERT(implicit_refs->at(1)->children[0] == g2c1.location()); |
317 } | 320 } |
| 321 |
| 322 |
| 323 static const int kBlockSize = 256; |
| 324 |
| 325 |
| 326 TEST(BlockCollection) { |
| 327 v8::V8::Initialize(); |
| 328 Isolate* isolate = Isolate::Current(); |
| 329 GlobalHandles* global_handles = isolate->global_handles(); |
| 330 CHECK_EQ(0, global_handles->block_count()); |
| 331 CHECK_EQ(0, global_handles->global_handles_count()); |
| 332 Object* object = isolate->heap()->undefined_value(); |
| 333 const int kNumberOfBlocks = 5; |
| 334 typedef Handle<Object> Block[kBlockSize]; |
| 335 for (int round = 0; round < 3; round++) { |
| 336 Block blocks[kNumberOfBlocks]; |
| 337 for (int i = 0; i < kNumberOfBlocks; i++) { |
| 338 for (int j = 0; j < kBlockSize; j++) { |
| 339 blocks[i][j] = global_handles->Create(object); |
| 340 } |
| 341 } |
| 342 CHECK_EQ(kNumberOfBlocks, global_handles->block_count()); |
| 343 for (int i = 0; i < kNumberOfBlocks; i++) { |
| 344 for (int j = 0; j < kBlockSize; j++) { |
| 345 global_handles->Destroy(blocks[i][j].location()); |
| 346 } |
| 347 } |
| 348 isolate->heap()->CollectAllAvailableGarbage("BlockCollection"); |
| 349 CHECK_EQ(0, global_handles->global_handles_count()); |
| 350 CHECK_EQ(1, global_handles->block_count()); |
| 351 } |
| 352 } |
| 353 |
| 354 |
| 355 class RandomMutationData { |
| 356 public: |
| 357 explicit RandomMutationData(Isolate* isolate) |
| 358 : isolate_(isolate), weak_offset_(0) {} |
| 359 |
| 360 void Mutate(double strong_growth_tendency, |
| 361 double weak_growth_tendency = 0.05) { |
| 362 for (int i = 0; i < kBlockSize * 100; i++) { |
| 363 if (rng_.next(strong_growth_tendency)) { |
| 364 AddStrong(); |
| 365 } else if (strong_nodes_.size() != 0) { |
| 366 size_t to_remove = rng_.next(static_cast<int>(strong_nodes_.size())); |
| 367 RemoveStrong(to_remove); |
| 368 } |
| 369 if (rng_.next(weak_growth_tendency)) AddWeak(); |
| 370 if (rng_.next(0.05)) { |
| 371 #ifdef DEBUG |
| 372 isolate_->global_handles()->VerifyBlockInvariants(); |
| 373 #endif |
| 374 } |
| 375 if (rng_.next(0.0001)) { |
| 376 isolate_->heap()->PerformScavenge(); |
| 377 } else if (rng_.next(0.00003)) { |
| 378 isolate_->heap()->CollectAllAvailableGarbage(); |
| 379 } |
| 380 CheckSizes(); |
| 381 } |
| 382 } |
| 383 |
| 384 void RemoveAll() { |
| 385 while (strong_nodes_.size() != 0) { |
| 386 RemoveStrong(strong_nodes_.size() - 1); |
| 387 } |
| 388 isolate_->heap()->PerformScavenge(); |
| 389 isolate_->heap()->CollectAllAvailableGarbage(); |
| 390 CheckSizes(); |
| 391 } |
| 392 |
| 393 private: |
| 394 typedef std::vector<Object**> NodeVector; |
| 395 typedef std::map<int32_t, Object**> NodeMap; |
| 396 |
| 397 void CheckSizes() { |
| 398 int stored_sizes = |
| 399 static_cast<int>(strong_nodes_.size() + weak_nodes_.size()); |
| 400 CHECK_EQ(isolate_->global_handles()->global_handles_count(), stored_sizes); |
| 401 } |
| 402 |
| 403 void AddStrong() { |
| 404 Object* object = isolate_->heap()->undefined_value(); |
| 405 Object** location = isolate_->global_handles()->Create(object).location(); |
| 406 strong_nodes_.push_back(location); |
| 407 } |
| 408 |
| 409 void RemoveStrong(size_t offset) { |
| 410 isolate_->global_handles()->Destroy(strong_nodes_.at(offset)); |
| 411 strong_nodes_.erase(strong_nodes_.begin() + offset); |
| 412 } |
| 413 |
| 414 void AddWeak() { |
| 415 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_); |
| 416 v8::HandleScope scope(isolate); |
| 417 v8::Local<v8::Object> object = v8::Object::New(); |
| 418 int32_t offset = ++weak_offset_; |
| 419 object->Set(7, v8::Integer::New(offset, isolate)); |
| 420 v8::Persistent<v8::Object> persistent(isolate, object); |
| 421 persistent.MakeWeak(isolate, this, WeakCallback); |
| 422 persistent.MarkIndependent(); |
| 423 Object** location = v8::Utils::OpenPersistent(persistent).location(); |
| 424 bool inserted = |
| 425 weak_nodes_.insert(std::make_pair(offset, location)).second; |
| 426 CHECK(inserted); |
| 427 } |
| 428 |
| 429 static void WeakCallback(v8::Isolate* isolate, |
| 430 v8::Persistent<v8::Object>* persistent, |
| 431 RandomMutationData* data) { |
| 432 v8::Local<v8::Object> object = |
| 433 v8::Local<v8::Object>::New(isolate, *persistent); |
| 434 int32_t offset = |
| 435 v8::Local<v8::Integer>::Cast(object->Get(7))->Int32Value(); |
| 436 Object** location = v8::Utils::OpenPersistent(persistent).location(); |
| 437 NodeMap& weak_nodes = data->weak_nodes_; |
| 438 NodeMap::iterator it = weak_nodes.find(offset); |
| 439 CHECK(it != weak_nodes.end()); |
| 440 CHECK(it->second == location); |
| 441 weak_nodes.erase(it); |
| 442 persistent->Dispose(); |
| 443 } |
| 444 |
| 445 Isolate* isolate_; |
| 446 RandomNumberGenerator rng_; |
| 447 NodeVector strong_nodes_; |
| 448 NodeMap weak_nodes_; |
| 449 int32_t weak_offset_; |
| 450 }; |
| 451 |
| 452 |
| 453 TEST(RandomMutation) { |
| 454 v8::V8::Initialize(); |
| 455 Isolate* isolate = Isolate::Current(); |
| 456 CHECK_EQ(0, isolate->global_handles()->block_count()); |
| 457 HandleScope handle_scope(isolate); |
| 458 v8::Context::Scope context_scope( |
| 459 v8::Context::New(reinterpret_cast<v8::Isolate*>(isolate))); |
| 460 RandomMutationData data(isolate); |
| 461 // grow some |
| 462 data.Mutate(0.65); |
| 463 data.Mutate(0.55); |
| 464 // balanced mutation |
| 465 for (int i = 0; i < 3; i++) data.Mutate(0.50); |
| 466 // shrink some |
| 467 data.Mutate(0.45); |
| 468 data.Mutate(0.35); |
| 469 // clear everything |
| 470 data.RemoveAll(); |
| 471 } |
OLD | NEW |