Commit dc390d0e authored by lrn@chromium.org's avatar lrn@chromium.org

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
parent 052f5951
......@@ -89,6 +89,8 @@ SOURCES = {
objects-visiting.cc
oprofile-agent.cc
parser.cc
preparser.cc
preparse-data.cc
profile-generator.cc
property.cc
regexp-macro-assembler-irregexp.cc
......
This diff is collapsed.
......@@ -32,6 +32,7 @@
#include "ast.h"
#include "scanner.h"
#include "scopes.h"
#include "preparse-data.h"
namespace v8 {
namespace internal {
......@@ -123,32 +124,15 @@ class ScriptDataImpl : public ScriptData {
Vector<const char*> BuildArgs();
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
// returned true.
bool has_error() { return store_[kHasErrorOffset]; }
unsigned magic() { return store_[kMagicOffset]; }
unsigned version() { return store_[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;
bool has_error() { return store_[PreparseDataConstants::kHasErrorOffset]; }
unsigned magic() { return store_[PreparseDataConstants::kMagicOffset]; }
unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
private:
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 {
public:
// Parses the source code represented by the compilation info and sets its
......
// 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.
// 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_
This diff is collapsed.
This diff is collapsed.
......@@ -8734,7 +8734,7 @@ TEST(PreCompileInvalidPreparseDataError) {
v8::ScriptData::PreCompile(script, i::StrLength(script));
CHECK(!sd->HasError());
// ScriptDataImpl private implementation details
const int kHeaderSize = i::ScriptDataImpl::kHeaderSize;
const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
const int kFunctionEntrySize = i::FunctionEntry::kSize;
const int kFunctionEntryStartOffset = 0;
const int kFunctionEntryEndOffset = 1;
......
......@@ -263,8 +263,7 @@ TEST(StandAlonePreParser) {
i::CompleteParserRecorder log;
i::V8JavaScriptScanner scanner;
scanner.Initialize(i::Handle<i::String>::null(), &stream);
v8::preparser::PreParser<i::V8JavaScriptScanner,
i::CompleteParserRecorder> preparser;
v8::preparser::PreParser preparser;
bool result = preparser.PreParseProgram(&scanner, &log, true);
CHECK(result);
i::ScriptDataImpl data(log.ExtractData());
......
......@@ -761,6 +761,22 @@
RelativePath="..\..\src\parser.h"
>
</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
RelativePath="..\..\src\profile-generator.cc"
>
......
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