Revision: 6386
Author: [email protected]
Date: Wed Jan 19 02:48:06 2011
Log: Introducing MemoryMappedExternalResource for creating an external
resource from a memory mapped file for creating strings.
Patch by Mark Lam from Hewlett-Packard Development Company, LP
Review URL: http://codereview.chromium.org/6240002/
http://code.google.com/p/v8/source/detail?r=6386
Modified:
/branches/bleeding_edge/src/platform-freebsd.cc
/branches/bleeding_edge/src/platform-linux.cc
/branches/bleeding_edge/src/platform-macos.cc
/branches/bleeding_edge/src/platform-nullos.cc
/branches/bleeding_edge/src/platform-openbsd.cc
/branches/bleeding_edge/src/platform-posix.cc
/branches/bleeding_edge/src/platform-solaris.cc
/branches/bleeding_edge/src/platform-win32.cc
/branches/bleeding_edge/src/platform.h
/branches/bleeding_edge/src/utils.cc
/branches/bleeding_edge/src/v8utils.h
=======================================
--- /branches/bleeding_edge/src/platform-freebsd.cc Tue Jan 4 01:09:50 2011
+++ /branches/bleeding_edge/src/platform-freebsd.cc Wed Jan 19 02:48:06 2011
@@ -215,6 +215,7 @@
: file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; }
+ virtual int size() { return size_; }
private:
FILE* file_;
void* memory_;
@@ -222,6 +223,19 @@
};
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ FILE* file = fopen(name, "w+");
+ if (file == NULL) return NULL;
+
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+
+ void* memory =
+ mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+ return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int
size,
void* initial) {
FILE* file = fopen(name, "w+");
=======================================
--- /branches/bleeding_edge/src/platform-linux.cc Tue Jan 4 01:09:50 2011
+++ /branches/bleeding_edge/src/platform-linux.cc Wed Jan 19 02:48:06 2011
@@ -318,6 +318,7 @@
: file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; }
+ virtual int size() { return size_; }
private:
FILE* file_;
void* memory_;
@@ -325,6 +326,19 @@
};
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ FILE* file = fopen(name, "w+");
+ if (file == NULL) return NULL;
+
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+
+ void* memory =
+ mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+ return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int
size,
void* initial) {
FILE* file = fopen(name, "w+");
=======================================
--- /branches/bleeding_edge/src/platform-macos.cc Tue Jan 4 05:23:33 2011
+++ /branches/bleeding_edge/src/platform-macos.cc Wed Jan 19 02:48:06 2011
@@ -196,6 +196,7 @@
: file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; }
+ virtual int size() { return size_; }
private:
FILE* file_;
void* memory_;
@@ -203,6 +204,19 @@
};
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ FILE* file = fopen(name, "w+");
+ if (file == NULL) return NULL;
+
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+
+ void* memory =
+ mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+ return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int
size,
void* initial) {
FILE* file = fopen(name, "w+");
=======================================
--- /branches/bleeding_edge/src/platform-nullos.cc Tue Jan 4 01:09:50 2011
+++ /branches/bleeding_edge/src/platform-nullos.cc Wed Jan 19 02:48:06 2011
@@ -240,6 +240,12 @@
void OS::DebugBreak() {
UNIMPLEMENTED();
}
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ UNIMPLEMENTED();
+ return NULL;
+}
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int
size,
=======================================
--- /branches/bleeding_edge/src/platform-openbsd.cc Tue Jan 4 01:09:50 2011
+++ /branches/bleeding_edge/src/platform-openbsd.cc Wed Jan 19 02:48:06 2011
@@ -213,6 +213,7 @@
: file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; }
+ virtual int size() { return size_; }
private:
FILE* file_;
void* memory_;
@@ -220,6 +221,19 @@
};
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ FILE* file = fopen(name, "w+");
+ if (file == NULL) return NULL;
+
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+
+ void* memory =
+ mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+ return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int
size,
void* initial) {
FILE* file = fopen(name, "w+");
=======================================
--- /branches/bleeding_edge/src/platform-posix.cc Mon Dec 20 02:38:19 2010
+++ /branches/bleeding_edge/src/platform-posix.cc Wed Jan 19 02:48:06 2011
@@ -120,6 +120,11 @@
FILE* OS::FOpen(const char* path, const char* mode) {
return fopen(path, mode);
}
+
+
+bool OS::Remove(const char* path) {
+ return (remove(path) == 0);
+}
const char* OS::LogFileOpenMode = "w";
=======================================
--- /branches/bleeding_edge/src/platform-solaris.cc Tue Jan 11 03:44:16 2011
+++ /branches/bleeding_edge/src/platform-solaris.cc Wed Jan 19 02:48:06 2011
@@ -226,6 +226,7 @@
: file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; }
+ virtual int size() { return size_; }
private:
FILE* file_;
void* memory_;
@@ -233,6 +234,19 @@
};
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ FILE* file = fopen(name, "w+");
+ if (file == NULL) return NULL;
+
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+
+ void* memory =
+ mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+ return new PosixMemoryMappedFile(file, memory, size);
+}
+
+
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int
size,
void* initial) {
FILE* file = fopen(name, "w+");
=======================================
--- /branches/bleeding_edge/src/platform-win32.cc Wed Jan 19 00:34:24 2011
+++ /branches/bleeding_edge/src/platform-win32.cc Wed Jan 19 02:48:06 2011
@@ -668,6 +668,11 @@
return NULL;
}
}
+
+
+bool OS::Remove(const char* path) {
+ return (DeleteFile(path) != 0);
+}
// Open log file in binary mode to avoid /n -> /r/n conversion.
@@ -911,17 +916,44 @@
class Win32MemoryMappedFile : public OS::MemoryMappedFile {
public:
- Win32MemoryMappedFile(HANDLE file, HANDLE file_mapping, void* memory)
- : file_(file), file_mapping_(file_mapping), memory_(memory) { }
+ Win32MemoryMappedFile(HANDLE file,
+ HANDLE file_mapping,
+ void* memory,
+ int size)
+ : file_(file),
+ file_mapping_(file_mapping),
+ memory_(memory),
+ size_(size) { }
virtual ~Win32MemoryMappedFile();
virtual void* memory() { return memory_; }
+ virtual void* size() { return size_; }
private:
HANDLE file_;
HANDLE file_mapping_;
void* memory_;
+ int size_;
};
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ // Open a physical file
+ HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if (file == NULL) return NULL;
+
+ int size = static_cast<int>(GetFileSize(file, NULL));
+
+ // Create a file mapping for the physical file
+ HANDLE file_mapping = CreateFileMapping(file, NULL,
+ PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
+ if (file_mapping == NULL) return NULL;
+
+ // Map a view of the file into memory
+ void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0,
size);
+ return new Win32MemoryMappedFile(file, file_mapping, memory, size);
+}
+
+
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int
size,
void* initial) {
// Open a physical file
@@ -935,7 +967,7 @@
// Map a view of the file into memory
void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0,
size);
if (memory) memmove(memory, initial, size);
- return new Win32MemoryMappedFile(file, file_mapping, memory);
+ return new Win32MemoryMappedFile(file, file_mapping, memory, size);
}
=======================================
--- /branches/bleeding_edge/src/platform.h Tue Jan 4 05:23:33 2011
+++ /branches/bleeding_edge/src/platform.h Wed Jan 19 02:48:06 2011
@@ -174,6 +174,7 @@
static int GetLastError();
static FILE* FOpen(const char* path, const char* mode);
+ static bool Remove(const char* path);
// Log file open mode is platform-dependent due to line ends issues.
static const char* LogFileOpenMode;
@@ -251,9 +252,11 @@
class MemoryMappedFile {
public:
+ static MemoryMappedFile* open(const char* name);
static MemoryMappedFile* create(const char* name, int size, void*
initial);
virtual ~MemoryMappedFile() { }
virtual void* memory() = 0;
+ virtual int size() = 0;
};
// Safe formatting print. Ensures that str is always null-terminated.
=======================================
--- /branches/bleeding_edge/src/utils.cc Mon Dec 20 02:38:19 2010
+++ /branches/bleeding_edge/src/utils.cc Wed Jan 19 02:48:06 2011
@@ -274,6 +274,98 @@
ASSERT(is_finalized());
return buffer_.start();
}
+
+
+MemoryMappedExternalResource::MemoryMappedExternalResource(const char*
filename)
+ : filename_(NULL),
+ data_(NULL),
+ length_(0),
+ remove_file_on_cleanup_(false) {
+ Init(filename);
+}
+
+
+MemoryMappedExternalResource::
+ MemoryMappedExternalResource(const char* filename,
+ bool remove_file_on_cleanup)
+ : filename_(NULL),
+ data_(NULL),
+ length_(0),
+ remove_file_on_cleanup_(remove_file_on_cleanup) {
+ Init(filename);
+}
+
+
+MemoryMappedExternalResource::~MemoryMappedExternalResource() {
+ // Release the resources if we had successfully acquired them:
+ if (file_ != NULL) {
+ delete file_;
+ if (remove_file_on_cleanup_) {
+ OS::Remove(filename_);
+ }
+ DeleteArray<char>(filename_);
+ }
+}
+
+
+void MemoryMappedExternalResource::Init(const char* filename) {
+ file_ = OS::MemoryMappedFile::open(filename);
+ if (file_ != NULL) {
+ filename_ = StrDup(filename);
+ data_ = reinterpret_cast<char*>(file_->memory());
+ length_ = file_->size();
+ }
+}
+
+
+bool MemoryMappedExternalResource::EnsureIsAscii(bool abort_if_failed)
const {
+ bool is_ascii = true;
+
+ int line_no = 1;
+ const char* start_of_line = data_;
+ const char* end = data_ + length_;
+ for (const char* p = data_; p < end; p++) {
+ char c = *p;
+ if ((c & 0x80) != 0) {
+ // Non-ascii detected:
+ is_ascii = false;
+
+ // Report the error and abort if appropriate:
+ if (abort_if_failed) {
+ int char_no = (p - start_of_line) - 1;
+
+ ASSERT(filename_ != NULL);
+ PrintF("\n\n\n"
+ "Abort: Non-Ascii character 0x%.2x in file %s line %d
char %d",
+ c, filename_, line_no, char_no);
+
+ // Allow for some context up to kNumberOfLeadingContextChars chars
+ // before the offending non-ascii char to help the user see where
+ // the offending char is.
+ const int kNumberOfLeadingContextChars = 10;
+ const char* err_context = p - kNumberOfLeadingContextChars;
+ if (err_context < data_) {
+ err_context = data_;
+ }
+ // Compute the length of the error context and print it.
+ int err_context_length = p - err_context;
+ if (err_context_length != 0) {
+ PrintF(" after \"%.*s\"", err_context_length, err_context);
+ }
+ PrintF(".\n\n\n");
+ OS::Abort();
+ }
+
+ break; // Non-ascii detected. No need to continue scanning.
+ }
+ if (c == '\n') {
+ start_of_line = p;
+ line_no++;
+ }
+ }
+
+ return is_ascii;
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/v8utils.h Tue Jan 11 03:47:30 2011
+++ /branches/bleeding_edge/src/v8utils.h Wed Jan 19 02:48:06 2011
@@ -315,6 +315,39 @@
*dest++ = static_cast<sinkchar>(*src++);
}
}
+
+
+// A resource for using mmapped files to back external strings that are
read
+// from files.
+class MemoryMappedExternalResource: public
+ v8::String::ExternalAsciiStringResource {
+ public:
+ explicit MemoryMappedExternalResource(const char* filename);
+ MemoryMappedExternalResource(const char* filename,
+ bool remove_file_on_cleanup);
+ virtual ~MemoryMappedExternalResource();
+
+ virtual const char* data() const { return data_; }
+ virtual size_t length() const { return length_; }
+
+ bool exists() const { return file_ != NULL; }
+ bool is_empty() const { return length_ == 0; }
+
+ bool EnsureIsAscii(bool abort_if_failed) const;
+ bool EnsureIsAscii() const { return EnsureIsAscii(true); }
+ bool IsAscii() const { return EnsureIsAscii(false); }
+
+ private:
+ void Init(const char* filename);
+
+ char* filename_;
+ OS::MemoryMappedFile* file_;
+
+ const char* data_;
+ size_t length_;
+ bool remove_file_on_cleanup_;
+};
+
} } // namespace v8::internal
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev