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/

Relanded with Windows compilation issues fixed.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6401 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ac0b1ded
...@@ -215,6 +215,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -215,6 +215,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
: file_(file), memory_(memory), size_(size) { } : file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile(); virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; } virtual void* memory() { return memory_; }
virtual int size() { return size_; }
private: private:
FILE* file_; FILE* file_;
void* memory_; void* memory_;
...@@ -222,6 +223,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -222,6 +223,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
}; };
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, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
FILE* file = fopen(name, "w+"); FILE* file = fopen(name, "w+");
......
...@@ -318,6 +318,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -318,6 +318,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
: file_(file), memory_(memory), size_(size) { } : file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile(); virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; } virtual void* memory() { return memory_; }
virtual int size() { return size_; }
private: private:
FILE* file_; FILE* file_;
void* memory_; void* memory_;
...@@ -325,6 +326,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -325,6 +326,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
}; };
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, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
FILE* file = fopen(name, "w+"); FILE* file = fopen(name, "w+");
......
...@@ -196,6 +196,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -196,6 +196,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
: file_(file), memory_(memory), size_(size) { } : file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile(); virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; } virtual void* memory() { return memory_; }
virtual int size() { return size_; }
private: private:
FILE* file_; FILE* file_;
void* memory_; void* memory_;
...@@ -203,6 +204,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -203,6 +204,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
}; };
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, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
FILE* file = fopen(name, "w+"); FILE* file = fopen(name, "w+");
......
...@@ -242,6 +242,12 @@ void OS::DebugBreak() { ...@@ -242,6 +242,12 @@ void OS::DebugBreak() {
} }
OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
UNIMPLEMENTED();
return NULL;
}
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
UNIMPLEMENTED(); UNIMPLEMENTED();
......
...@@ -213,6 +213,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -213,6 +213,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
: file_(file), memory_(memory), size_(size) { } : file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile(); virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; } virtual void* memory() { return memory_; }
virtual int size() { return size_; }
private: private:
FILE* file_; FILE* file_;
void* memory_; void* memory_;
...@@ -220,6 +221,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -220,6 +221,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
}; };
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, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
FILE* file = fopen(name, "w+"); FILE* file = fopen(name, "w+");
......
...@@ -122,6 +122,11 @@ FILE* OS::FOpen(const char* path, const char* mode) { ...@@ -122,6 +122,11 @@ FILE* OS::FOpen(const char* path, const char* mode) {
} }
bool OS::Remove(const char* path) {
return (remove(path) == 0);
}
const char* OS::LogFileOpenMode = "w"; const char* OS::LogFileOpenMode = "w";
......
...@@ -226,6 +226,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -226,6 +226,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
: file_(file), memory_(memory), size_(size) { } : file_(file), memory_(memory), size_(size) { }
virtual ~PosixMemoryMappedFile(); virtual ~PosixMemoryMappedFile();
virtual void* memory() { return memory_; } virtual void* memory() { return memory_; }
virtual int size() { return size_; }
private: private:
FILE* file_; FILE* file_;
void* memory_; void* memory_;
...@@ -233,6 +234,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { ...@@ -233,6 +234,19 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile {
}; };
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, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
FILE* file = fopen(name, "w+"); FILE* file = fopen(name, "w+");
......
...@@ -670,6 +670,11 @@ FILE* OS::FOpen(const char* path, const char* mode) { ...@@ -670,6 +670,11 @@ FILE* OS::FOpen(const char* path, const char* mode) {
} }
bool OS::Remove(const char* path) {
return (DeleteFile(path) != 0);
}
// Open log file in binary mode to avoid /n -> /r/n conversion. // Open log file in binary mode to avoid /n -> /r/n conversion.
const char* OS::LogFileOpenMode = "wb"; const char* OS::LogFileOpenMode = "wb";
...@@ -911,17 +916,44 @@ void OS::DebugBreak() { ...@@ -911,17 +916,44 @@ void OS::DebugBreak() {
class Win32MemoryMappedFile : public OS::MemoryMappedFile { class Win32MemoryMappedFile : public OS::MemoryMappedFile {
public: public:
Win32MemoryMappedFile(HANDLE file, HANDLE file_mapping, void* memory) Win32MemoryMappedFile(HANDLE file,
: file_(file), file_mapping_(file_mapping), memory_(memory) { } HANDLE file_mapping,
void* memory,
int size)
: file_(file),
file_mapping_(file_mapping),
memory_(memory),
size_(size) { }
virtual ~Win32MemoryMappedFile(); virtual ~Win32MemoryMappedFile();
virtual void* memory() { return memory_; } virtual void* memory() { return memory_; }
virtual int size() { return size_; }
private: private:
HANDLE file_; HANDLE file_;
HANDLE file_mapping_; HANDLE file_mapping_;
void* memory_; 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, OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
// Open a physical file // Open a physical file
...@@ -935,7 +967,7 @@ OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, ...@@ -935,7 +967,7 @@ OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
// Map a view of the file into memory // Map a view of the file into memory
void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
if (memory) memmove(memory, initial, size); if (memory) memmove(memory, initial, size);
return new Win32MemoryMappedFile(file, file_mapping, memory); return new Win32MemoryMappedFile(file, file_mapping, memory, size);
} }
......
...@@ -174,6 +174,7 @@ class OS { ...@@ -174,6 +174,7 @@ class OS {
static int GetLastError(); static int GetLastError();
static FILE* FOpen(const char* path, const char* mode); 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. // Log file open mode is platform-dependent due to line ends issues.
static const char* LogFileOpenMode; static const char* LogFileOpenMode;
...@@ -251,9 +252,11 @@ class OS { ...@@ -251,9 +252,11 @@ class OS {
class MemoryMappedFile { class MemoryMappedFile {
public: public:
static MemoryMappedFile* open(const char* name);
static MemoryMappedFile* create(const char* name, int size, void* initial); static MemoryMappedFile* create(const char* name, int size, void* initial);
virtual ~MemoryMappedFile() { } virtual ~MemoryMappedFile() { }
virtual void* memory() = 0; virtual void* memory() = 0;
virtual int size() = 0;
}; };
// Safe formatting print. Ensures that str is always null-terminated. // Safe formatting print. Ensures that str is always null-terminated.
......
...@@ -276,4 +276,96 @@ char* StringBuilder::Finalize() { ...@@ -276,4 +276,96 @@ char* StringBuilder::Finalize() {
} }
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) {
intptr_t 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.
intptr_t 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 } } // namespace v8::internal
...@@ -316,6 +316,39 @@ static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) { ...@@ -316,6 +316,39 @@ static inline void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
} }
} }
// 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 } } // namespace v8::internal
#endif // V8_V8UTILS_H_ #endif // V8_V8UTILS_H_
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