Preprocess structured stack trace on GC to get rid of code reference.
R=verwaest@chromium.org BUG=v8:2340 LOG=N Review URL: https://codereview.chromium.org/1103843002 Cr-Commit-Position: refs/heads/master@{#28085}
This commit is contained in:
parent
671ac25cf9
commit
462ffa1dfa
@ -644,6 +644,10 @@ class Factory final {
|
|||||||
isolate()->heap()->set_string_table(*table);
|
isolate()->heap()->set_string_table(*table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void set_weak_stack_trace_list(Handle<WeakFixedArray> list) {
|
||||||
|
isolate()->heap()->set_weak_stack_trace_list(*list);
|
||||||
|
}
|
||||||
|
|
||||||
Handle<String> hidden_string() {
|
Handle<String> hidden_string() {
|
||||||
return Handle<String>(&isolate()->heap()->hidden_string_);
|
return Handle<String>(&isolate()->heap()->hidden_string_);
|
||||||
}
|
}
|
||||||
|
@ -706,6 +706,26 @@ void Heap::GarbageCollectionEpilogue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Heap::PreprocessStackTraces() {
|
||||||
|
if (!weak_stack_trace_list()->IsWeakFixedArray()) return;
|
||||||
|
WeakFixedArray* array = WeakFixedArray::cast(weak_stack_trace_list());
|
||||||
|
int length = array->Length();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (array->IsEmptySlot(i)) continue;
|
||||||
|
FixedArray* elements = FixedArray::cast(array->Get(i));
|
||||||
|
for (int j = 1; j < elements->length(); j += 4) {
|
||||||
|
Code* code = Code::cast(elements->get(j + 2));
|
||||||
|
int offset = Smi::cast(elements->get(j + 3))->value();
|
||||||
|
Address pc = code->address() + offset;
|
||||||
|
int pos = code->SourcePosition(pc);
|
||||||
|
elements->set(j + 2, Smi::FromInt(pos));
|
||||||
|
}
|
||||||
|
array->Clear(i);
|
||||||
|
}
|
||||||
|
array->Compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Heap::HandleGCRequest() {
|
void Heap::HandleGCRequest() {
|
||||||
if (incremental_marking()->request_type() ==
|
if (incremental_marking()->request_type() ==
|
||||||
IncrementalMarking::COMPLETE_MARKING) {
|
IncrementalMarking::COMPLETE_MARKING) {
|
||||||
@ -1272,6 +1292,8 @@ void Heap::MarkCompactEpilogue() {
|
|||||||
isolate_->counters()->objs_since_last_full()->Set(0);
|
isolate_->counters()->objs_since_last_full()->Set(0);
|
||||||
|
|
||||||
incremental_marking()->Epilogue();
|
incremental_marking()->Epilogue();
|
||||||
|
|
||||||
|
PreprocessStackTraces();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3082,6 +3104,8 @@ void Heap::CreateInitialObjects() {
|
|||||||
cell->set_value(Smi::FromInt(Isolate::kArrayProtectorValid));
|
cell->set_value(Smi::FromInt(Isolate::kArrayProtectorValid));
|
||||||
set_array_protector(*cell);
|
set_array_protector(*cell);
|
||||||
|
|
||||||
|
set_weak_stack_trace_list(Smi::FromInt(0));
|
||||||
|
|
||||||
set_allocation_sites_scratchpad(
|
set_allocation_sites_scratchpad(
|
||||||
*factory->NewFixedArray(kAllocationSiteScratchpadSize, TENURED));
|
*factory->NewFixedArray(kAllocationSiteScratchpadSize, TENURED));
|
||||||
InitializeAllocationSitesScratchpad();
|
InitializeAllocationSitesScratchpad();
|
||||||
@ -3118,6 +3142,7 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
|
|||||||
case kDetachedContextsRootIndex:
|
case kDetachedContextsRootIndex:
|
||||||
case kWeakObjectToCodeTableRootIndex:
|
case kWeakObjectToCodeTableRootIndex:
|
||||||
case kRetainedMapsRootIndex:
|
case kRetainedMapsRootIndex:
|
||||||
|
case kWeakStackTraceListRootIndex:
|
||||||
// Smi values
|
// Smi values
|
||||||
#define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
|
#define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
|
||||||
SMI_ROOT_LIST(SMI_ENTRY)
|
SMI_ROOT_LIST(SMI_ENTRY)
|
||||||
|
@ -186,7 +186,8 @@ namespace internal {
|
|||||||
V(FixedArray, detached_contexts, DetachedContexts) \
|
V(FixedArray, detached_contexts, DetachedContexts) \
|
||||||
V(ArrayList, retained_maps, RetainedMaps) \
|
V(ArrayList, retained_maps, RetainedMaps) \
|
||||||
V(WeakHashTable, weak_object_to_code_table, WeakObjectToCodeTable) \
|
V(WeakHashTable, weak_object_to_code_table, WeakObjectToCodeTable) \
|
||||||
V(PropertyCell, array_protector, ArrayProtector)
|
V(PropertyCell, array_protector, ArrayProtector) \
|
||||||
|
V(Object, weak_stack_trace_list, WeakStackTraceList)
|
||||||
|
|
||||||
// Entries in this list are limited to Smis and are not visited during GC.
|
// Entries in this list are limited to Smis and are not visited during GC.
|
||||||
#define SMI_ROOT_LIST(V) \
|
#define SMI_ROOT_LIST(V) \
|
||||||
@ -1742,6 +1743,8 @@ class Heap {
|
|||||||
void GarbageCollectionPrologue();
|
void GarbageCollectionPrologue();
|
||||||
void GarbageCollectionEpilogue();
|
void GarbageCollectionEpilogue();
|
||||||
|
|
||||||
|
void PreprocessStackTraces();
|
||||||
|
|
||||||
// Pretenuring decisions are made based on feedback collected during new
|
// Pretenuring decisions are made based on feedback collected during new
|
||||||
// space evacuation. Note that between feedback collection and calling this
|
// space evacuation. Note that between feedback collection and calling this
|
||||||
// method object in old space must not move.
|
// method object in old space must not move.
|
||||||
|
@ -407,8 +407,13 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
elements->set(0, Smi::FromInt(sloppy_frames));
|
elements->set(0, Smi::FromInt(sloppy_frames));
|
||||||
|
elements->Shrink(cursor);
|
||||||
Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
|
Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
|
||||||
result->set_length(Smi::FromInt(cursor));
|
result->set_length(Smi::FromInt(cursor));
|
||||||
|
// Queue this structured stack trace for preprocessing on GC.
|
||||||
|
Handle<WeakFixedArray> new_weak_list =
|
||||||
|
WeakFixedArray::Add(factory()->weak_stack_trace_list(), elements);
|
||||||
|
factory()->set_weak_stack_trace_list(new_weak_list);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,7 +1009,7 @@ function GetStackFrames(raw_stack) {
|
|||||||
var fun = raw_stack[i + 1];
|
var fun = raw_stack[i + 1];
|
||||||
var code = raw_stack[i + 2];
|
var code = raw_stack[i + 2];
|
||||||
var pc = raw_stack[i + 3];
|
var pc = raw_stack[i + 3];
|
||||||
var pos = %FunctionGetPositionForOffset(code, pc);
|
var pos = %_IsSmi(code) ? code : %FunctionGetPositionForOffset(code, pc);
|
||||||
sloppy_frames--;
|
sloppy_frames--;
|
||||||
frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
|
frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
|
||||||
}
|
}
|
||||||
|
@ -2356,7 +2356,7 @@ bool WeakFixedArray::IsEmptySlot(int index) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WeakFixedArray::clear(int index) {
|
void WeakFixedArray::Clear(int index) {
|
||||||
FixedArray::cast(this)->set(index + kFirstIndex, Smi::FromInt(0));
|
FixedArray::cast(this)->set(index + kFirstIndex, Smi::FromInt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8347,7 +8347,7 @@ bool WeakFixedArray::Remove(Handle<HeapObject> value) {
|
|||||||
int first_index = last_used_index();
|
int first_index = last_used_index();
|
||||||
for (int i = first_index;;) {
|
for (int i = first_index;;) {
|
||||||
if (Get(i) == *value) {
|
if (Get(i) == *value) {
|
||||||
clear(i);
|
Clear(i);
|
||||||
// Users of WeakFixedArray should make sure that there are no duplicates,
|
// Users of WeakFixedArray should make sure that there are no duplicates,
|
||||||
// they can use Add(..., kAddIfNotFound) if necessary.
|
// they can use Add(..., kAddIfNotFound) if necessary.
|
||||||
return true;
|
return true;
|
||||||
|
@ -2632,8 +2632,10 @@ class WeakFixedArray : public FixedArray {
|
|||||||
void Compact();
|
void Compact();
|
||||||
|
|
||||||
inline Object* Get(int index) const;
|
inline Object* Get(int index) const;
|
||||||
|
inline void Clear(int index);
|
||||||
inline int Length() const;
|
inline int Length() const;
|
||||||
|
|
||||||
|
inline bool IsEmptySlot(int index) const;
|
||||||
static Object* Empty() { return Smi::FromInt(0); }
|
static Object* Empty() { return Smi::FromInt(0); }
|
||||||
|
|
||||||
DECLARE_CAST(WeakFixedArray)
|
DECLARE_CAST(WeakFixedArray)
|
||||||
@ -2648,7 +2650,6 @@ class WeakFixedArray : public FixedArray {
|
|||||||
static void Set(Handle<WeakFixedArray> array, int index,
|
static void Set(Handle<WeakFixedArray> array, int index,
|
||||||
Handle<HeapObject> value);
|
Handle<HeapObject> value);
|
||||||
inline void clear(int index);
|
inline void clear(int index);
|
||||||
inline bool IsEmptySlot(int index) const;
|
|
||||||
|
|
||||||
inline int last_used_index() const;
|
inline int last_used_index() const;
|
||||||
inline void set_last_used_index(int index);
|
inline void set_last_used_index(int index);
|
||||||
|
@ -5379,3 +5379,36 @@ TEST(WeakFixedArray) {
|
|||||||
array->Compact();
|
array->Compact();
|
||||||
WeakFixedArray::Add(array, number);
|
WeakFixedArray::Add(array, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(PreprocessStackTrace) {
|
||||||
|
// Do not automatically trigger early GC.
|
||||||
|
FLAG_gc_interval = -1;
|
||||||
|
CcTest::InitializeVM();
|
||||||
|
v8::HandleScope scope(CcTest::isolate());
|
||||||
|
v8::TryCatch try_catch;
|
||||||
|
CompileRun("throw new Error();");
|
||||||
|
CHECK(try_catch.HasCaught());
|
||||||
|
Isolate* isolate = CcTest::i_isolate();
|
||||||
|
Handle<Object> exception = v8::Utils::OpenHandle(*try_catch.Exception());
|
||||||
|
Handle<Name> key = isolate->factory()->stack_trace_symbol();
|
||||||
|
Handle<Object> stack_trace =
|
||||||
|
JSObject::GetProperty(exception, key).ToHandleChecked();
|
||||||
|
Handle<Object> code =
|
||||||
|
Object::GetElement(isolate, stack_trace, 3).ToHandleChecked();
|
||||||
|
CHECK(code->IsCode());
|
||||||
|
|
||||||
|
isolate->heap()->CollectAllAvailableGarbage("stack trace preprocessing");
|
||||||
|
|
||||||
|
Handle<Object> pos =
|
||||||
|
Object::GetElement(isolate, stack_trace, 3).ToHandleChecked();
|
||||||
|
CHECK(pos->IsSmi());
|
||||||
|
|
||||||
|
Handle<JSArray> stack_trace_array = Handle<JSArray>::cast(stack_trace);
|
||||||
|
int array_length = Smi::cast(stack_trace_array->length())->value();
|
||||||
|
for (int i = 0; i < array_length; i++) {
|
||||||
|
Handle<Object> element =
|
||||||
|
Object::GetElement(isolate, stack_trace, i).ToHandleChecked();
|
||||||
|
CHECK(!element->IsCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user