| Index: src/factory.cc
|
| diff --git a/src/factory.cc b/src/factory.cc
|
| index 12d7f5750e3909c37d680b33052e5e38a343c72c..d6dd38d963d6dfeff29c20fe56ff14ca2344ed94 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>(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(
|
|
|