From: erik.corry@gmail.com Date: Thu, 30 Oct 2008 11:12:08 +0000 (+0000) Subject: Fix 3 places where we were doing retry after GC without using the macros that X-Git-Tag: upstream/4.7.83~25073 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8a8a24870b8bd8af18ea0f8f74a002fe5b9ffb36;p=platform%2Fupstream%2Fv8.git Fix 3 places where we were doing retry after GC without using the macros that were defined for that purpose. Review URL: http://codereview.chromium.org/8734 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@650 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/builtins.cc b/src/builtins.cc index 9309c1c98..fdff2d215 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -642,13 +642,12 @@ void Builtins::Setup(bool create_heap_objects) { CodeDesc desc; masm.GetCode(&desc); Code::Flags flags = functions[i].flags; - Object* code = Heap::CreateCode(desc, NULL, flags); - if (code->IsFailure()) { - if (code->IsRetryAfterGC()) { - CHECK(Heap::CollectGarbage(Failure::cast(code)->requested(), - Failure::cast(code)->allocation_space())); - code = Heap::CreateCode(desc, NULL, flags); - } + Object* code; + { + // During startup it's OK to always allocate and defer GC to later. + // This simplifies things because we don't need to retry. + AlwaysAllocateScope __scope__; + code = Heap::CreateCode(desc, NULL, flags); if (code->IsFailure()) { v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); } diff --git a/src/factory.cc b/src/factory.cc index 0adf25899..4b0faef5b 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -452,6 +452,7 @@ Handle Factory::NewFunctionWithPrototype(Handle name, return function; } + Handle Factory::NewCode(const CodeDesc& desc, ScopeInfo<>* sinfo, Code::Flags flags) { CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags), Code); @@ -463,42 +464,26 @@ Handle Factory::CopyCode(Handle code) { } -#define CALL_GC(RETRY) \ - do { \ - if (!Heap::CollectGarbage(Failure::cast(RETRY)->requested(), \ - Failure::cast(RETRY)->allocation_space())) { \ - /* TODO(1181417): Fix this. */ \ - V8::FatalProcessOutOfMemory("Factory CALL_GC"); \ - } \ - } while (false) +static inline Object* DoCopyInsert(DescriptorArray* array, + String* key, + Object* value, + PropertyAttributes attributes) { + CallbacksDescriptor desc(key, value, attributes); + Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS); + return obj; +} -// Allocate the new array. We cannot use the CALL_HEAP_FUNCTION macro here, -// because the stack-allocated CallbacksDescriptor instance is not GC safe. +// Allocate the new array. Handle Factory::CopyAppendProxyDescriptor( Handle array, Handle key, Handle value, PropertyAttributes attributes) { - GC_GREEDY_CHECK(); - CallbacksDescriptor desc(*key, *value, attributes); - Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS); - if (obj->IsFailure()) { - if (obj->IsRetryAfterGC()) { - CALL_GC(obj); - CallbacksDescriptor desc(*key, *value, attributes); - obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS); - } - if (obj->IsFailure()) { - // TODO(1181417): Fix this. - V8::FatalProcessOutOfMemory("CopyAppendProxyDescriptor"); - } - } - return Handle(DescriptorArray::cast(obj)); + CALL_HEAP_FUNCTION(DoCopyInsert(*array, *key, *value, attributes), + DescriptorArray); } -#undef CALL_GC - Handle Factory::SymbolFromString(Handle value) { CALL_HEAP_FUNCTION(Heap::LookupSymbol(*value), String); diff --git a/src/jsregexp.cc b/src/jsregexp.cc index 02b53e00d..115ff2783 100644 --- a/src/jsregexp.cc +++ b/src/jsregexp.cc @@ -307,15 +307,55 @@ Handle RegExpImpl::AtomExecGlobal(Handle re, } -Handle RegExpImpl::JsreCompile(Handle re, - Handle pattern, - JSRegExp::Flags flags) { +static inline Object* DoCompile(String* pattern, + JSRegExp::Flags flags, + unsigned* number_of_captures, + const char** error_message, + JscreRegExp** code) { JSRegExpIgnoreCaseOption case_option = flags.is_ignore_case() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase; JSRegExpMultilineOption multiline_option = flags.is_multiline() ? JSRegExpMultiline : JSRegExpSingleLine; + *error_message = NULL; + malloc_failure = Failure::Exception(); + *code = jsRegExpCompile(pattern->GetTwoByteData(), + pattern->length(), + case_option, + multiline_option, + number_of_captures, + error_message, + &JSREMalloc, + &JSREFree); + if (code == NULL && (malloc_failure->IsRetryAfterGC() || + malloc_failure->IsOutOfMemoryFailure())) { + return malloc_failure; + } else { + // It doesn't matter which object we return here, we just need to return + // a non-failure to indicate to the GC-retry code that there was no + // allocation failure. + return pattern; + } +} + + +void CompileWithRetryAfterGC(Handle pattern, + JSRegExp::Flags flags, + unsigned* number_of_captures, + const char** error_message, + JscreRegExp** code) { + CALL_HEAP_FUNCTION_VOID(DoCompile(*pattern, + flags, + number_of_captures, + error_message, + code)); +} + + +Handle RegExpImpl::JsreCompile(Handle re, + Handle pattern, + JSRegExp::Flags flags) { Handle two_byte_pattern = StringToTwoByte(pattern); @@ -325,52 +365,33 @@ Handle RegExpImpl::JsreCompile(Handle re, JscreRegExp* code = NULL; FlattenString(pattern); - bool first_time = true; + CompileWithRetryAfterGC(two_byte_pattern, + flags, + &number_of_captures, + &error_message, + &code); - while (true) { - malloc_failure = Failure::Exception(); - code = jsRegExpCompile(two_byte_pattern->GetTwoByteData(), - pattern->length(), case_option, - multiline_option, &number_of_captures, - &error_message, &JSREMalloc, &JSREFree); - if (code == NULL) { - if (first_time && malloc_failure->IsRetryAfterGC()) { - first_time = false; - if (!Heap::CollectGarbage(malloc_failure->requested(), - malloc_failure->allocation_space())) { - // TODO(1181417): Fix this. - V8::FatalProcessOutOfMemory("RegExpImpl::JsreCompile"); - } - continue; - } - if (malloc_failure->IsRetryAfterGC() || - malloc_failure->IsOutOfMemoryFailure()) { - // TODO(1181417): Fix this. - V8::FatalProcessOutOfMemory("RegExpImpl::JsreCompile"); - } else { - // Throw an exception. - Handle array = Factory::NewJSArray(2); - SetElement(array, 0, pattern); - SetElement(array, 1, Factory::NewStringFromUtf8(CStrVector( - (error_message == NULL) ? "Unknown regexp error" : error_message))); - Handle regexp_err = - Factory::NewSyntaxError("malformed_regexp", array); - return Handle(Top::Throw(*regexp_err)); - } - } + if (code == NULL) { + // Throw an exception. + Handle array = Factory::NewJSArray(2); + SetElement(array, 0, pattern); + SetElement(array, 1, Factory::NewStringFromUtf8(CStrVector( + (error_message == NULL) ? "Unknown regexp error" : error_message))); + Handle regexp_err = + Factory::NewSyntaxError("malformed_regexp", array); + return Handle(Top::Throw(*regexp_err)); + } - ASSERT(code != NULL); - // Convert the return address to a ByteArray pointer. - Handle internal( - ByteArray::FromDataStartAddress(reinterpret_cast
(code))); + // Convert the return address to a ByteArray pointer. + Handle internal( + ByteArray::FromDataStartAddress(reinterpret_cast
(code))); - Handle value = Factory::NewFixedArray(2); - value->set(CAPTURE_INDEX, Smi::FromInt(number_of_captures)); - value->set(INTERNAL_INDEX, *internal); - Factory::SetRegExpData(re, JSRegExp::JSCRE, pattern, flags, value); + Handle value = Factory::NewFixedArray(2); + value->set(CAPTURE_INDEX, Smi::FromInt(number_of_captures)); + value->set(INTERNAL_INDEX, *internal); + Factory::SetRegExpData(re, JSRegExp::JSCRE, pattern, flags, value); - return re; - } + return re; }