LCOV - code coverage report
Current view: top level - test/cctest/heap - test-external-string-tracker.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 87 87 100.0 %
Date: 2019-04-19 Functions: 11 11 100.0 %

          Line data    Source code
       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             : #include "src/api-inl.h"
       6             : #include "src/api.h"
       7             : #include "src/heap/heap-inl.h"
       8             : #include "src/heap/spaces.h"
       9             : #include "src/isolate.h"
      10             : #include "src/objects-inl.h"
      11             : #include "test/cctest/cctest.h"
      12             : #include "test/cctest/heap/heap-tester.h"
      13             : #include "test/cctest/heap/heap-utils.h"
      14             : 
      15             : #define TEST_STR "tests are great!"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : namespace heap {
      20             : 
      21             : // Adapted from cctest/test-api.cc
      22             : class TestOneByteResource : public v8::String::ExternalOneByteStringResource {
      23             :  public:
      24             :   explicit TestOneByteResource(const char* data, int* counter = nullptr,
      25             :                                size_t offset = 0)
      26             :       : orig_data_(data),
      27             :         data_(data + offset),
      28          30 :         length_(strlen(data) - offset),
      29          60 :         counter_(counter) {}
      30             : 
      31          90 :   ~TestOneByteResource() override {
      32          30 :     i::DeleteArray(orig_data_);
      33          30 :     if (counter_ != nullptr) ++*counter_;
      34          60 :   }
      35             : 
      36          85 :   const char* data() const override { return data_; }
      37             : 
      38          80 :   size_t length() const override { return length_; }
      39             : 
      40             :  private:
      41             :   const char* orig_data_;
      42             :   const char* data_;
      43             :   size_t length_;
      44             :   int* counter_;
      45             : };
      46             : 
      47       26661 : TEST(ExternalString_ExternalBackingStoreSizeIncreases) {
      48           5 :   CcTest::InitializeVM();
      49           5 :   LocalContext env;
      50           5 :   v8::Isolate* isolate = env->GetIsolate();
      51             :   Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
      52             :   ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
      53             : 
      54             :   const size_t backing_store_before =
      55           5 :       heap->old_space()->ExternalBackingStoreBytes(type);
      56             : 
      57             :   {
      58          10 :     v8::HandleScope handle_scope(isolate);
      59           5 :     v8::Local<v8::String> es = v8::String::NewExternalOneByte(
      60           5 :         isolate, new TestOneByteResource(i::StrDup(TEST_STR))).ToLocalChecked();
      61             :     USE(es);
      62             : 
      63             :     const size_t backing_store_after =
      64           5 :         heap->old_space()->ExternalBackingStoreBytes(type);
      65             : 
      66          10 :     CHECK_EQ(es->Length(), backing_store_after - backing_store_before);
      67             :   }
      68           5 : }
      69             : 
      70       26661 : TEST(ExternalString_ExternalBackingStoreSizeDecreases) {
      71             :   ManualGCScope manual_gc_scope;
      72           5 :   CcTest::InitializeVM();
      73           5 :   LocalContext env;
      74           5 :   v8::Isolate* isolate = env->GetIsolate();
      75             :   Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
      76             :   ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
      77             : 
      78             :   const size_t backing_store_before =
      79           5 :       heap->old_space()->ExternalBackingStoreBytes(type);
      80             : 
      81             :   {
      82          10 :     v8::HandleScope handle_scope(isolate);
      83           5 :     v8::Local<v8::String> es = v8::String::NewExternalOneByte(
      84           5 :         isolate, new TestOneByteResource(i::StrDup(TEST_STR))).ToLocalChecked();
      85             :     USE(es);
      86             :   }
      87             : 
      88           5 :   heap::GcAndSweep(heap, OLD_SPACE);
      89             : 
      90             :   const size_t backing_store_after =
      91           5 :       heap->old_space()->ExternalBackingStoreBytes(type);
      92             : 
      93           5 :   CHECK_EQ(0, backing_store_after - backing_store_before);
      94           5 : }
      95             : 
      96       26661 : TEST(ExternalString_ExternalBackingStoreSizeIncreasesMarkCompact) {
      97           5 :   if (FLAG_never_compact) return;
      98             :   ManualGCScope manual_gc_scope;
      99           5 :   FLAG_manual_evacuation_candidates_selection = true;
     100           5 :   CcTest::InitializeVM();
     101           5 :   LocalContext env;
     102           5 :   v8::Isolate* isolate = env->GetIsolate();
     103             :   Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
     104           5 :   heap::AbandonCurrentlyFreeMemory(heap->old_space());
     105             :   ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
     106             : 
     107             :   const size_t backing_store_before =
     108           5 :       heap->old_space()->ExternalBackingStoreBytes(type);
     109             : 
     110             :   {
     111          10 :     v8::HandleScope handle_scope(isolate);
     112           5 :     v8::Local<v8::String> es = v8::String::NewExternalOneByte(
     113           5 :         isolate, new TestOneByteResource(i::StrDup(TEST_STR))).ToLocalChecked();
     114             :     v8::internal::Handle<v8::internal::String> esh = v8::Utils::OpenHandle(*es);
     115             : 
     116             :     Page* page_before_gc = Page::FromHeapObject(*esh);
     117           5 :     heap::ForceEvacuationCandidate(page_before_gc);
     118             : 
     119           5 :     CcTest::CollectAllGarbage();
     120             : 
     121             :     const size_t backing_store_after =
     122           5 :         heap->old_space()->ExternalBackingStoreBytes(type);
     123          10 :     CHECK_EQ(es->Length(), backing_store_after - backing_store_before);
     124             :   }
     125             : 
     126           5 :   heap::GcAndSweep(heap, OLD_SPACE);
     127             :   const size_t backing_store_after =
     128           5 :       heap->old_space()->ExternalBackingStoreBytes(type);
     129           5 :   CHECK_EQ(0, backing_store_after - backing_store_before);
     130             : }
     131             : 
     132       26661 : TEST(ExternalString_ExternalBackingStoreSizeIncreasesAfterExternalization) {
     133           5 :   CcTest::InitializeVM();
     134           5 :   LocalContext env;
     135           5 :   v8::Isolate* isolate = env->GetIsolate();
     136             :   Heap* heap = reinterpret_cast<Isolate*>(isolate)->heap();
     137             :   ExternalBackingStoreType type = ExternalBackingStoreType::kExternalString;
     138             :   size_t old_backing_store_before = 0, new_backing_store_before = 0;
     139             : 
     140             :   {
     141          10 :     v8::HandleScope handle_scope(isolate);
     142             : 
     143             :     new_backing_store_before =
     144           5 :         heap->new_space()->ExternalBackingStoreBytes(type);
     145             :     old_backing_store_before =
     146           5 :         heap->old_space()->ExternalBackingStoreBytes(type);
     147             : 
     148             :     // Allocate normal string in the new gen.
     149             :     v8::Local<v8::String> str =
     150           5 :         v8::String::NewFromUtf8(isolate, TEST_STR, v8::NewStringType::kNormal)
     151             :             .ToLocalChecked();
     152             : 
     153          10 :     CHECK_EQ(0, heap->new_space()->ExternalBackingStoreBytes(type) -
     154             :                     new_backing_store_before);
     155             : 
     156             :     // Trigger GCs so that the newly allocated string moves to old gen.
     157           5 :     heap::GcAndSweep(heap, NEW_SPACE);  // in survivor space now
     158           5 :     heap::GcAndSweep(heap, NEW_SPACE);  // in old gen now
     159             : 
     160             :     bool success =
     161          10 :         str->MakeExternal(new TestOneByteResource(i::StrDup(TEST_STR)));
     162           5 :     CHECK(success);
     163             : 
     164          10 :     CHECK_EQ(str->Length(), heap->old_space()->ExternalBackingStoreBytes(type) -
     165             :                                 old_backing_store_before);
     166             :   }
     167             : 
     168           5 :   heap::GcAndSweep(heap, OLD_SPACE);
     169             : 
     170          10 :   CHECK_EQ(0, heap->old_space()->ExternalBackingStoreBytes(type) -
     171             :                   old_backing_store_before);
     172           5 : }
     173             : 
     174       26661 : TEST(ExternalString_PromotedThinString) {
     175             :   ManualGCScope manual_gc_scope;
     176           5 :   CcTest::InitializeVM();
     177           5 :   LocalContext env;
     178           5 :   v8::Isolate* isolate = env->GetIsolate();
     179             :   i::Isolate* i_isolate = CcTest::i_isolate();
     180             :   i::Factory* factory = i_isolate->factory();
     181             :   Heap* heap = i_isolate->heap();
     182             : 
     183             :   {
     184          10 :     v8::HandleScope handle_scope(isolate);
     185             : 
     186             :     // New external string in the old space.
     187             :     v8::internal::Handle<v8::internal::String> string1 =
     188             :         factory
     189          10 :             ->NewExternalStringFromOneByte(
     190           5 :                 new TestOneByteResource(i::StrDup(TEST_STR)))
     191             :             .ToHandleChecked();
     192             : 
     193             :     // Internalize external string.
     194           5 :     i::Handle<i::String> isymbol1 = factory->InternalizeString(string1);
     195           5 :     CHECK(isymbol1->IsInternalizedString());
     196           5 :     CHECK(string1->IsExternalString());
     197           5 :     CHECK(!heap->InYoungGeneration(*isymbol1));
     198             : 
     199             :     // New external string in the young space. This string has the same content
     200             :     // as the previous one (that was already internalized).
     201             :     v8::Local<v8::String> string2 =
     202           5 :         v8::String::NewFromUtf8(isolate, TEST_STR, v8::NewStringType::kNormal)
     203             :             .ToLocalChecked();
     204             :     bool success =
     205          10 :         string2->MakeExternal(new TestOneByteResource(i::StrDup(TEST_STR)));
     206           5 :     CHECK(success);
     207             : 
     208             :     // Internalize (it will create a thin string in the new space).
     209             :     i::Handle<i::String> istring = v8::Utils::OpenHandle(*string2);
     210           5 :     i::Handle<i::String> isymbol2 = factory->InternalizeString(istring);
     211           5 :     CHECK(isymbol2->IsInternalizedString());
     212           5 :     CHECK(istring->IsThinString());
     213           5 :     CHECK(heap->InYoungGeneration(*istring));
     214             : 
     215             :     // Collect thin string. References to the thin string will be updated to
     216             :     // point to the actual external string in the old space.
     217           5 :     heap::GcAndSweep(heap, NEW_SPACE);
     218             : 
     219             :     USE(isymbol1);
     220             :     USE(isymbol2);
     221             :   }
     222           5 : }
     223             : }  // namespace heap
     224             : }  // namespace internal
     225       79968 : }  // namespace v8
     226             : 
     227             : #undef TEST_STR

Generated by: LCOV version 1.10