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,
while (true) {
// Go through all shared function infos associated with this script to
// 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;
WeakFixedArray* array =
WeakFixedArray::cast(script->shared_function_infos());
SharedFunctionInfo* shared;
{
SharedFunctionInfoFinder finder(position);
for (int i = 0; i < array->Length(); i++) {
Object* item = array->Get(i);
if (!item->IsSharedFunctionInfo()) continue;
finder.NewCandidate(SharedFunctionInfo::cast(item));
WeakFixedArray::Iterator iterator(script->shared_function_infos());
SharedFunctionInfo* candidate;
while ((candidate = iterator.Next<SharedFunctionInfo>())) {
finder.NewCandidate(candidate);
}
shared = finder.Result();
if (shared == NULL) break;
......@@ -1608,8 +1608,7 @@ void Debug::ClearMirrorCache() {
Handle<FixedArray> Debug::GetLoadedScripts() {
isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
"Debug::GetLoadedScripts");
isolate_->heap()->CollectAllGarbage();
Factory* factory = isolate_->factory();
if (!factory->script_list()->IsWeakFixedArray()) {
return factory->empty_fixed_array();
......@@ -1618,10 +1617,11 @@ Handle<FixedArray> Debug::GetLoadedScripts() {
Handle<WeakFixedArray>::cast(factory->script_list());
Handle<FixedArray> results = factory->NewFixedArray(array->Length());
int length = 0;
for (int i = 0; i < array->Length(); ++i) {
Object* item = array->Get(i);
if (item->IsScript() && Script::cast(item)->HasValidSource()) {
results->set(length++, item);
{
Script::Iterator iterator(isolate_);
Script* script;
while ((script = iterator.Next())) {
if (script->HasValidSource()) results->set(length++, script);
}
}
results->Shrink(length);
......
......@@ -715,12 +715,9 @@ 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));
WeakFixedArray::Iterator iterator(weak_stack_trace_list());
FixedArray* elements;
while ((elements = iterator.Next<FixedArray>())) {
for (int j = 1; j < elements->length(); j += 4) {
Object* maybe_code = elements->get(j + 2);
// 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) {
}
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() {
if (FixedArray::cast(this)->length() == 0) return 0;
return Smi::cast(FixedArray::cast(this)->get(kLengthIndex))->value();
......
......@@ -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,
int old_index,
int new_index) {
......@@ -9666,16 +9677,10 @@ static void InvalidatePrototypeChainsInternal(Map* map) {
cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
}
Object* maybe_array = proto_info->prototype_users();
if (!maybe_array->IsWeakFixedArray()) return;
WeakFixedArray* users = WeakFixedArray::cast(maybe_array);
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);
WeakFixedArray::Iterator iterator(proto_info->prototype_users());
// For now, only maps register themselves as users.
Map* user;
while ((user = iterator.Next<Map>())) {
// Walk the prototype chain (backwards, towards leaf objects) if necessary.
InvalidatePrototypeChainsInternal(user);
}
......@@ -10179,22 +10184,48 @@ Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
FunctionLiteral* fun) {
if (shared_function_infos()->IsWeakFixedArray()) {
WeakFixedArray* array = WeakFixedArray::cast(shared_function_infos());
for (int i = 0; i < array->Length(); i++) {
Object* obj = array->Get(i);
if (!obj->IsSharedFunctionInfo()) continue;
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
if (fun->function_token_position() == shared->function_token_position() &&
fun->start_position() == shared->start_position()) {
return Handle<SharedFunctionInfo>(shared);
}
WeakFixedArray::Iterator iterator(shared_function_infos());
SharedFunctionInfo* shared;
while ((shared = iterator.Next<SharedFunctionInfo>())) {
if (fun->function_token_position() == shared->function_token_position() &&
fun->start_position() == shared->start_position()) {
return Handle<SharedFunctionInfo>(shared);
}
}
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,
Handle<Object> script_object) {
if (shared->script() == *script_object) return;
......@@ -10212,10 +10243,11 @@ void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
Handle<Script> script = Handle<Script>::cast(script_object);
Handle<Object> list(script->shared_function_infos(), shared->GetIsolate());
#ifdef DEBUG
if (list->IsWeakFixedArray()) {
Handle<WeakFixedArray> array = Handle<WeakFixedArray>::cast(list);
for (int i = 0; i < array->Length(); ++i) {
DCHECK(array->Get(i) != *shared);
{
WeakFixedArray::Iterator iterator(*list);
SharedFunctionInfo* next;
while ((next = iterator.Next<SharedFunctionInfo>())) {
DCHECK_NE(next, *shared);
}
}
#endif // DEBUG
......
......@@ -2515,6 +2515,24 @@ class WeakFixedArray : public FixedArray {
inline bool IsEmptySlot(int index) const;
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)
private:
......@@ -5930,6 +5948,17 @@ class Script: public Struct {
// that matches the function literal. Return empty handle if not found.
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.
DECLARE_PRINTER(Script)
DECLARE_VERIFIER(Script)
......@@ -6393,6 +6422,23 @@ class SharedFunctionInfo: public HeapObject {
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)
// Constants.
......
......@@ -1602,13 +1602,10 @@ RUNTIME_FUNCTION(Runtime_GetScript) {
CONVERT_ARG_HANDLE_CHECKED(String, script_name, 0);
Handle<Script> found;
Heap* heap = isolate->heap();
{
HeapIterator iterator(heap);
HeapObject* obj = NULL;
while ((obj = iterator.next()) != NULL) {
if (!obj->IsScript()) continue;
Script* script = Script::cast(obj);
Script::Iterator iterator(isolate);
Script* script = NULL;
while ((script = iterator.Next()) != NULL) {
if (!script->name()->IsString()) continue;
String* name = String::cast(script->name());
if (name->Equals(*script_name)) {
......@@ -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);
}
......
......@@ -6440,5 +6440,67 @@ TEST(ContextMeasure) {
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 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