Commit 4c5efa99 authored by yangguo's avatar yangguo Committed by Commit bot

Introduce SharedFunctionInfo::Iterator and Script::Iterator.

R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/1300333003

Cr-Commit-Position: refs/heads/master@{#30283}
parent 01579c6e
...@@ -1424,17 +1424,17 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, ...@@ -1424,17 +1424,17 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
while (true) { while (true) {
// Go through all shared function infos associated with this script to // Go through all shared function infos associated with this script to
// find the inner most function containing this position. // find the inner most function containing this position.
// If there is no shared function info for this script at all, there is
// no point in looking for it by walking the heap.
if (!script->shared_function_infos()->IsWeakFixedArray()) break; if (!script->shared_function_infos()->IsWeakFixedArray()) break;
WeakFixedArray* array =
WeakFixedArray::cast(script->shared_function_infos());
SharedFunctionInfo* shared; SharedFunctionInfo* shared;
{ {
SharedFunctionInfoFinder finder(position); SharedFunctionInfoFinder finder(position);
for (int i = 0; i < array->Length(); i++) { WeakFixedArray::Iterator iterator(script->shared_function_infos());
Object* item = array->Get(i); SharedFunctionInfo* candidate;
if (!item->IsSharedFunctionInfo()) continue; while ((candidate = iterator.Next<SharedFunctionInfo>())) {
finder.NewCandidate(SharedFunctionInfo::cast(item)); finder.NewCandidate(candidate);
} }
shared = finder.Result(); shared = finder.Result();
if (shared == NULL) break; if (shared == NULL) break;
...@@ -1608,8 +1608,7 @@ void Debug::ClearMirrorCache() { ...@@ -1608,8 +1608,7 @@ void Debug::ClearMirrorCache() {
Handle<FixedArray> Debug::GetLoadedScripts() { Handle<FixedArray> Debug::GetLoadedScripts() {
isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, isolate_->heap()->CollectAllGarbage();
"Debug::GetLoadedScripts");
Factory* factory = isolate_->factory(); Factory* factory = isolate_->factory();
if (!factory->script_list()->IsWeakFixedArray()) { if (!factory->script_list()->IsWeakFixedArray()) {
return factory->empty_fixed_array(); return factory->empty_fixed_array();
...@@ -1618,10 +1617,11 @@ Handle<FixedArray> Debug::GetLoadedScripts() { ...@@ -1618,10 +1617,11 @@ Handle<FixedArray> Debug::GetLoadedScripts() {
Handle<WeakFixedArray>::cast(factory->script_list()); Handle<WeakFixedArray>::cast(factory->script_list());
Handle<FixedArray> results = factory->NewFixedArray(array->Length()); Handle<FixedArray> results = factory->NewFixedArray(array->Length());
int length = 0; int length = 0;
for (int i = 0; i < array->Length(); ++i) { {
Object* item = array->Get(i); Script::Iterator iterator(isolate_);
if (item->IsScript() && Script::cast(item)->HasValidSource()) { Script* script;
results->set(length++, item); while ((script = iterator.Next())) {
if (script->HasValidSource()) results->set(length++, script);
} }
} }
results->Shrink(length); results->Shrink(length);
......
...@@ -715,12 +715,9 @@ void Heap::GarbageCollectionEpilogue() { ...@@ -715,12 +715,9 @@ void Heap::GarbageCollectionEpilogue() {
void Heap::PreprocessStackTraces() { void Heap::PreprocessStackTraces() {
if (!weak_stack_trace_list()->IsWeakFixedArray()) return; WeakFixedArray::Iterator iterator(weak_stack_trace_list());
WeakFixedArray* array = WeakFixedArray::cast(weak_stack_trace_list()); FixedArray* elements;
int length = array->Length(); while ((elements = iterator.Next<FixedArray>())) {
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) { for (int j = 1; j < elements->length(); j += 4) {
Object* maybe_code = elements->get(j + 2); Object* maybe_code = elements->get(j + 2);
// If GC happens while adding a stack trace to the weak fixed array, // If GC happens while adding a stack trace to the weak fixed array,
......
...@@ -2523,6 +2523,21 @@ void WeakFixedArray::set_last_used_index(int index) { ...@@ -2523,6 +2523,21 @@ void WeakFixedArray::set_last_used_index(int index) {
} }
template <class T>
T* WeakFixedArray::Iterator::Next() {
if (list_ != NULL) {
// Assert that list did not change during iteration.
DCHECK_EQ(last_used_index_, list_->last_used_index());
while (index_ < list_->Length()) {
Object* item = list_->Get(index_++);
if (item != Empty()) return T::cast(item);
}
list_ = NULL;
}
return NULL;
}
int ArrayList::Length() { int ArrayList::Length() {
if (FixedArray::cast(this)->length() == 0) return 0; if (FixedArray::cast(this)->length() == 0) return 0;
return Smi::cast(FixedArray::cast(this)->get(kLengthIndex))->value(); return Smi::cast(FixedArray::cast(this)->get(kLengthIndex))->value();
......
...@@ -7816,6 +7816,17 @@ void WeakFixedArray::Compact() { ...@@ -7816,6 +7816,17 @@ void WeakFixedArray::Compact() {
} }
void WeakFixedArray::Iterator::Reset(Object* maybe_array) {
if (maybe_array->IsWeakFixedArray()) {
list_ = WeakFixedArray::cast(maybe_array);
index_ = 0;
#ifdef DEBUG
last_used_index_ = list_->last_used_index();
#endif // DEBUG
}
}
void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value, void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value,
int old_index, int old_index,
int new_index) { int new_index) {
...@@ -9666,16 +9677,10 @@ static void InvalidatePrototypeChainsInternal(Map* map) { ...@@ -9666,16 +9677,10 @@ static void InvalidatePrototypeChainsInternal(Map* map) {
cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid)); cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
} }
Object* maybe_array = proto_info->prototype_users(); WeakFixedArray::Iterator iterator(proto_info->prototype_users());
if (!maybe_array->IsWeakFixedArray()) return; // For now, only maps register themselves as users.
Map* user;
WeakFixedArray* users = WeakFixedArray::cast(maybe_array); while ((user = iterator.Next<Map>())) {
for (int i = 0; i < users->Length(); ++i) {
Object* maybe_user = users->Get(i);
if (maybe_user->IsSmi()) continue;
// For now, only maps register themselves as users.
Map* user = Map::cast(maybe_user);
// Walk the prototype chain (backwards, towards leaf objects) if necessary. // Walk the prototype chain (backwards, towards leaf objects) if necessary.
InvalidatePrototypeChainsInternal(user); InvalidatePrototypeChainsInternal(user);
} }
...@@ -10179,22 +10184,48 @@ Handle<JSObject> Script::GetWrapper(Handle<Script> script) { ...@@ -10179,22 +10184,48 @@ Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo( MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
FunctionLiteral* fun) { FunctionLiteral* fun) {
if (shared_function_infos()->IsWeakFixedArray()) { WeakFixedArray::Iterator iterator(shared_function_infos());
WeakFixedArray* array = WeakFixedArray::cast(shared_function_infos()); SharedFunctionInfo* shared;
for (int i = 0; i < array->Length(); i++) { while ((shared = iterator.Next<SharedFunctionInfo>())) {
Object* obj = array->Get(i); if (fun->function_token_position() == shared->function_token_position() &&
if (!obj->IsSharedFunctionInfo()) continue; fun->start_position() == shared->start_position()) {
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); return Handle<SharedFunctionInfo>(shared);
if (fun->function_token_position() == shared->function_token_position() &&
fun->start_position() == shared->start_position()) {
return Handle<SharedFunctionInfo>(shared);
}
} }
} }
return MaybeHandle<SharedFunctionInfo>(); return MaybeHandle<SharedFunctionInfo>();
} }
Script::Iterator::Iterator(Isolate* isolate)
: iterator_(isolate->heap()->script_list()) {}
Script* Script::Iterator::Next() { return iterator_.Next<Script>(); }
SharedFunctionInfo::Iterator::Iterator(Isolate* isolate)
: script_iterator_(isolate), sfi_iterator_(NULL) {
NextScript();
}
bool SharedFunctionInfo::Iterator::NextScript() {
Script* script = script_iterator_.Next();
if (script == NULL) return false;
sfi_iterator_.Reset(script->shared_function_infos());
return true;
}
SharedFunctionInfo* SharedFunctionInfo::Iterator::Next() {
do {
SharedFunctionInfo* next = sfi_iterator_.Next<SharedFunctionInfo>();
if (next != NULL) return next;
} while (NextScript());
return NULL;
}
void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared, void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
Handle<Object> script_object) { Handle<Object> script_object) {
if (shared->script() == *script_object) return; if (shared->script() == *script_object) return;
...@@ -10212,10 +10243,11 @@ void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared, ...@@ -10212,10 +10243,11 @@ void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
Handle<Script> script = Handle<Script>::cast(script_object); Handle<Script> script = Handle<Script>::cast(script_object);
Handle<Object> list(script->shared_function_infos(), shared->GetIsolate()); Handle<Object> list(script->shared_function_infos(), shared->GetIsolate());
#ifdef DEBUG #ifdef DEBUG
if (list->IsWeakFixedArray()) { {
Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(list); WeakFixedArray::Iterator iterator(*list);
for (int i = 0; i < array->Length(); ++i) { SharedFunctionInfo* next;
DCHECK(array->Get(i) != *shared); while ((next = iterator.Next<SharedFunctionInfo>())) {
DCHECK_NE(next, *shared);
} }
} }
#endif // DEBUG #endif // DEBUG
......
...@@ -2515,6 +2515,24 @@ class WeakFixedArray : public FixedArray { ...@@ -2515,6 +2515,24 @@ class WeakFixedArray : public FixedArray {
inline bool IsEmptySlot(int index) const; inline bool IsEmptySlot(int index) const;
static Object* Empty() { return Smi::FromInt(0); } static Object* Empty() { return Smi::FromInt(0); }
class Iterator {
public:
explicit Iterator(Object* maybe_array) : list_(NULL) { Reset(maybe_array); }
void Reset(Object* maybe_array);
template <class T>
inline T* Next();
private:
int index_;
WeakFixedArray* list_;
#ifdef DEBUG
int last_used_index_;
DisallowHeapAllocation no_gc_;
#endif // DEBUG
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
DECLARE_CAST(WeakFixedArray) DECLARE_CAST(WeakFixedArray)
private: private:
...@@ -5930,6 +5948,17 @@ class Script: public Struct { ...@@ -5930,6 +5948,17 @@ class Script: public Struct {
// that matches the function literal. Return empty handle if not found. // that matches the function literal. Return empty handle if not found.
MaybeHandle<SharedFunctionInfo> FindSharedFunctionInfo(FunctionLiteral* fun); MaybeHandle<SharedFunctionInfo> FindSharedFunctionInfo(FunctionLiteral* fun);
// Iterate over all script objects on the heap.
class Iterator {
public:
explicit Iterator(Isolate* isolate);
Script* Next();
private:
WeakFixedArray::Iterator iterator_;
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
// Dispatched behavior. // Dispatched behavior.
DECLARE_PRINTER(Script) DECLARE_PRINTER(Script)
DECLARE_VERIFIER(Script) DECLARE_VERIFIER(Script)
...@@ -6393,6 +6422,23 @@ class SharedFunctionInfo: public HeapObject { ...@@ -6393,6 +6422,23 @@ class SharedFunctionInfo: public HeapObject {
void ResetForNewContext(int new_ic_age); void ResetForNewContext(int new_ic_age);
// Iterate over all shared function infos that are created from a script.
// That excludes shared function infos created for API functions and C++
// builtins.
class Iterator {
public:
explicit Iterator(Isolate* isolate);
SharedFunctionInfo* Next();
private:
bool NextScript();
Script::Iterator script_iterator_;
WeakFixedArray::Iterator sfi_iterator_;
DisallowHeapAllocation no_gc_;
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
DECLARE_CAST(SharedFunctionInfo) DECLARE_CAST(SharedFunctionInfo)
// Constants. // Constants.
......
...@@ -1602,13 +1602,10 @@ RUNTIME_FUNCTION(Runtime_GetScript) { ...@@ -1602,13 +1602,10 @@ RUNTIME_FUNCTION(Runtime_GetScript) {
CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0); CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
Handle<Script> found; Handle<Script> found;
Heap* heap = isolate->heap();
{ {
HeapIterator iterator(heap); Script::Iterator iterator(isolate);
HeapObject* obj = NULL; Script* script = NULL;
while ((obj = iterator.next()) != NULL) { while ((script = iterator.Next()) != NULL) {
if (!obj->IsScript()) continue;
Script* script = Script::cast(obj);
if (!script->name()->IsString()) continue; if (!script->name()->IsString()) continue;
String* name = String::cast(script->name()); String* name = String::cast(script->name());
if (name->Equals(*script_name)) { if (name->Equals(*script_name)) {
...@@ -1618,7 +1615,7 @@ RUNTIME_FUNCTION(Runtime_GetScript) { ...@@ -1618,7 +1615,7 @@ RUNTIME_FUNCTION(Runtime_GetScript) {
} }
} }
if (found.is_null()) return heap->undefined_value(); if (found.is_null()) return isolate->heap()->undefined_value();
return *Script::GetWrapper(found); return *Script::GetWrapper(found);
} }
......
...@@ -6440,5 +6440,67 @@ TEST(ContextMeasure) { ...@@ -6440,5 +6440,67 @@ TEST(ContextMeasure) {
CHECK_LE(measure.Size(), size_upper_limit); CHECK_LE(measure.Size(), size_upper_limit);
} }
TEST(ScriptIterator) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Heap* heap = CcTest::heap();
LocalContext context;
heap->CollectAllGarbage();
int script_count = 0;
{
HeapIterator it(heap);
for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
if (obj->IsScript()) script_count++;
}
}
{
Script::Iterator iterator(isolate);
while (iterator.Next()) script_count--;
}
CHECK_EQ(0, script_count);
}
TEST(SharedFunctionInfoIterator) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Heap* heap = CcTest::heap();
LocalContext context;
heap->CollectAllGarbage();
heap->CollectAllGarbage();
int sfi_count = 0;
{
HeapIterator it(heap);
for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
if (!obj->IsSharedFunctionInfo()) continue;
// Shared function infos without a script (API functions or C++ builtins)
// are not returned by the iterator because they are not created from a
// script. They are not interesting for type feedback vector anyways.
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
if (shared->script()->IsUndefined()) {
CHECK_EQ(0, shared->feedback_vector()->ICSlots());
} else {
sfi_count++;
}
}
}
{
SharedFunctionInfo::Iterator iterator(isolate);
while (iterator.Next()) sfi_count--;
}
CHECK_EQ(0, sfi_count);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment