13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h> 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef __linux__ 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <errno.h> 323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <fcntl.h> 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/stat.h> 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <sys/types.h> 353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <unistd.h> 363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <utility> 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h" 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/global-handles.h" 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/snapshot.h" 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h" 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing namespace v8::internal; 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 503ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(MarkingDeque) { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int mem_size = 20 * kPointerSize; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block byte* mem = NewArray<byte>(20*kPointerSize); 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address low = reinterpret_cast<Address>(mem); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address high = low + mem_size; 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MarkingDeque s; 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block s.Initialize(low, high); 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address original_address = reinterpret_cast<Address>(&s); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address current_address = original_address; 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!s.IsFull()) { 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s.PushBlack(HeapObject::FromAddress(current_address)); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_address += kPointerSize; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!s.IsEmpty()) { 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address value = s.Pop()->address(); 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current_address -= kPointerSize; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(current_address, value); 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(original_address, current_address); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DeleteArray(mem); 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Promotion) { 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TestHeap* heap = CcTest::test_heap(); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->ConfigureHeap(1, 1, 1, 0); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope sc(CcTest::isolate()); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate a fixed array in the new space. 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int array_length = 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) / 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (4 * kPointerSize); 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* obj = heap->AllocateFixedArray(array_length).ToObjectChecked(); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> array(FixedArray::cast(obj)); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array should be in the new space. 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(heap->InSpace(*array, NEW_SPACE)); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call mark compact GC, so array becomes an old object. 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Array now sits in the old space 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(heap->InSpace(*array, OLD_POINTER_SPACE)); 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(NoPromotion) { 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TestHeap* heap = CcTest::test_heap(); 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->ConfigureHeap(1, 1, 1, 0); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope sc(CcTest::isolate()); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate a big fixed array in the new space. 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int array_length = 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) / 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (2 * kPointerSize); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* obj = heap->AllocateFixedArray(array_length).ToObjectChecked(); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> array(FixedArray::cast(obj)); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Array should be in the new space. 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(heap->InSpace(*array, NEW_SPACE)); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Simulate a full old space to make promotion fail. 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SimulateFullSpace(heap->old_pointer_space()); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call mark compact GC, and it should pass. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(OLD_POINTER_SPACE); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MarkCompactCollector) { 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLAG_incremental_marking = false; 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = CcTest::i_isolate(); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TestHeap* heap = CcTest::test_heap(); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate->factory(); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope sc(CcTest::isolate()); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<GlobalObject> global(isolate->context()->global_object()); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // call mark-compact when heap is empty 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 1"); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // keep allocating garbage in new space until it fails 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int arraysize = 100; 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationResult allocation; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation = heap->AllocateFixedArray(arraysize); 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (!allocation.IsRetry()); 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(NEW_SPACE, "trigger 2"); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->AllocateFixedArray(arraysize).ToObjectChecked(); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // keep allocating maps until it fails 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation = heap->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (!allocation.IsRetry()); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(MAP_SPACE, "trigger 3"); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize).ToObjectChecked(); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { HandleScope scope(isolate); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // allocate a garbage 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> func_name = factory->InternalizeUtf8String("theFunction"); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> function = factory->NewFunction(func_name); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSReceiver::SetProperty(global, func_name, function, SLOPPY).Check(); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory->NewJSObject(function); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 4"); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { HandleScope scope(isolate); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> func_name = factory->InternalizeUtf8String("theFunction"); 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, func_name); 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(maybe.has_value); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(maybe.value); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> func_value = 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object::GetProperty(global, func_name).ToHandleChecked(); 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(func_value->IsJSFunction()); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSFunction> function = Handle<JSFunction>::cast(func_value); 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> obj = factory->NewJSObject(function); 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> obj_name = factory->InternalizeUtf8String("theObject"); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSReceiver::SetProperty(global, obj_name, obj, SLOPPY).Check(); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> prop_name = factory->InternalizeUtf8String("theSlot"); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Smi> twenty_three(Smi::FromInt(23), isolate); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSReceiver::SetProperty(obj, prop_name, twenty_three, SLOPPY).Check(); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(OLD_POINTER_SPACE, "trigger 5"); 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { HandleScope scope(isolate); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> obj_name = factory->InternalizeUtf8String("theObject"); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Maybe<bool> maybe = JSReceiver::HasOwnProperty(global, obj_name); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(maybe.has_value); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(maybe.value); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> object = 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object::GetProperty(global, obj_name).ToHandleChecked(); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(object->IsJSObject()); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> prop_name = factory->InternalizeUtf8String("theSlot"); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(*Object::GetProperty(object, prop_name).ToHandleChecked(), 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(23)); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(1600): compaction of map space is temporary removed from GC. 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if 0 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Handle<Map> CreateMap(Isolate* isolate) { 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return isolate->factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 207d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTEST(MapCompact) { 211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke FLAG_max_map_space_pages = 16; 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = CcTest::i_isolate(); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate->factory(); 215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke { 217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke v8::HandleScope sc; 218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // keep allocating maps while pointers are still encodable and thus 219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // mark compact is permitted. 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSObject> root = factory->NewJSObjectFromMap(CreateMap()); 221d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke do { 222d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Handle<Map> map = CreateMap(); 223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke map->set_prototype(*root); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch root = factory->NewJSObjectFromMap(map); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (CcTest::heap()->map_space()->MapPointersEncodable()); 226d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 227d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Now, as we don't have any handles to just allocated maps, we should 228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // be able to trigger map compaction. 229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // To give an additional chance to fail, try to force compaction which 230d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // should be impossible right now. 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::heap()->CollectAllGarbage(Heap::kForceCompactionMask); 232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // And now map pointers should be encodable again. 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(CcTest::heap()->map_space()->MapPointersEncodable()); 234d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 236d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int NumberOfWeakCalls = 0; 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void WeakPointerCallback( 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const v8::WeakCallbackData<v8::Value, void>& data) { 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<v8::Persistent<v8::Value>*, int>* p = 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<std::pair<v8::Persistent<v8::Value>*, int>*>( 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data.GetParameter()); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(1234, p->second); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NumberOfWeakCalls++; 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch p->first->Reset(); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(ObjectGroups) { 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLAG_incremental_marking = false; 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles* global_handles = CcTest::i_isolate()->global_handles(); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TestHeap* heap = CcTest::test_heap(); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NumberOfWeakCalls = 0; 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope handle_scope(CcTest::isolate()); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g1s1 = 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g1s2 = 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); 26244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Object> g1c1 = 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<Handle<Object>*, int> g1s1_and_id(&g1s1, 1234); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g1s1.location(), 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g1s1_and_id), 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<Handle<Object>*, int> g1s2_and_id(&g1s2, 1234); 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g1s2.location(), 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g1s2_and_id), 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<Handle<Object>*, int> g1c1_and_id(&g1c1, 1234); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g1c1.location(), 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g1c1_and_id), 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g2s1 = 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> g2s2 = 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); 28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Object> g2c1 = 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->Create(heap->AllocateFixedArray(1).ToObjectChecked()); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<Handle<Object>*, int> g2s1_and_id(&g2s1, 1234); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g2s1.location(), 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g2s1_and_id), 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<Handle<Object>*, int> g2s2_and_id(&g2s2, 1234); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g2s2.location(), 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g2s2_and_id), 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<Handle<Object>*, int> g2c1_and_id(&g2c1, 1234); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g2c1.location(), 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g2c1_and_id), 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 29644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Object> root = global_handles->Create(*g1s1); // make a root. 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Connect group 1 and 2, make a cycle. 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray>::cast(g1s2)->set(0, *g2s2); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray>::cast(g2s1)->set(0, *g1s1); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g1_objects[] = { g1s1.location(), g1s2.location() }; 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g2_objects[] = { g2s1.location(), g2s2.location() }; 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->AddObjectGroup(g1_objects, 2, NULL); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->SetReference(Handle<HeapObject>::cast(g1s1).location(), 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g1c1.location()); 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->AddObjectGroup(g2_objects, 2, NULL); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->SetReference(Handle<HeapObject>::cast(g2s1).location(), 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g2c1.location()); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do a full GC 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(OLD_POINTER_SPACE); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All object should be alive. 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(0, NumberOfWeakCalls); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Weaken the root. 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<Handle<Object>*, int> root_and_id(&root, 1234); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(root.location(), 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&root_and_id), 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // But make children strong roots---all the objects (except for children) 32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // should be collectable now. 32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->ClearWeakness(g1c1.location()); 32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->ClearWeakness(g2c1.location()); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Groups are deleted, rebuild groups. 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g1_objects[] = { g1s1.location(), g1s2.location() }; 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** g2_objects[] = { g2s1.location(), g2s2.location() }; 33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->AddObjectGroup(g1_objects, 2, NULL); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->SetReference(Handle<HeapObject>::cast(g1s1).location(), 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g1c1.location()); 33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->AddObjectGroup(g2_objects, 2, NULL); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_handles->SetReference(Handle<HeapObject>::cast(g2s1).location(), 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g2c1.location()); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(OLD_POINTER_SPACE); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // All objects should be gone. 5 global handles in total. 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(5, NumberOfWeakCalls); 34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // And now make children weak again and collect them. 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g1c1.location(), 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g1c1_and_id), 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles::MakeWeak(g2c1.location(), 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<void*>(&g2c1_and_id), 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &WeakPointerCallback); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->CollectGarbage(OLD_POINTER_SPACE); 35444f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(7, NumberOfWeakCalls); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass TestRetainedObjectInfo : public v8::RetainedObjectInfo { 3598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 3608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TestRetainedObjectInfo() : has_been_disposed_(false) {} 3618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool has_been_disposed() { return has_been_disposed_; } 3638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual void Dispose() { 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!has_been_disposed_); 3668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch has_been_disposed_ = true; 3678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual bool IsEquivalent(v8::RetainedObjectInfo* other) { 3708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return other == this; 3718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual intptr_t GetHash() { return 0; } 3748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual const char* GetLabel() { return "whatever"; } 3768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 3788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool has_been_disposed_; 3798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 3808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3828b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTEST(EmptyObjectGroups) { 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CcTest::InitializeVM(); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandles* global_handles = CcTest::i_isolate()->global_handles(); 3858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope handle_scope(CcTest::isolate()); 3878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TestRetainedObjectInfo info; 3898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch global_handles->AddObjectGroup(NULL, 0, &info); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info.has_been_disposed()); 3918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__has_feature) 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if __has_feature(address_sanitizer) 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_WITH_ASAN 1 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Here is a memory use test that uses /proc, and is therefore Linux-only. We 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// do not care how much memory the simulator uses, since it is only there for 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// debugging purposes. Testing with ASAN doesn't make sense, either. 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(__linux__) && !defined(USE_SIMULATOR) && !defined(V8_WITH_ASAN) 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic uintptr_t ReadLong(char* buffer, intptr_t* position, int base) { 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char* end_address = buffer + *position; 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t result = strtoul(buffer + *position, &end_address, base); 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK(result != ULONG_MAX || errno != ERANGE); 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK(end_address > buffer + *position); 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *position = end_address - buffer; 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return result; 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The memory use computed this way is not entirely accurate and depends on 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the way malloc allocates memory. That's why the memory use may seem to 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// increase even though the sum of the allocated object sizes decreases. It 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// also means that the memory use depends on the kernel and stdlib. 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic intptr_t MemoryInUse() { 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t memory_use = 0; 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int fd = open("/proc/self/maps", O_RDONLY); 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fd < 0) return -1; 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int kBufSize = 10000; 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char buffer[kBufSize]; 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int length = read(fd, buffer, kBufSize); 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t line_start = 0; 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_LT(length, kBufSize); // Make the buffer bigger. 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_GT(length, 0); // We have to find some data in the file. 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (line_start < length) { 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (buffer[line_start] == '\n') { 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch line_start++; 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch continue; 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t position = line_start; 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t start = ReadLong(buffer, &position, 16); 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_EQ(buffer[position++], '-'); 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t end = ReadLong(buffer, &position, 16); 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_EQ(buffer[position++], ' '); 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK(buffer[position] == '-' || buffer[position] == 'r'); 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool read_permission = (buffer[position++] == 'r'); 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK(buffer[position] == '-' || buffer[position] == 'w'); 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool write_permission = (buffer[position++] == 'w'); 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK(buffer[position] == '-' || buffer[position] == 'x'); 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool execute_permission = (buffer[position++] == 'x'); 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK(buffer[position] == '-' || buffer[position] == 'p'); 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool private_mapping = (buffer[position++] == 'p'); 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_EQ(buffer[position++], ' '); 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t offset = ReadLong(buffer, &position, 16); 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(offset); 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_EQ(buffer[position++], ' '); 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t major = ReadLong(buffer, &position, 16); 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(major); 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_EQ(buffer[position++], ':'); 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t minor = ReadLong(buffer, &position, 16); 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(minor); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_EQ(buffer[position++], ' '); 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t inode = ReadLong(buffer, &position, 10); 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (position < length && buffer[position] != '\n') position++; 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((read_permission || write_permission || execute_permission) && 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private_mapping && inode == 0) { 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch memory_use += (end - start); 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch line_start = position; 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch close(fd); 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return memory_use; 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t ShortLivingIsolate() { 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Isolate* isolate = v8::Isolate::New(); 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { v8::Isolate::Scope isolate_scope(isolate); 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Locker lock(isolate); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HandleScope handle_scope(isolate); 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::Local<v8::Context> context = v8::Context::New(isolate); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!context.IsEmpty()); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->Dispose(); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MemoryInUse(); 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(RegressJoinThreadsOnIsolateDeinit) { 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t size_limit = ShortLivingIsolate() * 2; 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < 10; i++) { 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_GT(size_limit, ShortLivingIsolate()); 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif // __linux__ and !USE_SIMULATOR 496