Revision: 13341
Author: [email protected]
Date: Wed Jan 9 04:29:06 2013
Log: Some more instrumentation to narrow down Failure leaks.
The basic idea is to tag OOM-Failure objects with an ID indicating where
they were created. This requires changes to equality comparisons.
Note to MIPS folks: I'm planning to revert this CL in a couple of days, so
feel free to skip porting the platform-specific changes.
BUG=chromium:156010
Review URL: https://codereview.chromium.org/11818023
http://code.google.com/p/v8/source/detail?r=13341
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/execution.cc
/branches/bleeding_edge/src/heap-inl.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/x64/code-stubs-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Wed Jan 9 02:30:54
2013
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Wed Jan 9 04:29:06
2013
@@ -3930,6 +3930,18 @@
Handle<Code> code = stub.GetCode();
code->set_is_pregenerated(true);
}
+
+
+static void JumpIfOOM(MacroAssembler* masm,
+ Register value,
+ Register scratch,
+ Label* oom_label) {
+ STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3);
+ STATIC_ASSERT(kFailureTag == 3);
+ __ and_(scratch, value, Operand(0xf));
+ __ cmp(scratch, Operand(0xf));
+ __ b(eq, oom_label);
+}
void CEntryStub::GenerateCore(MacroAssembler* masm,
@@ -4031,9 +4043,7 @@
__ b(eq, &retry);
// Special handling of out of memory exceptions.
- Failure* out_of_memory = Failure::OutOfMemoryException();
- __ cmp(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
- __ b(eq, throw_out_of_memory_exception);
+ JumpIfOOM(masm, r0, ip, throw_out_of_memory_exception);
// Retrieve the pending exception and clear the variable.
__ mov(r3, Operand(isolate->factory()->the_hole_value()));
@@ -4125,8 +4135,11 @@
__ str(r0, MemOperand(r2));
// Set pending exception and r0 to out of memory exception.
- Failure* out_of_memory = Failure::OutOfMemoryException();
+ Label already_have_failure;
+ JumpIfOOM(masm, r0, ip, &already_have_failure);
+ Failure* out_of_memory = Failure::OutOfMemoryException(0x1);
__ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
+ __ bind(&already_have_failure);
__ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
isolate)));
__ str(r0, MemOperand(r2));
=======================================
--- /branches/bleeding_edge/src/execution.cc Thu Dec 13 09:21:15 2012
+++ /branches/bleeding_edge/src/execution.cc Wed Jan 9 04:29:06 2013
@@ -127,7 +127,7 @@
ASSERT(*has_pending_exception ==
Isolate::Current()->has_pending_exception());
if (*has_pending_exception) {
isolate->ReportPendingMessages();
- if (isolate->pending_exception() == Failure::OutOfMemoryException()) {
+ if (isolate->pending_exception()->IsOutOfMemory()) {
if (!isolate->ignore_out_of_memory()) {
V8::FatalProcessOutOfMemory("JS", true);
}
=======================================
--- /branches/bleeding_edge/src/heap-inl.h Wed Jan 9 02:30:54 2013
+++ /branches/bleeding_edge/src/heap-inl.h Wed Jan 9 04:29:06 2013
@@ -134,7 +134,7 @@
MaybeObject* Heap::AllocateOneByteSymbol(Vector<const uint8_t> str,
uint32_t hash_field) {
if (str.length() > SeqOneByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x2);
}
// Compute map and object size.
Map* map = ascii_symbol_map();
@@ -168,7 +168,7 @@
MaybeObject* Heap::AllocateTwoByteSymbol(Vector<const uc16> str,
uint32_t hash_field) {
if (str.length() > SeqTwoByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x3);
}
// Compute map and object size.
Map* map = symbol_map();
=======================================
--- /branches/bleeding_edge/src/heap.cc Wed Jan 9 02:30:54 2013
+++ /branches/bleeding_edge/src/heap.cc Wed Jan 9 04:29:06 2013
@@ -3362,7 +3362,7 @@
// of the new cons string is too large.
if (length > String::kMaxLength || length < 0) {
isolate()->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x4);
}
bool is_ascii_data_in_two_byte_string = false;
@@ -3550,7 +3550,7 @@
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x5);
}
ASSERT(String::IsAscii(resource->data(), static_cast<int>(length)));
@@ -3575,7 +3575,7 @@
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x6);
}
// For small strings we check whether the resource contains only
@@ -3627,7 +3627,7 @@
MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) {
if (length < 0 || length > ByteArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x7);
}
if (pretenure == NOT_TENURED) {
return AllocateByteArray(length);
@@ -3649,7 +3649,7 @@
MaybeObject* Heap::AllocateByteArray(int length) {
if (length < 0 || length > ByteArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x8);
}
int size = ByteArray::SizeFor(length);
AllocationSpace space =
@@ -4700,13 +4700,13 @@
if (is_one_byte) {
if (chars > SeqOneByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x9);
}
map = ascii_symbol_map();
size = SeqOneByteString::SizeFor(chars);
} else {
if (chars > SeqTwoByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xa);
}
map = symbol_map();
size = SeqTwoByteString::SizeFor(chars);
@@ -4751,7 +4751,7 @@
MaybeObject* Heap::AllocateRawOneByteString(int length,
PretenureFlag pretenure) {
if (length < 0 || length > SeqOneByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xb);
}
int size = SeqOneByteString::SizeFor(length);
@@ -4799,7 +4799,7 @@
MaybeObject* Heap::AllocateRawTwoByteString(int length,
PretenureFlag pretenure) {
if (length < 0 || length > SeqTwoByteString::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xc);
}
int size = SeqTwoByteString::SizeFor(length);
ASSERT(size <= SeqTwoByteString::kMaxSize);
@@ -4868,7 +4868,7 @@
MaybeObject* Heap::AllocateRawFixedArray(int length) {
if (length < 0 || length > FixedArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xd);
}
ASSERT(length > 0);
// Use the general function if we're forced to always allocate.
@@ -4944,7 +4944,7 @@
MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag
pretenure) {
if (length < 0 || length > FixedArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xe);
}
AllocationSpace space =
@@ -5077,7 +5077,7 @@
MaybeObject* Heap::AllocateRawFixedDoubleArray(int length,
PretenureFlag pretenure) {
if (length < 0 || length > FixedDoubleArray::kMaxLength) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0xf);
}
AllocationSpace space =
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Wed Jan 9 02:30:54
2013
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Wed Jan 9 04:29:06
2013
@@ -4876,6 +4876,19 @@
Handle<Code> code = stub.GetCode();
code->set_is_pregenerated(true);
}
+
+
+static void JumpIfOOM(MacroAssembler* masm,
+ Register value,
+ Register scratch,
+ Label* oom_label) {
+ __ mov(scratch, value);
+ STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3);
+ STATIC_ASSERT(kFailureTag == 3);
+ __ and_(scratch, 0xf);
+ __ cmp(scratch, 0xf);
+ __ j(equal, oom_label);
+}
void CEntryStub::GenerateCore(MacroAssembler* masm,
@@ -4975,8 +4988,7 @@
__ j(zero, &retry, Label::kNear);
// Special handling of out of memory exceptions.
- __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
- __ j(equal, throw_out_of_memory_exception);
+ JumpIfOOM(masm, eax, ecx, throw_out_of_memory_exception);
// Retrieve the pending exception and clear the variable.
__ mov(eax, Operand::StaticVariable(pending_exception_address));
@@ -5058,7 +5070,10 @@
// Set pending exception and eax to out of memory exception.
ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
isolate);
- __ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
+ Label already_have_failure;
+ JumpIfOOM(masm, eax, ecx, &already_have_failure);
+ __ mov(eax,
reinterpret_cast<int32_t>(Failure::OutOfMemoryException(0x1)));
+ __ bind(&already_have_failure);
__ mov(Operand::StaticVariable(pending_exception), eax);
// Fall through to the next label.
=======================================
--- /branches/bleeding_edge/src/isolate.cc Mon Dec 31 03:13:50 2012
+++ /branches/bleeding_edge/src/isolate.cc Wed Jan 9 04:29:06 2013
@@ -1344,7 +1344,7 @@
// since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
// set it.
HandleScope scope;
- if (thread_local_top_.pending_exception_ ==
Failure::OutOfMemoryException()) {
+ if (thread_local_top_.pending_exception_->IsOutOfMemory()) {
context()->mark_out_of_memory();
} else if (thread_local_top_.pending_exception_ ==
heap()->termination_exception()) {
@@ -1375,7 +1375,7 @@
MessageLocation Isolate::GetMessageLocation() {
ASSERT(has_pending_exception());
- if (thread_local_top_.pending_exception_ !=
Failure::OutOfMemoryException() &&
+ if (!thread_local_top_.pending_exception_->IsOutOfMemory() &&
thread_local_top_.pending_exception_ !=
heap()->termination_exception() &&
thread_local_top_.has_pending_message_ &&
!thread_local_top_.pending_message_obj_->IsTheHole() &&
@@ -1889,7 +1889,7 @@
if (!external_caught) return;
- if (thread_local_top_.pending_exception_ ==
Failure::OutOfMemoryException()) {
+ if (thread_local_top_.pending_exception_->IsOutOfMemory()) {
// Do not propagate OOM exception: we should kill VM asap.
} else if (thread_local_top_.pending_exception_ ==
heap()->termination_exception()) {
=======================================
--- /branches/bleeding_edge/src/isolate.h Mon Dec 31 03:13:50 2012
+++ /branches/bleeding_edge/src/isolate.h Wed Jan 9 04:29:06 2013
@@ -615,7 +615,7 @@
bool IsExternallyCaught();
bool is_catchable_by_javascript(MaybeObject* exception) {
- return (exception != Failure::OutOfMemoryException()) &&
+ return (!exception->IsOutOfMemory()) &&
(exception != heap()->termination_exception());
}
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Wed Jan 9 02:30:54 2013
+++ /branches/bleeding_edge/src/objects-inl.h Wed Jan 9 04:29:06 2013
@@ -1043,8 +1043,8 @@
}
-Failure* Failure::OutOfMemoryException() {
- return Construct(OUT_OF_MEMORY_EXCEPTION);
+Failure* Failure::OutOfMemoryException(intptr_t value) {
+ return Construct(OUT_OF_MEMORY_EXCEPTION, value);
}
=======================================
--- /branches/bleeding_edge/src/objects.cc Wed Jan 9 02:30:54 2013
+++ /branches/bleeding_edge/src/objects.cc Wed Jan 9 04:29:06 2013
@@ -11640,7 +11640,7 @@
? at_least_space_for
: ComputeCapacity(at_least_space_for);
if (capacity > HashTable::kMaxCapacity) {
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x10);
}
Object* obj;
=======================================
--- /branches/bleeding_edge/src/objects.h Wed Jan 9 02:30:54 2013
+++ /branches/bleeding_edge/src/objects.h Wed Jan 9 04:29:06 2013
@@ -1144,7 +1144,9 @@
static inline Failure* RetryAfterGC(); // NEW_SPACE
static inline Failure* Exception();
static inline Failure* InternalError();
- static inline Failure* OutOfMemoryException();
+ // TODO(jkummerow): The value is temporary instrumentation. Remove it
+ // when it has served its purpose.
+ static inline Failure* OutOfMemoryException(intptr_t value);
// Casting.
static inline Failure* cast(MaybeObject* object);
=======================================
--- /branches/bleeding_edge/src/runtime.cc Wed Jan 9 02:30:54 2013
+++ /branches/bleeding_edge/src/runtime.cc Wed Jan 9 04:29:06 2013
@@ -1804,25 +1804,27 @@
result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
source,
final);
- ASSERT(!result->IsFailure());
+ // TODO(jkummerow): Turn these back into ASSERTs when we can be certain
+ // that it never fires in Release mode in the wild.
+ CHECK(!result->IsFailure());
result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
global,
final);
- ASSERT(!result->IsFailure());
+ CHECK(!result->IsFailure());
result =
regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
ignoreCase,
final);
- ASSERT(!result->IsFailure());
+ CHECK(!result->IsFailure());
result =
regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
multiline,
final);
- ASSERT(!result->IsFailure());
+ CHECK(!result->IsFailure());
result =
regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
Smi::FromInt(0),
writable);
- ASSERT(!result->IsFailure());
+ CHECK(!result->IsFailure());
USE(result);
return regexp;
}
@@ -2913,7 +2915,7 @@
static_cast<int64_t>(pattern_len)) *
static_cast<int64_t>(matches) +
static_cast<int64_t>(subject_len);
- if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException();
+ if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11);
int result_len = static_cast<int>(result_len_64);
int subject_pos = 0;
@@ -5160,7 +5162,7 @@
ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow.
if (escaped_length > String::kMaxLength) {
isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x12);
}
}
}
@@ -5767,7 +5769,7 @@
current_length += char_length;
if (current_length > Smi::kMaxValue) {
isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x13);
}
}
// Try again with the real length.
@@ -6437,7 +6439,7 @@
CONVERT_ARG_CHECKED(JSArray, array, 0);
if (!args[1]->IsSmi()) {
isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x14);
}
int array_length = args.smi_at(1);
CONVERT_ARG_CHECKED(String, special, 2);
@@ -6514,7 +6516,7 @@
}
if (increment > String::kMaxLength - position) {
isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x15);
}
position += increment;
}
@@ -6554,7 +6556,7 @@
CONVERT_ARG_CHECKED(JSArray, array, 0);
if (!args[1]->IsSmi()) {
isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x16);
}
int array_length = args.smi_at(1);
CONVERT_ARG_CHECKED(String, separator, 2);
@@ -6579,7 +6581,7 @@
(String::kMaxLength + separator_length - 1) / separator_length;
if (max_nof_separators < (array_length - 1)) {
isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x17);
}
int length = (array_length - 1) * separator_length;
for (int i = 0; i < array_length; i++) {
@@ -6592,7 +6594,7 @@
int increment = element->length();
if (increment > String::kMaxLength - length) {
isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException();
+ return Failure::OutOfMemoryException(0x18);
}
length += increment;
}
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Wed Jan 9 02:30:54
2013
+++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Wed Jan 9 04:29:06
2013
@@ -3925,6 +3925,19 @@
CEntryStub save_doubles(1, kSaveFPRegs);
save_doubles.GetCode()->set_is_pregenerated(true);
}
+
+
+static void JumpIfOOM(MacroAssembler* masm,
+ Register value,
+ Register scratch,
+ Label* oom_label) {
+ __ movq(scratch, value);
+ STATIC_ASSERT(Failure::OUT_OF_MEMORY_EXCEPTION == 3);
+ STATIC_ASSERT(kFailureTag == 3);
+ __ and_(scratch, Immediate(0xf));
+ __ cmpq(scratch, Immediate(0xf));
+ __ j(equal, oom_label);
+}
void CEntryStub::GenerateCore(MacroAssembler* masm,
@@ -4040,9 +4053,7 @@
__ j(zero, &retry, Label::kNear);
// Special handling of out of memory exceptions.
- __ movq(kScratchRegister, Failure::OutOfMemoryException(),
RelocInfo::NONE64);
- __ cmpq(rax, kScratchRegister);
- __ j(equal, throw_out_of_memory_exception);
+ JumpIfOOM(masm, rax, kScratchRegister, throw_out_of_memory_exception);
// Retrieve the pending exception and clear the variable.
ExternalReference pending_exception_address(
@@ -4139,7 +4150,10 @@
// Set pending exception and rax to out of memory exception.
ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
isolate);
- __ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE64);
+ Label already_have_failure;
+ JumpIfOOM(masm, rax, kScratchRegister, &already_have_failure);
+ __ movq(rax, Failure::OutOfMemoryException(0x1), RelocInfo::NONE64);
+ __ bind(&already_have_failure);
__ Store(pending_exception, rax);
// Fall through to the next label.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev