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;
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();
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);
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,
}
+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();
}
+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) {
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);
}
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;
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
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:
// 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)
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.
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)) {
}
}
- if (found.is_null()) return heap->undefined_value();
+ if (found.is_null()) return isolate->heap()->undefined_value();
return *Script::GetWrapper(found);
}
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