diff options
author | Ben Murdoch <benm@google.com> | 2011-11-30 15:57:28 +0000 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-12-02 17:27:08 +0000 |
commit | 257744e915dfc84d6d07a6b2accf8402d9ffc708 (patch) | |
tree | 19d8782d5686697f36b1771e7fcd46f290b82c3c /preparser | |
parent | 92022043ea907575278de828a5c9cf6939b51e5e (diff) | |
download | android_external_v8-257744e915dfc84d6d07a6b2accf8402d9ffc708.tar.gz android_external_v8-257744e915dfc84d6d07a6b2accf8402d9ffc708.tar.bz2 android_external_v8-257744e915dfc84d6d07a6b2accf8402d9ffc708.zip |
Upgrade to V8 3.3
Merge V8 at 3.3.10.39
Simple merge required updates to makefiles only.
Bug: 5688872
Change-Id: I14703f418235f5ce6013b9b3e2e502407a9f6dfd
Diffstat (limited to 'preparser')
-rw-r--r-- | preparser/preparser-process.cc | 300 |
1 files changed, 255 insertions, 45 deletions
diff --git a/preparser/preparser-process.cc b/preparser/preparser-process.cc index fb6e3866..a19c66b7 100644 --- a/preparser/preparser-process.cc +++ b/preparser/preparser-process.cc @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -28,23 +28,38 @@ #include <stdlib.h> #include <stdarg.h> #include <stdio.h> +#include <string.h> #include "../include/v8stdint.h" #include "../include/v8-preparser.h" +#include "../src/preparse-data-format.h" + +namespace i = v8::internal; + // This file is only used for testing the stand-alone preparser // library. -// The first (and only) argument must be the path of a JavaScript file. -// This file is preparsed and the resulting preparser data is written -// to stdout. Diagnostic output is output on stderr. -// The file must contain only ASCII characters (UTF-8 isn't supported). +// The first argument must be the path of a JavaScript source file, or +// the flags "-e" and the next argument is then the source of a JavaScript +// program. +// Optionally this can be followed by the word "throws" (case sensitive), +// which signals that the parsing is expected to throw - the default is +// to expect the parsing to not throw. +// The command line can further be followed by a message text (the +// *type* of the exception to throw), and even more optionally, the +// start and end position reported with the exception. +// +// This source file is preparsed and tested against the expectations, and if +// successful, the resulting preparser data is written to stdout. +// Diagnostic output is output on stderr. +// The source file must contain only ASCII characters (UTF-8 isn't supported). // The file is read into memory, so it should have a reasonable size. // Adapts an ASCII string to the UnicodeInputStream interface. class AsciiInputStream : public v8::UnicodeInputStream { public: - AsciiInputStream(uint8_t* buffer, size_t length) + AsciiInputStream(const uint8_t* buffer, size_t length) : buffer_(buffer), end_offset_(static_cast<int>(length)), offset_(0) { } @@ -97,73 +112,268 @@ bool WriteBuffer(FILE* dest, const void* buffer, size_t length) { } +class PreparseDataInterpreter { + public: + PreparseDataInterpreter(const uint8_t* data, int length) + : data_(data), length_(length), message_(NULL) { } + + ~PreparseDataInterpreter() { + if (message_ != NULL) delete[] message_; + } + + bool valid() { + int header_length = + i::PreparseDataConstants::kHeaderSize * sizeof(int); // NOLINT + return length_ >= header_length; + } + + bool throws() { + return valid() && + word(i::PreparseDataConstants::kHasErrorOffset) != 0; + } + + const char* message() { + if (message_ != NULL) return message_; + if (!throws()) return NULL; + int text_pos = i::PreparseDataConstants::kHeaderSize + + i::PreparseDataConstants::kMessageTextPos; + int length = word(text_pos); + char* buffer = new char[length + 1]; + for (int i = 1; i <= length; i++) { + int character = word(text_pos + i); + buffer[i - 1] = character; + } + buffer[length] = '\0'; + message_ = buffer; + return buffer; + } + + int beg_pos() { + if (!throws()) return -1; + return word(i::PreparseDataConstants::kHeaderSize + + i::PreparseDataConstants::kMessageStartPos); + } + + int end_pos() { + if (!throws()) return -1; + return word(i::PreparseDataConstants::kHeaderSize + + i::PreparseDataConstants::kMessageEndPos); + } + + private: + int word(int offset) { + const int* word_data = reinterpret_cast<const int*>(data_); + if (word_data + offset < reinterpret_cast<const int*>(data_ + length_)) { + return word_data[offset]; + } + return -1; + } + + const uint8_t* const data_; + const int length_; + const char* message_; +}; + + template <typename T> class ScopedPointer { public: + explicit ScopedPointer() : pointer_(NULL) {} explicit ScopedPointer(T* pointer) : pointer_(pointer) {} - ~ScopedPointer() { delete[] pointer_; } + ~ScopedPointer() { if (pointer_ != NULL) delete[] pointer_; } T& operator[](int index) { return pointer_[index]; } T* operator*() { return pointer_ ;} + T* operator=(T* new_value) { + if (pointer_ != NULL) delete[] pointer_; + pointer_ = new_value; + return new_value; + } private: T* pointer_; }; -int main(int argc, char* argv[]) { - // Check for filename argument. - if (argc < 2) { - fprintf(stderr, "ERROR: No filename on command line.\n"); + +void fail(v8::PreParserData* data, const char* message, ...) { + va_list args; + va_start(args, message); + vfprintf(stderr, message, args); + va_end(args); + fflush(stderr); + // Print preparser data to stdout. + uint32_t size = data->size(); + fprintf(stderr, "LOG: data size: %u\n", size); + if (!WriteBuffer(stdout, data->data(), size)) { + perror("ERROR: Writing data"); fflush(stderr); - return EXIT_FAILURE; } - const char* filename = argv[1]; + exit(EXIT_FAILURE); +}; - // Open JS file. - FILE* input = fopen(filename, "rb"); - if (input == NULL) { - perror("ERROR: Error opening file"); - fflush(stderr); - return EXIT_FAILURE; + +bool IsFlag(const char* arg) { + // Anything starting with '-' is considered a flag. + // It's summarily ignored for now. + return arg[0] == '-'; +} + + +struct ExceptionExpectation { + ExceptionExpectation() + : throws(false), type(NULL), beg_pos(-1), end_pos(-1) { } + bool throws; + const char* type; + int beg_pos; + int end_pos; +}; + + +void CheckException(v8::PreParserData* data, + ExceptionExpectation* expects) { + PreparseDataInterpreter reader(data->data(), data->size()); + if (expects->throws) { + if (!reader.throws()) { + if (expects->type == NULL) { + fail(data, "Didn't throw as expected\n"); + } else { + fail(data, "Didn't throw \"%s\" as expected\n", expects->type); + } + } + if (expects->type != NULL) { + const char* actual_message = reader.message(); + if (strcmp(expects->type, actual_message)) { + fail(data, "Wrong error message. Expected <%s>, found <%s> at %d..%d\n", + expects->type, actual_message, reader.beg_pos(), reader.end_pos()); + } + } + if (expects->beg_pos >= 0) { + if (expects->beg_pos != reader.beg_pos()) { + fail(data, "Wrong error start position: Expected %i, found %i\n", + expects->beg_pos, reader.beg_pos()); + } + } + if (expects->end_pos >= 0) { + if (expects->end_pos != reader.end_pos()) { + fail(data, "Wrong error end position: Expected %i, found %i\n", + expects->end_pos, reader.end_pos()); + } + } + } else if (reader.throws()) { + const char* message = reader.message(); + fail(data, "Throws unexpectedly with message: %s at location %d-%d\n", + message, reader.beg_pos(), reader.end_pos()); } +} - // Find length of JS file. - if (fseek(input, 0, SEEK_END) != 0) { - perror("ERROR: Error during seek"); - fflush(stderr); - return EXIT_FAILURE; + +ExceptionExpectation ParseExpectation(int argc, const char* argv[]) { + ExceptionExpectation expects; + + // Parse exception expectations from (the remainder of) the command line. + int arg_index = 0; + // Skip any flags. + while (argc > arg_index && IsFlag(argv[arg_index])) arg_index++; + if (argc > arg_index) { + if (strncmp("throws", argv[arg_index], 7)) { + // First argument after filename, if present, must be the verbatim + // "throws", marking that the preparsing should fail with an exception. + fail(NULL, "ERROR: Extra arguments not prefixed by \"throws\".\n"); + } + expects.throws = true; + do { + arg_index++; + } while (argc > arg_index && IsFlag(argv[arg_index])); + if (argc > arg_index) { + // Next argument is the exception type identifier. + expects.type = argv[arg_index]; + do { + arg_index++; + } while (argc > arg_index && IsFlag(argv[arg_index])); + if (argc > arg_index) { + expects.beg_pos = atoi(argv[arg_index]); + do { + arg_index++; + } while (argc > arg_index && IsFlag(argv[arg_index])); + if (argc > arg_index) { + expects.end_pos = atoi(argv[arg_index]); + } + } + } } - size_t length = static_cast<size_t>(ftell(input)); - rewind(input); + return expects; +} - // Read JS file into memory buffer. - ScopedPointer<uint8_t> buffer(new uint8_t[length]); - if (!ReadBuffer(input, *buffer, length)) { - perror("ERROR: Reading file"); - fflush(stderr); - return EXIT_FAILURE; + +int main(int argc, const char* argv[]) { + // Parse command line. + // Format: preparser (<scriptfile> | -e "<source>") + // ["throws" [<exn-type> [<start> [<end>]]]] + // Any flags (except an initial -s) are ignored. + + // Check for mandatory filename argument. + int arg_index = 1; + if (argc <= arg_index) { + fail(NULL, "ERROR: No filename on command line.\n"); + } + const uint8_t* source = NULL; + const char* filename = argv[arg_index]; + if (!strcmp(filename, "-e")) { + arg_index++; + if (argc <= arg_index) { + fail(NULL, "ERROR: No source after -e on command line.\n"); + } + source = reinterpret_cast<const uint8_t*>(argv[arg_index]); + } + // Check remainder of command line for exception expectations. + arg_index++; + ExceptionExpectation expects = + ParseExpectation(argc - arg_index, argv + arg_index); + + ScopedPointer<uint8_t> buffer; + size_t length; + + if (source == NULL) { + // Open JS file. + FILE* input = fopen(filename, "rb"); + if (input == NULL) { + perror("ERROR: Error opening file"); + fflush(stderr); + return EXIT_FAILURE; + } + // Find length of JS file. + if (fseek(input, 0, SEEK_END) != 0) { + perror("ERROR: Error during seek"); + fflush(stderr); + return EXIT_FAILURE; + } + length = static_cast<size_t>(ftell(input)); + rewind(input); + // Read JS file into memory buffer. + buffer = new uint8_t[length]; + if (!ReadBuffer(input, *buffer, length)) { + perror("ERROR: Reading file"); + fflush(stderr); + return EXIT_FAILURE; + } + fclose(input); + source = *buffer; + } else { + length = strlen(reinterpret_cast<const char*>(source)); } - fclose(input); // Preparse input file. - AsciiInputStream input_buffer(*buffer, length); + AsciiInputStream input_buffer(source, length); size_t kMaxStackSize = 64 * 1024 * sizeof(void*); // NOLINT v8::PreParserData data = v8::Preparse(&input_buffer, kMaxStackSize); // Fail if stack overflow. if (data.stack_overflow()) { - fprintf(stderr, "ERROR: Stack overflow\n"); - fflush(stderr); - return EXIT_FAILURE; + fail(&data, "ERROR: Stack overflow\n"); } - // Print preparser data to stdout. - uint32_t size = data.size(); - fprintf(stderr, "LOG: Success, data size: %u\n", size); - fflush(stderr); - if (!WriteBuffer(stdout, data.data(), size)) { - perror("ERROR: Writing data"); - return EXIT_FAILURE; - } + // Check that the expected exception is thrown, if an exception is + // expected. + CheckException(&data, &expects); return EXIT_SUCCESS; } |