Untemplated preparser.h and made it depend on virtual types.
Extracted preparse-data specification and logging classes. Review URL: http://codereview.chromium.org/5166006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5877 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
052f595184
commit
dc390d0e1f
@ -89,6 +89,8 @@ SOURCES = {
|
|||||||
objects-visiting.cc
|
objects-visiting.cc
|
||||||
oprofile-agent.cc
|
oprofile-agent.cc
|
||||||
parser.cc
|
parser.cc
|
||||||
|
preparser.cc
|
||||||
|
preparse-data.cc
|
||||||
profile-generator.cc
|
profile-generator.cc
|
||||||
property.cc
|
property.cc
|
||||||
regexp-macro-assembler-irregexp.cc
|
regexp-macro-assembler-irregexp.cc
|
||||||
|
193
src/parser.cc
193
src/parser.cc
@ -356,65 +356,6 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vector<unsigned> PartialParserRecorder::ExtractData() {
|
|
||||||
int function_size = function_store_.size();
|
|
||||||
int total_size = ScriptDataImpl::kHeaderSize + function_size;
|
|
||||||
Vector<unsigned> data = Vector<unsigned>::New(total_size);
|
|
||||||
preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
|
|
||||||
preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
|
|
||||||
memcpy(data.start(), preamble_, sizeof(preamble_));
|
|
||||||
int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
|
|
||||||
if (function_size > 0) {
|
|
||||||
function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
|
|
||||||
symbol_start));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CompleteParserRecorder::LogSymbol(int start, Vector<const char> literal) {
|
|
||||||
if (!is_recording_) return;
|
|
||||||
|
|
||||||
int hash = vector_hash(literal);
|
|
||||||
HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
|
|
||||||
int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
|
|
||||||
if (id == 0) {
|
|
||||||
// Put (symbol_id_ + 1) into entry and increment it.
|
|
||||||
id = ++symbol_id_;
|
|
||||||
entry->value = reinterpret_cast<void*>(id);
|
|
||||||
Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
|
|
||||||
entry->key = &symbol[0];
|
|
||||||
}
|
|
||||||
WriteNumber(id - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Vector<unsigned> CompleteParserRecorder::ExtractData() {
|
|
||||||
int function_size = function_store_.size();
|
|
||||||
// Add terminator to symbols, then pad to unsigned size.
|
|
||||||
int symbol_size = symbol_store_.size();
|
|
||||||
int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
|
|
||||||
symbol_store_.AddBlock(padding, ScriptDataImpl::kNumberTerminator);
|
|
||||||
symbol_size += padding;
|
|
||||||
int total_size = ScriptDataImpl::kHeaderSize + function_size
|
|
||||||
+ (symbol_size / sizeof(unsigned));
|
|
||||||
Vector<unsigned> data = Vector<unsigned>::New(total_size);
|
|
||||||
preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
|
|
||||||
preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_;
|
|
||||||
memcpy(data.start(), preamble_, sizeof(preamble_));
|
|
||||||
int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
|
|
||||||
if (function_size > 0) {
|
|
||||||
function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
|
|
||||||
symbol_start));
|
|
||||||
}
|
|
||||||
if (!has_error()) {
|
|
||||||
symbol_store_.WriteTo(
|
|
||||||
Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
|
FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
|
||||||
// The current pre-data entry must be a FunctionEntry with the given
|
// The current pre-data entry must be a FunctionEntry with the given
|
||||||
// start position.
|
// start position.
|
||||||
@ -437,92 +378,52 @@ int ScriptDataImpl::GetSymbolIdentifier() {
|
|||||||
bool ScriptDataImpl::SanityCheck() {
|
bool ScriptDataImpl::SanityCheck() {
|
||||||
// Check that the header data is valid and doesn't specify
|
// Check that the header data is valid and doesn't specify
|
||||||
// point to positions outside the store.
|
// point to positions outside the store.
|
||||||
if (store_.length() < ScriptDataImpl::kHeaderSize) return false;
|
if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
|
||||||
if (magic() != ScriptDataImpl::kMagicNumber) return false;
|
if (magic() != PreparseDataConstants::kMagicNumber) return false;
|
||||||
if (version() != ScriptDataImpl::kCurrentVersion) return false;
|
if (version() != PreparseDataConstants::kCurrentVersion) return false;
|
||||||
if (has_error()) {
|
if (has_error()) {
|
||||||
// Extra sane sanity check for error message encoding.
|
// Extra sane sanity check for error message encoding.
|
||||||
if (store_.length() <= kHeaderSize + kMessageTextPos) return false;
|
if (store_.length() <= PreparseDataConstants::kHeaderSize
|
||||||
if (Read(kMessageStartPos) > Read(kMessageEndPos)) return false;
|
+ PreparseDataConstants::kMessageTextPos) {
|
||||||
unsigned arg_count = Read(kMessageArgCountPos);
|
return false;
|
||||||
int pos = kMessageTextPos;
|
}
|
||||||
|
if (Read(PreparseDataConstants::kMessageStartPos) >
|
||||||
|
Read(PreparseDataConstants::kMessageEndPos)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
|
||||||
|
int pos = PreparseDataConstants::kMessageTextPos;
|
||||||
for (unsigned int i = 0; i <= arg_count; i++) {
|
for (unsigned int i = 0; i <= arg_count; i++) {
|
||||||
if (store_.length() <= kHeaderSize + pos) return false;
|
if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int length = static_cast<int>(Read(pos));
|
int length = static_cast<int>(Read(pos));
|
||||||
if (length < 0) return false;
|
if (length < 0) return false;
|
||||||
pos += 1 + length;
|
pos += 1 + length;
|
||||||
}
|
}
|
||||||
if (store_.length() < kHeaderSize + pos) return false;
|
if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Check that the space allocated for function entries is sane.
|
// Check that the space allocated for function entries is sane.
|
||||||
int functions_size =
|
int functions_size =
|
||||||
static_cast<int>(store_[ScriptDataImpl::kFunctionsSizeOffset]);
|
static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
|
||||||
if (functions_size < 0) return false;
|
if (functions_size < 0) return false;
|
||||||
if (functions_size % FunctionEntry::kSize != 0) return false;
|
if (functions_size % FunctionEntry::kSize != 0) return false;
|
||||||
// Check that the count of symbols is non-negative.
|
// Check that the count of symbols is non-negative.
|
||||||
int symbol_count =
|
int symbol_count =
|
||||||
static_cast<int>(store_[ScriptDataImpl::kSymbolCountOffset]);
|
static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
|
||||||
if (symbol_count < 0) return false;
|
if (symbol_count < 0) return false;
|
||||||
// Check that the total size has room for header and function entries.
|
// Check that the total size has room for header and function entries.
|
||||||
int minimum_size =
|
int minimum_size =
|
||||||
ScriptDataImpl::kHeaderSize + functions_size;
|
PreparseDataConstants::kHeaderSize + functions_size;
|
||||||
if (store_.length() < minimum_size) return false;
|
if (store_.length() < minimum_size) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PartialParserRecorder::PartialParserRecorder()
|
|
||||||
: function_store_(0),
|
|
||||||
is_recording_(true),
|
|
||||||
pause_count_(0) {
|
|
||||||
preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
|
|
||||||
preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
|
|
||||||
preamble_[ScriptDataImpl::kHasErrorOffset] = false;
|
|
||||||
preamble_[ScriptDataImpl::kFunctionsSizeOffset] = 0;
|
|
||||||
preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
|
|
||||||
preamble_[ScriptDataImpl::kSizeOffset] = 0;
|
|
||||||
ASSERT_EQ(6, ScriptDataImpl::kHeaderSize);
|
|
||||||
#ifdef DEBUG
|
|
||||||
prev_start_ = -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CompleteParserRecorder::CompleteParserRecorder()
|
|
||||||
: PartialParserRecorder(),
|
|
||||||
symbol_store_(0),
|
|
||||||
symbol_entries_(0),
|
|
||||||
symbol_table_(vector_compare),
|
|
||||||
symbol_id_(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PartialParserRecorder::WriteString(Vector<const char> str) {
|
|
||||||
function_store_.Add(str.length());
|
|
||||||
for (int i = 0; i < str.length(); i++) {
|
|
||||||
function_store_.Add(str[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CompleteParserRecorder::WriteNumber(int number) {
|
|
||||||
ASSERT(number >= 0);
|
|
||||||
|
|
||||||
int mask = (1 << 28) - 1;
|
|
||||||
for (int i = 28; i > 0; i -= 7) {
|
|
||||||
if (number > mask) {
|
|
||||||
symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
|
|
||||||
number &= mask;
|
|
||||||
}
|
|
||||||
mask >>= 7;
|
|
||||||
}
|
|
||||||
symbol_store_.Add(static_cast<byte>(number));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
|
const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
|
||||||
int length = start[0];
|
int length = start[0];
|
||||||
char* result = NewArray<char>(length + 1);
|
char* result = NewArray<char>(length + 1);
|
||||||
@ -534,47 +435,26 @@ const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PartialParserRecorder::LogMessage(Scanner::Location loc,
|
|
||||||
const char* message,
|
|
||||||
Vector<const char*> args) {
|
|
||||||
if (has_error()) return;
|
|
||||||
preamble_[ScriptDataImpl::kHasErrorOffset] = true;
|
|
||||||
function_store_.Reset();
|
|
||||||
STATIC_ASSERT(ScriptDataImpl::kMessageStartPos == 0);
|
|
||||||
function_store_.Add(loc.beg_pos);
|
|
||||||
STATIC_ASSERT(ScriptDataImpl::kMessageEndPos == 1);
|
|
||||||
function_store_.Add(loc.end_pos);
|
|
||||||
STATIC_ASSERT(ScriptDataImpl::kMessageArgCountPos == 2);
|
|
||||||
function_store_.Add(args.length());
|
|
||||||
STATIC_ASSERT(ScriptDataImpl::kMessageTextPos == 3);
|
|
||||||
WriteString(CStrVector(message));
|
|
||||||
for (int i = 0; i < args.length(); i++) {
|
|
||||||
WriteString(CStrVector(args[i]));
|
|
||||||
}
|
|
||||||
is_recording_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Scanner::Location ScriptDataImpl::MessageLocation() {
|
Scanner::Location ScriptDataImpl::MessageLocation() {
|
||||||
int beg_pos = Read(kMessageStartPos);
|
int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
|
||||||
int end_pos = Read(kMessageEndPos);
|
int end_pos = Read(PreparseDataConstants::kMessageEndPos);
|
||||||
return Scanner::Location(beg_pos, end_pos);
|
return Scanner::Location(beg_pos, end_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* ScriptDataImpl::BuildMessage() {
|
const char* ScriptDataImpl::BuildMessage() {
|
||||||
unsigned* start = ReadAddress(kMessageTextPos);
|
unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
|
||||||
return ReadString(start, NULL);
|
return ReadString(start, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Vector<const char*> ScriptDataImpl::BuildArgs() {
|
Vector<const char*> ScriptDataImpl::BuildArgs() {
|
||||||
int arg_count = Read(kMessageArgCountPos);
|
int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
|
||||||
const char** array = NewArray<const char*>(arg_count);
|
const char** array = NewArray<const char*>(arg_count);
|
||||||
// Position after text found by skipping past length field and
|
// Position after text found by skipping past length field and
|
||||||
// length field content words.
|
// length field content words.
|
||||||
int pos = kMessageTextPos + 1 + Read(kMessageTextPos);
|
int pos = PreparseDataConstants::kMessageTextPos + 1
|
||||||
|
+ Read(PreparseDataConstants::kMessageTextPos);
|
||||||
for (int i = 0; i < arg_count; i++) {
|
for (int i = 0; i < arg_count; i++) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
array[i] = ReadString(ReadAddress(pos), &count);
|
array[i] = ReadString(ReadAddress(pos), &count);
|
||||||
@ -585,12 +465,12 @@ Vector<const char*> ScriptDataImpl::BuildArgs() {
|
|||||||
|
|
||||||
|
|
||||||
unsigned ScriptDataImpl::Read(int position) {
|
unsigned ScriptDataImpl::Read(int position) {
|
||||||
return store_[ScriptDataImpl::kHeaderSize + position];
|
return store_[PreparseDataConstants::kHeaderSize + position];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned* ScriptDataImpl::ReadAddress(int position) {
|
unsigned* ScriptDataImpl::ReadAddress(int position) {
|
||||||
return &store_[ScriptDataImpl::kHeaderSize + position];
|
return &store_[PreparseDataConstants::kHeaderSize + position];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4601,9 +4481,10 @@ bool ScriptDataImpl::HasError() {
|
|||||||
|
|
||||||
void ScriptDataImpl::Initialize() {
|
void ScriptDataImpl::Initialize() {
|
||||||
// Prepares state for use.
|
// Prepares state for use.
|
||||||
if (store_.length() >= kHeaderSize) {
|
if (store_.length() >= PreparseDataConstants::kHeaderSize) {
|
||||||
function_index_ = kHeaderSize;
|
function_index_ = PreparseDataConstants::kHeaderSize;
|
||||||
int symbol_data_offset = kHeaderSize + store_[kFunctionsSizeOffset];
|
int symbol_data_offset = PreparseDataConstants::kHeaderSize
|
||||||
|
+ store_[PreparseDataConstants::kFunctionsSizeOffset];
|
||||||
if (store_.length() > symbol_data_offset) {
|
if (store_.length() > symbol_data_offset) {
|
||||||
symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
|
symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
|
||||||
} else {
|
} else {
|
||||||
@ -4625,7 +4506,7 @@ int ScriptDataImpl::ReadNumber(byte** source) {
|
|||||||
byte* data = *source;
|
byte* data = *source;
|
||||||
if (data >= symbol_data_end_) return -1;
|
if (data >= symbol_data_end_) return -1;
|
||||||
byte input = *data;
|
byte input = *data;
|
||||||
if (input == kNumberTerminator) {
|
if (input == PreparseDataConstants::kNumberTerminator) {
|
||||||
// End of stream marker.
|
// End of stream marker.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -4646,11 +4527,11 @@ int ScriptDataImpl::ReadNumber(byte** source) {
|
|||||||
static ScriptDataImpl* DoPreParse(Handle<String> source,
|
static ScriptDataImpl* DoPreParse(Handle<String> source,
|
||||||
unibrow::CharacterStream* stream,
|
unibrow::CharacterStream* stream,
|
||||||
bool allow_lazy,
|
bool allow_lazy,
|
||||||
PartialParserRecorder* recorder,
|
ParserRecorder* recorder,
|
||||||
int literal_flags) {
|
int literal_flags) {
|
||||||
V8JavaScriptScanner scanner;
|
V8JavaScriptScanner scanner;
|
||||||
scanner.Initialize(source, stream, literal_flags);
|
scanner.Initialize(source, stream, literal_flags);
|
||||||
preparser::PreParser<JavaScriptScanner, PartialParserRecorder> preparser;
|
preparser::PreParser preparser;
|
||||||
if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) {
|
if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) {
|
||||||
Top::StackOverflow();
|
Top::StackOverflow();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
151
src/parser.h
151
src/parser.h
@ -32,6 +32,7 @@
|
|||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "scopes.h"
|
#include "scopes.h"
|
||||||
|
#include "preparse-data.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -123,32 +124,15 @@ class ScriptDataImpl : public ScriptData {
|
|||||||
Vector<const char*> BuildArgs();
|
Vector<const char*> BuildArgs();
|
||||||
|
|
||||||
int symbol_count() {
|
int symbol_count() {
|
||||||
return (store_.length() > kHeaderSize) ? store_[kSymbolCountOffset] : 0;
|
return (store_.length() > PreparseDataConstants::kHeaderSize)
|
||||||
|
? store_[PreparseDataConstants::kSymbolCountOffset]
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
// The following functions should only be called if SanityCheck has
|
// The following functions should only be called if SanityCheck has
|
||||||
// returned true.
|
// returned true.
|
||||||
bool has_error() { return store_[kHasErrorOffset]; }
|
bool has_error() { return store_[PreparseDataConstants::kHasErrorOffset]; }
|
||||||
unsigned magic() { return store_[kMagicOffset]; }
|
unsigned magic() { return store_[PreparseDataConstants::kMagicOffset]; }
|
||||||
unsigned version() { return store_[kVersionOffset]; }
|
unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
|
||||||
|
|
||||||
static const unsigned kMagicNumber = 0xBadDead;
|
|
||||||
static const unsigned kCurrentVersion = 5;
|
|
||||||
|
|
||||||
static const int kMagicOffset = 0;
|
|
||||||
static const int kVersionOffset = 1;
|
|
||||||
static const int kHasErrorOffset = 2;
|
|
||||||
static const int kFunctionsSizeOffset = 3;
|
|
||||||
static const int kSymbolCountOffset = 4;
|
|
||||||
static const int kSizeOffset = 5;
|
|
||||||
static const int kHeaderSize = 6;
|
|
||||||
|
|
||||||
// If encoding a message, the following positions are fixed.
|
|
||||||
static const int kMessageStartPos = 0;
|
|
||||||
static const int kMessageEndPos = 1;
|
|
||||||
static const int kMessageArgCountPos = 2;
|
|
||||||
static const int kMessageTextPos = 3;
|
|
||||||
|
|
||||||
static const byte kNumberTerminator = 0x80u;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<unsigned> store_;
|
Vector<unsigned> store_;
|
||||||
@ -177,127 +161,6 @@ class ScriptDataImpl : public ScriptData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Record only functions.
|
|
||||||
class PartialParserRecorder {
|
|
||||||
public:
|
|
||||||
PartialParserRecorder();
|
|
||||||
virtual ~PartialParserRecorder() {}
|
|
||||||
|
|
||||||
void LogFunction(int start, int end, int literals, int properties) {
|
|
||||||
function_store_.Add(start);
|
|
||||||
function_store_.Add(end);
|
|
||||||
function_store_.Add(literals);
|
|
||||||
function_store_.Add(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void LogSymbol(int start, const char* symbol, int length) { }
|
|
||||||
|
|
||||||
// Logs an error message and marks the log as containing an error.
|
|
||||||
// Further logging will be ignored, and ExtractData will return a vector
|
|
||||||
// representing the error only.
|
|
||||||
void LogMessage(int start,
|
|
||||||
int end,
|
|
||||||
const char* message,
|
|
||||||
const char* argument_opt) {
|
|
||||||
Scanner::Location location(start, end);
|
|
||||||
Vector<const char*> arguments;
|
|
||||||
if (argument_opt != NULL) {
|
|
||||||
arguments = Vector<const char*>(&argument_opt, 1);
|
|
||||||
}
|
|
||||||
this->LogMessage(location, message, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
int function_position() { return function_store_.size(); }
|
|
||||||
|
|
||||||
void LogMessage(Scanner::Location loc,
|
|
||||||
const char* message,
|
|
||||||
Vector<const char*> args);
|
|
||||||
|
|
||||||
virtual Vector<unsigned> ExtractData();
|
|
||||||
|
|
||||||
void PauseRecording() {
|
|
||||||
pause_count_++;
|
|
||||||
is_recording_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResumeRecording() {
|
|
||||||
ASSERT(pause_count_ > 0);
|
|
||||||
if (--pause_count_ == 0) is_recording_ = !has_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
int symbol_position() { return 0; }
|
|
||||||
int symbol_ids() { return 0; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool has_error() {
|
|
||||||
return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_recording() {
|
|
||||||
return is_recording_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteString(Vector<const char> str);
|
|
||||||
|
|
||||||
Collector<unsigned> function_store_;
|
|
||||||
unsigned preamble_[ScriptDataImpl::kHeaderSize];
|
|
||||||
bool is_recording_;
|
|
||||||
int pause_count_;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
int prev_start_;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Record both functions and symbols.
|
|
||||||
class CompleteParserRecorder: public PartialParserRecorder {
|
|
||||||
public:
|
|
||||||
CompleteParserRecorder();
|
|
||||||
virtual ~CompleteParserRecorder() { }
|
|
||||||
|
|
||||||
void LogSymbol(int start, Vector<const char> literal);
|
|
||||||
|
|
||||||
virtual void LogSymbol(int start, const char* symbol, int length) {
|
|
||||||
LogSymbol(start, Vector<const char>(symbol, length));
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Vector<unsigned> ExtractData();
|
|
||||||
|
|
||||||
int symbol_position() { return symbol_store_.size(); }
|
|
||||||
int symbol_ids() { return symbol_id_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
static int vector_hash(Vector<const char> string) {
|
|
||||||
int hash = 0;
|
|
||||||
for (int i = 0; i < string.length(); i++) {
|
|
||||||
int c = string[i];
|
|
||||||
hash += c;
|
|
||||||
hash += (hash << 10);
|
|
||||||
hash ^= (hash >> 6);
|
|
||||||
}
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool vector_compare(void* a, void* b) {
|
|
||||||
Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
|
|
||||||
Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b);
|
|
||||||
int length = string1->length();
|
|
||||||
if (string2->length() != length) return false;
|
|
||||||
return memcmp(string1->start(), string2->start(), length) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write a non-negative number to the symbol store.
|
|
||||||
void WriteNumber(int number);
|
|
||||||
|
|
||||||
Collector<byte> symbol_store_;
|
|
||||||
Collector<Vector<const char> > symbol_entries_;
|
|
||||||
HashMap symbol_table_;
|
|
||||||
int symbol_id_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ParserApi {
|
class ParserApi {
|
||||||
public:
|
public:
|
||||||
// Parses the source code represented by the compilation info and sets its
|
// Parses the source code represented by the compilation info and sets its
|
||||||
|
180
src/preparse-data.cc
Normal file
180
src/preparse-data.cc
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
// Copyright 2010 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:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "../include/v8stdint.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "checks.h"
|
||||||
|
#include "allocation.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "list-inl.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include "preparse-data.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// FunctionLoggingParserRecorder
|
||||||
|
|
||||||
|
FunctionLoggingParserRecorder::FunctionLoggingParserRecorder()
|
||||||
|
: function_store_(0),
|
||||||
|
is_recording_(true),
|
||||||
|
pause_count_(0) {
|
||||||
|
preamble_[PreparseDataConstants::kMagicOffset] =
|
||||||
|
PreparseDataConstants::kMagicNumber;
|
||||||
|
preamble_[PreparseDataConstants::kVersionOffset] =
|
||||||
|
PreparseDataConstants::kCurrentVersion;
|
||||||
|
preamble_[PreparseDataConstants::kHasErrorOffset] = false;
|
||||||
|
preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0;
|
||||||
|
preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
|
||||||
|
preamble_[PreparseDataConstants::kSizeOffset] = 0;
|
||||||
|
ASSERT_EQ(6, PreparseDataConstants::kHeaderSize);
|
||||||
|
#ifdef DEBUG
|
||||||
|
prev_start_ = -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FunctionLoggingParserRecorder::LogMessage(int start_pos,
|
||||||
|
int end_pos,
|
||||||
|
const char* message,
|
||||||
|
const char* arg_opt) {
|
||||||
|
if (has_error()) return;
|
||||||
|
preamble_[PreparseDataConstants::kHasErrorOffset] = true;
|
||||||
|
function_store_.Reset();
|
||||||
|
STATIC_ASSERT(PreparseDataConstants::kMessageStartPos == 0);
|
||||||
|
function_store_.Add(start_pos);
|
||||||
|
STATIC_ASSERT(PreparseDataConstants::kMessageEndPos == 1);
|
||||||
|
function_store_.Add(end_pos);
|
||||||
|
STATIC_ASSERT(PreparseDataConstants::kMessageArgCountPos == 2);
|
||||||
|
function_store_.Add((arg_opt == NULL) ? 0 : 1);
|
||||||
|
STATIC_ASSERT(PreparseDataConstants::kMessageTextPos == 3);
|
||||||
|
WriteString(CStrVector(message));
|
||||||
|
if (arg_opt) WriteString(CStrVector(arg_opt));
|
||||||
|
is_recording_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FunctionLoggingParserRecorder::WriteString(Vector<const char> str) {
|
||||||
|
function_store_.Add(str.length());
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
function_store_.Add(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// PartialParserRecorder - Record both function entries and symbols.
|
||||||
|
|
||||||
|
Vector<unsigned> PartialParserRecorder::ExtractData() {
|
||||||
|
int function_size = function_store_.size();
|
||||||
|
int total_size = PreparseDataConstants::kHeaderSize + function_size;
|
||||||
|
Vector<unsigned> data = Vector<unsigned>::New(total_size);
|
||||||
|
preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
|
||||||
|
preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
|
||||||
|
memcpy(data.start(), preamble_, sizeof(preamble_));
|
||||||
|
int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
|
||||||
|
if (function_size > 0) {
|
||||||
|
function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
|
||||||
|
symbol_start));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// CompleteParserRecorder - Record both function entries and symbols.
|
||||||
|
|
||||||
|
CompleteParserRecorder::CompleteParserRecorder()
|
||||||
|
: FunctionLoggingParserRecorder(),
|
||||||
|
symbol_store_(0),
|
||||||
|
symbol_entries_(0),
|
||||||
|
symbol_table_(vector_compare),
|
||||||
|
symbol_id_(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CompleteParserRecorder::LogSymbol(
|
||||||
|
int start, const char* literal_chars, int length) {
|
||||||
|
if (!is_recording_) return;
|
||||||
|
|
||||||
|
Vector<const char> literal(literal_chars, length);
|
||||||
|
int hash = vector_hash(literal);
|
||||||
|
HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
|
||||||
|
int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
|
||||||
|
if (id == 0) {
|
||||||
|
// Put (symbol_id_ + 1) into entry and increment it.
|
||||||
|
id = ++symbol_id_;
|
||||||
|
entry->value = reinterpret_cast<void*>(id);
|
||||||
|
Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
|
||||||
|
entry->key = &symbol[0];
|
||||||
|
}
|
||||||
|
WriteNumber(id - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Vector<unsigned> CompleteParserRecorder::ExtractData() {
|
||||||
|
int function_size = function_store_.size();
|
||||||
|
// Add terminator to symbols, then pad to unsigned size.
|
||||||
|
int symbol_size = symbol_store_.size();
|
||||||
|
int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
|
||||||
|
symbol_store_.AddBlock(padding, PreparseDataConstants::kNumberTerminator);
|
||||||
|
symbol_size += padding;
|
||||||
|
int total_size = PreparseDataConstants::kHeaderSize + function_size
|
||||||
|
+ (symbol_size / sizeof(unsigned));
|
||||||
|
Vector<unsigned> data = Vector<unsigned>::New(total_size);
|
||||||
|
preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
|
||||||
|
preamble_[PreparseDataConstants::kSymbolCountOffset] = symbol_id_;
|
||||||
|
memcpy(data.start(), preamble_, sizeof(preamble_));
|
||||||
|
int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
|
||||||
|
if (function_size > 0) {
|
||||||
|
function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
|
||||||
|
symbol_start));
|
||||||
|
}
|
||||||
|
if (!has_error()) {
|
||||||
|
symbol_store_.WriteTo(
|
||||||
|
Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CompleteParserRecorder::WriteNumber(int number) {
|
||||||
|
ASSERT(number >= 0);
|
||||||
|
|
||||||
|
int mask = (1 << 28) - 1;
|
||||||
|
for (int i = 28; i > 0; i -= 7) {
|
||||||
|
if (number > mask) {
|
||||||
|
symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
|
||||||
|
number &= mask;
|
||||||
|
}
|
||||||
|
mask >>= 7;
|
||||||
|
}
|
||||||
|
symbol_store_.Add(static_cast<byte>(number));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace v8::internal.
|
223
src/preparse-data.h
Normal file
223
src/preparse-data.h
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
// Copyright 2010 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:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#ifndef V8_PREPARSER_DATA_H_
|
||||||
|
#define V8_PREPARSER_DATA_H_
|
||||||
|
|
||||||
|
#include "hashmap.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Generic and general data used by preparse data recorders and readers.
|
||||||
|
|
||||||
|
class PreparseDataConstants : public AllStatic {
|
||||||
|
public:
|
||||||
|
// Layout and constants of the preparse data exchange format.
|
||||||
|
static const unsigned kMagicNumber = 0xBadDead;
|
||||||
|
static const unsigned kCurrentVersion = 5;
|
||||||
|
|
||||||
|
static const int kMagicOffset = 0;
|
||||||
|
static const int kVersionOffset = 1;
|
||||||
|
static const int kHasErrorOffset = 2;
|
||||||
|
static const int kFunctionsSizeOffset = 3;
|
||||||
|
static const int kSymbolCountOffset = 4;
|
||||||
|
static const int kSizeOffset = 5;
|
||||||
|
static const int kHeaderSize = 6;
|
||||||
|
|
||||||
|
// If encoding a message, the following positions are fixed.
|
||||||
|
static const int kMessageStartPos = 0;
|
||||||
|
static const int kMessageEndPos = 1;
|
||||||
|
static const int kMessageArgCountPos = 2;
|
||||||
|
static const int kMessageTextPos = 3;
|
||||||
|
|
||||||
|
static const byte kNumberTerminator = 0x80u;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// ParserRecorder - Logging of preparser data.
|
||||||
|
|
||||||
|
// Abstract interface for preparse data recorder.
|
||||||
|
class ParserRecorder {
|
||||||
|
public:
|
||||||
|
ParserRecorder() { }
|
||||||
|
virtual ~ParserRecorder() { }
|
||||||
|
|
||||||
|
// Logs the scope and some details of a function literal in the source.
|
||||||
|
virtual void LogFunction(int start,
|
||||||
|
int end,
|
||||||
|
int literals,
|
||||||
|
int properties) = 0;
|
||||||
|
|
||||||
|
// Logs a symbol creation of a literal or identifier.
|
||||||
|
virtual void LogSymbol(int start, const char* symbol, int length) = 0;
|
||||||
|
|
||||||
|
// Logs an error message and marks the log as containing an error.
|
||||||
|
// Further logging will be ignored, and ExtractData will return a vector
|
||||||
|
// representing the error only.
|
||||||
|
virtual void LogMessage(int start,
|
||||||
|
int end,
|
||||||
|
const char* message,
|
||||||
|
const char* argument_opt) = 0;
|
||||||
|
|
||||||
|
virtual int function_position() = 0;
|
||||||
|
|
||||||
|
virtual int symbol_position() = 0;
|
||||||
|
|
||||||
|
virtual int symbol_ids() = 0;
|
||||||
|
|
||||||
|
virtual Vector<unsigned> ExtractData() = 0;
|
||||||
|
|
||||||
|
virtual void PauseRecording() = 0;
|
||||||
|
|
||||||
|
virtual void ResumeRecording() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// FunctionLoggingParserRecorder - Record only function entries
|
||||||
|
|
||||||
|
class FunctionLoggingParserRecorder : public ParserRecorder {
|
||||||
|
public:
|
||||||
|
FunctionLoggingParserRecorder();
|
||||||
|
virtual ~FunctionLoggingParserRecorder() {}
|
||||||
|
|
||||||
|
virtual void LogFunction(int start, int end, int literals, int properties) {
|
||||||
|
function_store_.Add(start);
|
||||||
|
function_store_.Add(end);
|
||||||
|
function_store_.Add(literals);
|
||||||
|
function_store_.Add(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logs an error message and marks the log as containing an error.
|
||||||
|
// Further logging will be ignored, and ExtractData will return a vector
|
||||||
|
// representing the error only.
|
||||||
|
virtual void LogMessage(int start,
|
||||||
|
int end,
|
||||||
|
const char* message,
|
||||||
|
const char* argument_opt);
|
||||||
|
|
||||||
|
virtual int function_position() { return function_store_.size(); }
|
||||||
|
|
||||||
|
|
||||||
|
virtual Vector<unsigned> ExtractData() = 0;
|
||||||
|
|
||||||
|
virtual void PauseRecording() {
|
||||||
|
pause_count_++;
|
||||||
|
is_recording_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ResumeRecording() {
|
||||||
|
ASSERT(pause_count_ > 0);
|
||||||
|
if (--pause_count_ == 0) is_recording_ = !has_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool has_error() {
|
||||||
|
return static_cast<bool>(preamble_[PreparseDataConstants::kHasErrorOffset]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_recording() {
|
||||||
|
return is_recording_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteString(Vector<const char> str);
|
||||||
|
|
||||||
|
Collector<unsigned> function_store_;
|
||||||
|
unsigned preamble_[PreparseDataConstants::kHeaderSize];
|
||||||
|
bool is_recording_;
|
||||||
|
int pause_count_;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
int prev_start_;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// PartialParserRecorder - Record only function entries
|
||||||
|
|
||||||
|
class PartialParserRecorder : public FunctionLoggingParserRecorder {
|
||||||
|
public:
|
||||||
|
PartialParserRecorder() : FunctionLoggingParserRecorder() { }
|
||||||
|
virtual void LogSymbol(int start, const char* symbol, int length) { }
|
||||||
|
virtual ~PartialParserRecorder() { }
|
||||||
|
virtual Vector<unsigned> ExtractData();
|
||||||
|
virtual int symbol_position() { return 0; }
|
||||||
|
virtual int symbol_ids() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// CompleteParserRecorder - Record both function entries and symbols.
|
||||||
|
|
||||||
|
class CompleteParserRecorder: public FunctionLoggingParserRecorder {
|
||||||
|
public:
|
||||||
|
CompleteParserRecorder();
|
||||||
|
virtual ~CompleteParserRecorder() { }
|
||||||
|
|
||||||
|
virtual void LogSymbol(int start, const char* symbol, int length);
|
||||||
|
|
||||||
|
virtual Vector<unsigned> ExtractData();
|
||||||
|
|
||||||
|
virtual int symbol_position() { return symbol_store_.size(); }
|
||||||
|
virtual int symbol_ids() { return symbol_id_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int vector_hash(Vector<const char> string) {
|
||||||
|
int hash = 0;
|
||||||
|
for (int i = 0; i < string.length(); i++) {
|
||||||
|
int c = string[i];
|
||||||
|
hash += c;
|
||||||
|
hash += (hash << 10);
|
||||||
|
hash ^= (hash >> 6);
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool vector_compare(void* a, void* b) {
|
||||||
|
Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
|
||||||
|
Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b);
|
||||||
|
int length = string1->length();
|
||||||
|
if (string2->length() != length) return false;
|
||||||
|
return memcmp(string1->start(), string2->start(), length) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a non-negative number to the symbol store.
|
||||||
|
void WriteNumber(int number);
|
||||||
|
|
||||||
|
Collector<byte> symbol_store_;
|
||||||
|
Collector<Vector<const char> > symbol_entries_;
|
||||||
|
HashMap symbol_table_;
|
||||||
|
int symbol_id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace v8::internal.
|
||||||
|
|
||||||
|
#endif // V8_PREPARSER_DATA_H_
|
1184
src/preparser.cc
Normal file
1184
src/preparser.cc
Normal file
File diff suppressed because it is too large
Load Diff
1188
src/preparser.h
1188
src/preparser.h
File diff suppressed because it is too large
Load Diff
@ -8734,7 +8734,7 @@ TEST(PreCompileInvalidPreparseDataError) {
|
|||||||
v8::ScriptData::PreCompile(script, i::StrLength(script));
|
v8::ScriptData::PreCompile(script, i::StrLength(script));
|
||||||
CHECK(!sd->HasError());
|
CHECK(!sd->HasError());
|
||||||
// ScriptDataImpl private implementation details
|
// ScriptDataImpl private implementation details
|
||||||
const int kHeaderSize = i::ScriptDataImpl::kHeaderSize;
|
const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
|
||||||
const int kFunctionEntrySize = i::FunctionEntry::kSize;
|
const int kFunctionEntrySize = i::FunctionEntry::kSize;
|
||||||
const int kFunctionEntryStartOffset = 0;
|
const int kFunctionEntryStartOffset = 0;
|
||||||
const int kFunctionEntryEndOffset = 1;
|
const int kFunctionEntryEndOffset = 1;
|
||||||
|
@ -263,8 +263,7 @@ TEST(StandAlonePreParser) {
|
|||||||
i::CompleteParserRecorder log;
|
i::CompleteParserRecorder log;
|
||||||
i::V8JavaScriptScanner scanner;
|
i::V8JavaScriptScanner scanner;
|
||||||
scanner.Initialize(i::Handle<i::String>::null(), &stream);
|
scanner.Initialize(i::Handle<i::String>::null(), &stream);
|
||||||
v8::preparser::PreParser<i::V8JavaScriptScanner,
|
v8::preparser::PreParser preparser;
|
||||||
i::CompleteParserRecorder> preparser;
|
|
||||||
bool result = preparser.PreParseProgram(&scanner, &log, true);
|
bool result = preparser.PreParseProgram(&scanner, &log, true);
|
||||||
CHECK(result);
|
CHECK(result);
|
||||||
i::ScriptDataImpl data(log.ExtractData());
|
i::ScriptDataImpl data(log.ExtractData());
|
||||||
|
@ -761,6 +761,22 @@
|
|||||||
RelativePath="..\..\src\parser.h"
|
RelativePath="..\..\src\parser.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\preparser.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\preparser.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\preparse-data.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\preparse-data.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\profile-generator.cc"
|
RelativePath="..\..\src\profile-generator.cc"
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user