From df7df4df2aab9251a1ee4b995b58e805e0ce8800 Mon Sep 17 00:00:00 2001 From: mstarzinger Date: Mon, 28 Sep 2015 11:08:17 -0700 Subject: [PATCH] [heap] Move CALL_HEAP_FUNCTION macro into factory.cc file. R=hpayer@chromium.org Review URL: https://codereview.chromium.org/1372063002 Cr-Commit-Position: refs/heads/master@{#30985} --- src/factory.cc | 38 ++++++++++++++++++++++++++++++++++++++ src/heap/heap-inl.h | 38 -------------------------------------- test/cctest/test-alloc.cc | 17 ++++++----------- 3 files changed, 44 insertions(+), 49 deletions(-) diff --git a/src/factory.cc b/src/factory.cc index 12d7f57..d6dd38d 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -15,6 +15,44 @@ namespace v8 { namespace internal { +// Calls the FUNCTION_CALL function and retries it up to three times +// to guarantee that any allocations performed during the call will +// succeed if there's enough memory. +// +// Warning: Do not use the identifiers __object__, __maybe_object__, +// __allocation__ or __scope__ in a call to this macro. + +#define RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ + if (__allocation__.To(&__object__)) { \ + DCHECK(__object__ != (ISOLATE)->heap()->exception()); \ + return Handle(TYPE::cast(__object__), ISOLATE); \ + } + +#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE) \ + do { \ + AllocationResult __allocation__ = FUNCTION_CALL; \ + Object* __object__ = NULL; \ + RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ + /* Two GCs before panicking. In newspace will almost always succeed. */ \ + for (int __i__ = 0; __i__ < 2; __i__++) { \ + (ISOLATE)->heap()->CollectGarbage(__allocation__.RetrySpace(), \ + "allocation failure"); \ + __allocation__ = FUNCTION_CALL; \ + RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ + } \ + (ISOLATE)->counters()->gc_last_resort_from_handles()->Increment(); \ + (ISOLATE)->heap()->CollectAllAvailableGarbage("last resort gc"); \ + { \ + AlwaysAllocateScope __scope__(ISOLATE); \ + __allocation__ = FUNCTION_CALL; \ + } \ + RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ + /* TODO(1181417): Fix this. */ \ + v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \ + return Handle(); \ + } while (false) + + template Handle Factory::New(Handle map, AllocationSpace space) { CALL_HEAP_FUNCTION( diff --git a/src/heap/heap-inl.h b/src/heap/heap-inl.h index d903180..3f06764 100644 --- a/src/heap/heap-inl.h +++ b/src/heap/heap-inl.h @@ -537,44 +537,6 @@ Isolate* Heap::isolate() { } -// Calls the FUNCTION_CALL function and retries it up to three times -// to guarantee that any allocations performed during the call will -// succeed if there's enough memory. -// -// Warning: Do not use the identifiers __object__, __maybe_object__, -// __allocation__ or __scope__ in a call to this macro. - -#define RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ - if (__allocation__.To(&__object__)) { \ - DCHECK(__object__ != (ISOLATE)->heap()->exception()); \ - return Handle(TYPE::cast(__object__), ISOLATE); \ - } - -#define CALL_HEAP_FUNCTION(ISOLATE, FUNCTION_CALL, TYPE) \ - do { \ - AllocationResult __allocation__ = FUNCTION_CALL; \ - Object* __object__ = NULL; \ - RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ - /* Two GCs before panicking. In newspace will almost always succeed. */ \ - for (int __i__ = 0; __i__ < 2; __i__++) { \ - (ISOLATE)->heap()->CollectGarbage(__allocation__.RetrySpace(), \ - "allocation failure"); \ - __allocation__ = FUNCTION_CALL; \ - RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ - } \ - (ISOLATE)->counters()->gc_last_resort_from_handles()->Increment(); \ - (ISOLATE)->heap()->CollectAllAvailableGarbage("last resort gc"); \ - { \ - AlwaysAllocateScope __scope__(ISOLATE); \ - __allocation__ = FUNCTION_CALL; \ - } \ - RETURN_OBJECT_UNLESS_RETRY(ISOLATE, TYPE) \ - /* TODO(1181417): Fix this. */ \ - v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \ - return Handle(); \ - } while (false) - - void Heap::ExternalStringTable::AddString(String* string) { DCHECK(string->IsExternalString()); if (heap_->InNewSpace(string)) { diff --git a/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc index d7043c2..b9d0f61 100644 --- a/test/cctest/test-alloc.cc +++ b/test/cctest/test-alloc.cc @@ -37,18 +37,8 @@ using namespace v8::internal; AllocationResult v8::internal::HeapTester::AllocateAfterFailures() { - static int attempts = 0; - - // The first 4 times we simulate a full heap, by returning retry. - if (++attempts < 4) return AllocationResult::Retry(); - - // Expose some private stuff on Heap. Heap* heap = CcTest::heap(); - // Now that we have returned 'retry' 4 times, we are in a last-chance - // scenario, with always_allocate. See CALL_AND_RETRY. Test that all - // allocations succeed. - // New space. heap->AllocateByteArray(100).ToObjectChecked(); heap->AllocateFixedArray(100, NOT_TENURED).ToObjectChecked(); @@ -98,7 +88,12 @@ AllocationResult v8::internal::HeapTester::AllocateAfterFailures() { Handle v8::internal::HeapTester::TestAllocateAfterFailures() { - CALL_HEAP_FUNCTION(CcTest::i_isolate(), AllocateAfterFailures(), Object); + // Similar to what the CALL_AND_RETRY macro does in the last-resort case, we + // are wrapping the allocator function in an AlwaysAllocateScope. Test that + // all allocations succeed immediately without any retry. + CcTest::heap()->CollectAllAvailableGarbage("panic"); + AlwaysAllocateScope scope(CcTest::i_isolate()); + return handle(AllocateAfterFailures().ToObjectChecked(), CcTest::i_isolate()); } -- 2.7.4