+ static size_t iov_max = GOLD_IOV_MAX;
+ size_t count = rm.size();
+ size_t i = 0;
+ while (i < count)
+ {
+ // Find up to MAX_READV_ENTRIES consecutive entries which are
+ // less than one page apart.
+ const Read_multiple_entry& i_entry(rm[i]);
+ off_t i_off = i_entry.file_offset;
+ off_t end_off = i_off + i_entry.size;
+ size_t j;
+ for (j = i + 1; j < count; ++j)
+ {
+ if (j - i >= File_read::max_readv_entries || j - i >= iov_max / 2)
+ break;
+ const Read_multiple_entry& j_entry(rm[j]);
+ off_t j_off = j_entry.file_offset;
+ gold_assert(j_off >= end_off);
+ off_t j_end_off = j_off + j_entry.size;
+ if (j_end_off - end_off >= File_read::page_size)
+ break;
+ end_off = j_end_off;
+ }
+
+ if (j == i + 1)
+ this->read(base + i_off, i_entry.size, i_entry.buffer);
+ else
+ {
+ File_read::View* view = this->find_view(base + i_off,
+ end_off - i_off,
+ -1U, NULL);
+ if (view == NULL)
+ this->do_readv(base, rm, i, j - i);
+ else
+ {
+ const unsigned char* v = (view->data()
+ + (base + i_off - view->start()
+ + view->byteshift()));
+ for (size_t k = i; k < j; ++k)
+ {
+ const Read_multiple_entry& k_entry(rm[k]);
+ gold_assert((convert_to_section_size_type(k_entry.file_offset
+ - i_off)
+ + k_entry.size)
+ <= convert_to_section_size_type(end_off
+ - i_off));
+ memcpy(k_entry.buffer,
+ v + (k_entry.file_offset - i_off),
+ k_entry.size);
+ }
+ }
+ }
+
+ i = j;
+ }
+}
+
+// Mark all views as no longer cached.
+
+void
+File_read::clear_view_cache_marks()
+{
+ // Just ignore this if there are multiple objects associated with
+ // the file. Otherwise we will wind up uncaching and freeing some
+ // views for other objects.
+ if (this->object_count_ > 1)
+ return;
+
+ for (Views::iterator p = this->views_.begin();
+ p != this->views_.end();
+ ++p)
+ p->second->clear_cache();
+ for (Saved_views::iterator p = this->saved_views_.begin();
+ p != this->saved_views_.end();
+ ++p)
+ (*p)->clear_cache();
+}
+
+// Remove all the file views. For a file which has multiple
+// associated objects (i.e., an archive), we keep accessed views
+// around until next time, in the hopes that they will be useful for
+// the next object.
+
+void
+File_read::clear_views(Clear_views_mode mode)
+{
+ bool keep_files_mapped = (parameters->options_valid()
+ && parameters->options().keep_files_mapped());