Home | History | Annotate | Download | only in cctest
      1 // Copyright 2014 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 "test/cctest/cctest.h"
     29 
     30 using namespace v8::internal;
     31 
     32 
     33 static void SetUpNewSpaceWithPoisonedMementoAtTop() {
     34   Isolate* isolate = CcTest::i_isolate();
     35   Heap* heap = isolate->heap();
     36   NewSpace* new_space = heap->new_space();
     37 
     38   // Make sure we can allocate some objects without causing a GC later.
     39   heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
     40 
     41   // Allocate a string, the GC may suspect a memento behind the string.
     42   Handle<SeqOneByteString> string =
     43       isolate->factory()->NewRawOneByteString(12).ToHandleChecked();
     44   CHECK(*string);
     45 
     46   // Create an allocation memento behind the string with a garbage allocation
     47   // site pointer.
     48   AllocationMemento* memento =
     49       reinterpret_cast<AllocationMemento*>(new_space->top() + kHeapObjectTag);
     50   memento->set_map_no_write_barrier(heap->allocation_memento_map());
     51   memento->set_allocation_site(
     52       reinterpret_cast<AllocationSite*>(kHeapObjectTag), SKIP_WRITE_BARRIER);
     53 }
     54 
     55 
     56 TEST(Regress340063) {
     57   CcTest::InitializeVM();
     58   if (!i::FLAG_allocation_site_pretenuring) return;
     59   v8::HandleScope scope(CcTest::isolate());
     60 
     61 
     62   SetUpNewSpaceWithPoisonedMementoAtTop();
     63 
     64   // Call GC to see if we can handle a poisonous memento right after the
     65   // current new space top pointer.
     66   CcTest::i_isolate()->heap()->CollectAllGarbage(
     67       Heap::kAbortIncrementalMarkingMask);
     68 }
     69 
     70 
     71 TEST(BadMementoAfterTopForceScavenge) {
     72   CcTest::InitializeVM();
     73   if (!i::FLAG_allocation_site_pretenuring) return;
     74   v8::HandleScope scope(CcTest::isolate());
     75 
     76   SetUpNewSpaceWithPoisonedMementoAtTop();
     77 
     78   // Force GC to test the poisoned memento handling
     79   CcTest::i_isolate()->heap()->CollectGarbage(i::NEW_SPACE);
     80 }
     81 
     82 
     83 TEST(PretenuringCallNew) {
     84   CcTest::InitializeVM();
     85   if (!i::FLAG_allocation_site_pretenuring) return;
     86   if (!i::FLAG_pretenuring_call_new) return;
     87 
     88   v8::HandleScope scope(CcTest::isolate());
     89   Isolate* isolate = CcTest::i_isolate();
     90   Heap* heap = isolate->heap();
     91 
     92   int call_count = 10;
     93   i::ScopedVector<char> test_buf(1024);
     94   const char* program =
     95       "function f() {"
     96       "  this.a = 3;"
     97       "  this.b = {};"
     98       "  return this;"
     99       "};"
    100       "var a;"
    101       "for(var i = 0; i < %d; i++) {"
    102       "  a = new f();"
    103       "}"
    104       "a;";
    105   i::SNPrintF(test_buf, program, call_count);
    106   v8::Local<v8::Value> res = CompileRun(test_buf.start());
    107   Handle<JSObject> o =
    108       v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
    109 
    110   // The object of class f should have a memento secreted behind it.
    111   Address memento_address = o->address() + o->map()->instance_size();
    112   AllocationMemento* memento =
    113       reinterpret_cast<AllocationMemento*>(memento_address + kHeapObjectTag);
    114   CHECK_EQ(memento->map(), heap->allocation_memento_map());
    115 
    116   // Furthermore, how many mementos did we create? The count should match
    117   // call_count. Note, that mementos are allocated during the inobject slack
    118   // tracking phase.
    119   AllocationSite* site = memento->GetAllocationSite();
    120   CHECK_EQ(call_count, site->pretenure_create_count()->value());
    121 }
    122