masm.GetCode(&desc);
Code::Flags flags = functions[i].flags;
Object* code = Heap::CreateCode(desc, NULL, flags);
- if (code->IsRetryAfterGC()) {
- CHECK(Heap::CollectGarbage(Failure::cast(code)->requested(),
- Failure::cast(code)->allocation_space()));
- 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);
+ }
+ if (code->IsFailure()) {
+ v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
+ }
}
// Add any unresolved jumps or calls to the fixup list in the
// bootstrapper.
GC_GREEDY_CHECK();
CallbacksDescriptor desc(*key, *value, attributes);
Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS);
- if (obj->IsRetryAfterGC()) {
- CALL_GC(obj);
- CallbacksDescriptor desc(*key, *value, attributes);
- 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");
unsigned number_of_captures;
const char* error_message = NULL;
- malloc_failure = Failure::Exception();
- JscreRegExp* code;
+ JscreRegExp* code = NULL;
FlattenString(pattern);
- if (pattern->IsAsciiRepresentation()) {
- Vector<const char> contents = pattern->ToAsciiVector();
- code = jsRegExpCompile(contents.start(),
- contents.length(),
- case_option,
- multiline_option,
- &number_of_captures,
- &error_message,
- &JSREMalloc,
- &JSREFree);
- } else {
- Vector<const uc16> contents = pattern->ToUC16Vector();
- code = jsRegExpCompile(contents.start(),
- contents.length(),
- case_option,
- multiline_option,
- &number_of_captures,
- &error_message,
- &JSREMalloc,
- &JSREFree);
- }
+ bool first_time = true;
- if (code == NULL && malloc_failure->IsRetryAfterGC()) {
- // Performs a GC, then retries.
- if (!Heap::CollectGarbage(malloc_failure->requested(),
- malloc_failure->allocation_space())) {
- // TODO(1181417): Fix this.
- V8::FatalProcessOutOfMemory("RegExpImpl::JsreCompile");
- }
+ while (true) {
+ first_time = false;
malloc_failure = Failure::Exception();
-
if (pattern->IsAsciiRepresentation()) {
Vector<const char> contents = pattern->ToAsciiVector();
code = jsRegExpCompile(contents.start(),
&JSREMalloc,
&JSREFree);
}
-
- if (code == NULL && malloc_failure->IsRetryAfterGC()) {
- // TODO(1181417): Fix this.
- V8::FatalProcessOutOfMemory("RegExpImpl::JsreCompile");
+ if (code == NULL) {
+ if (first_time && malloc_failure->IsRetryAfterGC()) {
+ 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<JSArray> array = Factory::NewJSArray(2);
+ SetElement(array, 0, pattern);
+ SetElement(array, 1, Factory::NewStringFromUtf8(CStrVector(
+ (error_message == NULL) ? "Unknown regexp error" : error_message)));
+ Handle<Object> regexp_err =
+ Factory::NewSyntaxError("malformed_regexp", array);
+ return Handle<Object>(Top::Throw(*regexp_err));
+ }
}
- }
-
- if (error_message != NULL) {
- // Throw an exception.
- Handle<JSArray> array = Factory::NewJSArray(2);
- SetElement(array, 0, pattern);
- SetElement(array, 1, Factory::NewStringFromUtf8(CStrVector(error_message)));
- Handle<Object> regexp_err =
- Factory::NewSyntaxError("malformed_regexp", array);
- return Handle<Object>(Top::Throw(*regexp_err));
- }
- ASSERT(code != NULL);
+ ASSERT(code != NULL);
- // Convert the return address to a ByteArray pointer.
- Handle<ByteArray> internal(
- ByteArray::FromDataStartAddress(reinterpret_cast<Address>(code)));
+ // Convert the return address to a ByteArray pointer.
+ Handle<ByteArray> internal(
+ ByteArray::FromDataStartAddress(reinterpret_cast<Address>(code)));
- Handle<FixedArray> value = Factory::NewFixedArray(2);
- value->set(CAPTURE_INDEX, Smi::FromInt(number_of_captures));
- value->set(INTERNAL_INDEX, *internal);
- re->set_type_tag(JSRegExp::JSCRE);
- re->set_data(*value);
+ Handle<FixedArray> value = Factory::NewFixedArray(2);
+ value->set(CAPTURE_INDEX, Smi::FromInt(number_of_captures));
+ value->set(INTERNAL_INDEX, *internal);
+ re->set_type_tag(JSRegExp::JSCRE);
+ re->set_data(*value);
- return re;
+ return re;
+ }
}
}
+static const char* js_code_causing_huge_string_flattening =
+ "var str = 'X';"
+ "for (var i = 0; i < 29; i++) {"
+ " str = str + str;"
+ "}"
+ "str.match(/X/);";
+
+
+void OOMCallback(const char* location, const char* message) {
+ exit(0);
+}
+
+
+TEST(RegexpOutOfMemory) {
+ // Execute a script that causes out of memory when flattening a string.
+ v8::HandleScope scope;
+ v8::V8::SetFatalErrorHandler(OOMCallback);
+ LocalContext context;
+ Local<Script> script =
+ Script::Compile(String::New(js_code_causing_huge_string_flattening));
+ last_location = NULL;
+ Local<Value> result = script->Run();
+
+ CHECK(false); // Should not return.
+}
+
+
static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
v8::Handle<Value> data) {
CHECK_EQ(v8::Undefined(), data);