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>(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<TYPE>(); \
+ } while (false)
+
+
template<typename T>
Handle<T> Factory::New(Handle<Map> map, AllocationSpace space) {
CALL_HEAP_FUNCTION(
}
-// 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>(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<TYPE>(); \
- } while (false)
-
-
void Heap::ExternalStringTable::AddString(String* string) {
DCHECK(string->IsExternalString());
if (heap_->InNewSpace(string)) {
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();
Handle<Object> 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());
}