diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc index ad1e499ac5..7174c7f9cb 100644 --- a/src/platform-freebsd.cc +++ b/src/platform-freebsd.cc @@ -215,6 +215,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { : 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 @@ 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, void* initial) { FILE* file = fopen(name, "w+"); diff --git a/src/platform-linux.cc b/src/platform-linux.cc index 755e8cdaf6..761ff7e207 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -318,6 +318,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { : 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 @@ 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, void* initial) { FILE* file = fopen(name, "w+"); diff --git a/src/platform-macos.cc b/src/platform-macos.cc index ce53305173..ea35c1b130 100644 --- a/src/platform-macos.cc +++ b/src/platform-macos.cc @@ -196,6 +196,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { : 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 @@ 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, void* initial) { FILE* file = fopen(name, "w+"); diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc index f1b7695981..49d3dd988d 100644 --- a/src/platform-nullos.cc +++ b/src/platform-nullos.cc @@ -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, void* initial) { UNIMPLEMENTED(); diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc index 5de6081907..0002dd7620 100644 --- a/src/platform-openbsd.cc +++ b/src/platform-openbsd.cc @@ -213,6 +213,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { : 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 @@ 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, void* initial) { FILE* file = fopen(name, "w+"); diff --git a/src/platform-posix.cc b/src/platform-posix.cc index ab5c0a3768..256dc75f6b 100644 --- a/src/platform-posix.cc +++ b/src/platform-posix.cc @@ -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"; diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc index dc4493aab9..556e26be21 100644 --- a/src/platform-solaris.cc +++ b/src/platform-solaris.cc @@ -226,6 +226,7 @@ class PosixMemoryMappedFile : public OS::MemoryMappedFile { : 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 @@ 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, void* initial) { FILE* file = fopen(name, "w+"); diff --git a/src/platform-win32.cc b/src/platform-win32.cc index bf1737a54b..9ebf2c7e98 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -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. const char* OS::LogFileOpenMode = "wb"; @@ -911,17 +916,44 @@ void OS::DebugBreak() { 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(GetFileSize(file, NULL)); + + // Create a file mapping for the physical file + HANDLE file_mapping = CreateFileMapping(file, NULL, + PAGE_READWRITE, 0, static_cast(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 @@ OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, // 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); } diff --git a/src/platform.h b/src/platform.h index 7b17067477..0d7d2e9cb8 100644 --- a/src/platform.h +++ b/src/platform.h @@ -174,6 +174,7 @@ class OS { 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 OS { 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. diff --git a/src/utils.cc b/src/utils.cc index d0ec4ef528..5d70866eb7 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -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(filename_); + } +} + + +void MemoryMappedExternalResource::Init(const char* filename) { + file_ = OS::MemoryMappedFile::open(filename); + if (file_ != NULL) { + filename_ = StrDup(filename); + data_ = reinterpret_cast(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 diff --git a/src/v8utils.h b/src/v8utils.h index e9623be62e..0aa53cac59 100644 --- a/src/v8utils.h +++ b/src/v8utils.h @@ -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 #endif // V8_V8UTILS_H_