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

Generated by: LCOV version 1.10