Remove log compression support.

This is no longer used in Chromium, and only pollutes code.

BUG=859

Review URL: http://codereview.chromium.org/5575006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5934 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d693ff99
......@@ -456,8 +456,6 @@ DEFINE_bool(log_snapshot_positions, false,
"log positions of (de)serialized objects in the snapshot.")
DEFINE_bool(log_suspect, false, "Log suspect operations.")
DEFINE_bool(log_producers, false, "Log stack traces of JS objects allocations.")
DEFINE_bool(compress_log, false,
"Compress log to save space (makes log less human-readable).")
DEFINE_bool(prof, false,
"Log statistical profiling information (implies --log-code).")
DEFINE_bool(prof_auto, true,
......
......@@ -273,29 +273,7 @@ void LogMessageBuilder::Append(String* str) {
void LogMessageBuilder::AppendAddress(Address addr) {
static Address last_address_ = NULL;
AppendAddress(addr, last_address_);
last_address_ = addr;
}
void LogMessageBuilder::AppendAddress(Address addr, Address bias) {
if (!FLAG_compress_log) {
Append("0x%" V8PRIxPTR, addr);
} else if (bias == NULL) {
Append("%" V8PRIxPTR, addr);
} else {
uintptr_t delta;
char sign;
if (addr >= bias) {
delta = addr - bias;
sign = '+';
} else {
delta = bias - addr;
sign = '-';
}
Append("%c%" V8PRIxPTR, sign, delta);
}
Append("0x%" V8PRIxPTR, addr);
}
......@@ -343,24 +321,6 @@ void LogMessageBuilder::AppendStringPart(const char* str, int len) {
}
bool LogMessageBuilder::StoreInCompressor(LogRecordCompressor* compressor) {
return compressor->Store(Vector<const char>(Log::message_buffer_, pos_));
}
bool LogMessageBuilder::RetrieveCompressedPrevious(
LogRecordCompressor* compressor, const char* prefix) {
pos_ = 0;
if (prefix[0] != '\0') Append(prefix);
Vector<char> prev_record(Log::message_buffer_ + pos_,
Log::kMessageBufferSize - pos_);
const bool has_prev = compressor->RetrievePreviousCompressed(&prev_record);
if (!has_prev) return false;
pos_ += prev_record.length();
return true;
}
void LogMessageBuilder::WriteToLogFile() {
ASSERT(pos_ <= Log::kMessageBufferSize);
const int written = Log::Write(Log::message_buffer_, pos_);
......@@ -369,145 +329,6 @@ void LogMessageBuilder::WriteToLogFile() {
}
}
// Formatting string for back references to the whole line. E.g. "#2" means
// "the second line above".
const char* LogRecordCompressor::kLineBackwardReferenceFormat = "#%d";
// Formatting string for back references. E.g. "#2:10" means
// "the second line above, start from char 10 (0-based)".
const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d";
LogRecordCompressor::~LogRecordCompressor() {
for (int i = 0; i < buffer_.length(); ++i) {
buffer_[i].Dispose();
}
}
static int GetNumberLength(int number) {
ASSERT(number >= 0);
ASSERT(number < 10000);
if (number < 10) return 1;
if (number < 100) return 2;
if (number < 1000) return 3;
return 4;
}
int LogRecordCompressor::GetBackwardReferenceSize(int distance, int pos) {
// See kLineBackwardReferenceFormat and kBackwardReferenceFormat.
return pos == 0 ? GetNumberLength(distance) + 1
: GetNumberLength(distance) + GetNumberLength(pos) + 2;
}
void LogRecordCompressor::PrintBackwardReference(Vector<char> dest,
int distance,
int pos) {
if (pos == 0) {
OS::SNPrintF(dest, kLineBackwardReferenceFormat, distance);
} else {
OS::SNPrintF(dest, kBackwardReferenceFormat, distance, pos);
}
}
bool LogRecordCompressor::Store(const Vector<const char>& record) {
// Check if the record is the same as the last stored one.
if (curr_ != -1) {
Vector<const char>& curr = buffer_[curr_];
if (record.length() == curr.length()
&& strncmp(record.start(), curr.start(), record.length()) == 0) {
return false;
}
}
// buffer_ is circular.
prev_ = curr_++;
curr_ %= buffer_.length();
Vector<char> record_copy = Vector<char>::New(record.length());
memcpy(record_copy.start(), record.start(), record.length());
buffer_[curr_].Dispose();
buffer_[curr_] =
Vector<const char>(record_copy.start(), record_copy.length());
return true;
}
bool LogRecordCompressor::RetrievePreviousCompressed(
Vector<char>* prev_record) {
if (prev_ == -1) return false;
int index = prev_;
// Distance from prev_.
int distance = 0;
// Best compression result among records in the buffer.
struct {
intptr_t truncated_len;
int distance;
int copy_from_pos;
int backref_size;
} best = {-1, 0, 0, 0};
Vector<const char>& prev = buffer_[prev_];
const char* const prev_start = prev.start();
const char* const prev_end = prev.start() + prev.length();
do {
// We're moving backwards until we reach the current record.
// Remember that buffer_ is circular.
if (--index == -1) index = buffer_.length() - 1;
++distance;
if (index == curr_) break;
Vector<const char>& data = buffer_[index];
if (data.start() == NULL) break;
const char* const data_end = data.start() + data.length();
const char* prev_ptr = prev_end;
const char* data_ptr = data_end;
// Compare strings backwards, stop on the last matching character.
while (prev_ptr != prev_start && data_ptr != data.start()
&& *(prev_ptr - 1) == *(data_ptr - 1)) {
--prev_ptr;
--data_ptr;
}
const intptr_t truncated_len = prev_end - prev_ptr;
const int copy_from_pos = static_cast<int>(data_ptr - data.start());
// Check if the length of compressed tail is enough.
if (truncated_len <= kMaxBackwardReferenceSize
&& truncated_len <= GetBackwardReferenceSize(distance, copy_from_pos)) {
continue;
}
// Record compression results.
if (truncated_len > best.truncated_len) {
best.truncated_len = truncated_len;
best.distance = distance;
best.copy_from_pos = copy_from_pos;
best.backref_size = GetBackwardReferenceSize(distance, copy_from_pos);
}
} while (true);
if (best.distance == 0) {
// Can't compress the previous record. Return as is.
ASSERT(prev_record->length() >= prev.length());
memcpy(prev_record->start(), prev.start(), prev.length());
prev_record->Truncate(prev.length());
} else {
// Copy the uncompressible part unchanged.
const intptr_t unchanged_len = prev.length() - best.truncated_len;
// + 1 for '\0'.
ASSERT(prev_record->length() >= unchanged_len + best.backref_size + 1);
memcpy(prev_record->start(), prev.start(), unchanged_len);
// Append the backward reference.
Vector<char> backref(
prev_record->start() + unchanged_len, best.backref_size + 1);
PrintBackwardReference(backref, best.distance, best.copy_from_pos);
ASSERT(strlen(backref.start()) - best.backref_size == 0);
prev_record->Truncate(static_cast<int>(unchanged_len + best.backref_size));
}
return true;
}
#endif // ENABLE_LOGGING_AND_PROFILING
} } // namespace v8::internal
......@@ -176,50 +176,6 @@ class Log : public AllStatic {
friend class Logger;
friend class LogMessageBuilder;
friend class LogRecordCompressor;
};
// An utility class for performing backward reference compression
// of string ends. It operates using a window of previous strings.
class LogRecordCompressor {
public:
// 'window_size' is the size of backward lookup window.
explicit LogRecordCompressor(int window_size)
: buffer_(window_size + kNoCompressionWindowSize),
kMaxBackwardReferenceSize(
GetBackwardReferenceSize(window_size, Log::kMessageBufferSize)),
curr_(-1), prev_(-1) {
}
~LogRecordCompressor();
// Fills vector with a compressed version of the previous record.
// Returns false if there is no previous record.
bool RetrievePreviousCompressed(Vector<char>* prev_record);
// Stores a record if it differs from a previous one (or there's no previous).
// Returns true, if the record has been stored.
bool Store(const Vector<const char>& record);
private:
// The minimum size of a buffer: a place needed for the current and
// the previous record. Since there is no place for precedessors of a previous
// record, it can't be compressed at all.
static const int kNoCompressionWindowSize = 2;
// Formatting strings for back references.
static const char* kLineBackwardReferenceFormat;
static const char* kBackwardReferenceFormat;
static int GetBackwardReferenceSize(int distance, int pos);
static void PrintBackwardReference(Vector<char> dest, int distance, int pos);
ScopedVector< Vector<const char> > buffer_;
const int kMaxBackwardReferenceSize;
int curr_;
int prev_;
};
......@@ -244,32 +200,14 @@ class LogMessageBuilder BASE_EMBEDDED {
// Append a heap string.
void Append(String* str);
// Appends an address, compressing it if needed by offsetting
// from Logger::last_address_.
// Appends an address.
void AppendAddress(Address addr);
// Appends an address, compressing it if needed.
void AppendAddress(Address addr, Address bias);
void AppendDetailed(String* str, bool show_impl_info);
// Append a portion of a string.
void AppendStringPart(const char* str, int len);
// Stores log message into compressor, returns true if the message
// was stored (i.e. doesn't repeat the previous one).
bool StoreInCompressor(LogRecordCompressor* compressor);
// Sets log message to a previous version of compressed message.
// Returns false, if there is no previous message.
bool RetrieveCompressedPrevious(LogRecordCompressor* compressor) {
return RetrieveCompressedPrevious(compressor, "");
}
// Does the same at the version without arguments, and sets a prefix.
bool RetrieveCompressedPrevious(LogRecordCompressor* compressor,
const char* prefix);
// Write the log message to the log file currently opened.
void WriteToLogFile();
......
This diff is collapsed.
......@@ -74,7 +74,6 @@ class Profiler;
class Semaphore;
class SlidingStateWindow;
class LogMessageBuilder;
class CompressionHelper;
#undef LOG
#ifdef ENABLE_LOGGING_AND_PROFILING
......@@ -88,58 +87,55 @@ class CompressionHelper;
#endif
#define LOG_EVENTS_AND_TAGS_LIST(V) \
V(CODE_CREATION_EVENT, "code-creation", "cc") \
V(CODE_MOVE_EVENT, "code-move", "cm") \
V(CODE_DELETE_EVENT, "code-delete", "cd") \
V(CODE_MOVING_GC, "code-moving-gc", "cg") \
V(FUNCTION_CREATION_EVENT, "function-creation", "fc") \
V(FUNCTION_MOVE_EVENT, "function-move", "fm") \
V(FUNCTION_DELETE_EVENT, "function-delete", "fd") \
V(SNAPSHOT_POSITION_EVENT, "snapshot-pos", "sp") \
V(TICK_EVENT, "tick", "t") \
V(REPEAT_META_EVENT, "repeat", "r") \
V(BUILTIN_TAG, "Builtin", "bi") \
V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak", "cdb") \
V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn", "cdbsi") \
V(CALL_IC_TAG, "CallIC", "cic") \
V(CALL_INITIALIZE_TAG, "CallInitialize", "ci") \
V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic", "cmm") \
V(CALL_MISS_TAG, "CallMiss", "cm") \
V(CALL_NORMAL_TAG, "CallNormal", "cn") \
V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic", "cpm") \
V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak", "kcdb") \
V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \
"KeyedCallDebugPrepareStepIn", \
"kcdbsi") \
V(KEYED_CALL_IC_TAG, "KeyedCallIC", "kcic") \
V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize", "kci") \
V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic", "kcmm") \
V(KEYED_CALL_MISS_TAG, "KeyedCallMiss", "kcm") \
V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal", "kcn") \
V(KEYED_CALL_PRE_MONOMORPHIC_TAG, \
"KeyedCallPreMonomorphic", \
"kcpm") \
V(CALLBACK_TAG, "Callback", "cb") \
V(EVAL_TAG, "Eval", "e") \
V(FUNCTION_TAG, "Function", "f") \
V(KEYED_LOAD_IC_TAG, "KeyedLoadIC", "klic") \
V(KEYED_STORE_IC_TAG, "KeyedStoreIC", "ksic") \
V(LAZY_COMPILE_TAG, "LazyCompile", "lc") \
V(LOAD_IC_TAG, "LoadIC", "lic") \
V(REG_EXP_TAG, "RegExp", "re") \
V(SCRIPT_TAG, "Script", "sc") \
V(STORE_IC_TAG, "StoreIC", "sic") \
V(STUB_TAG, "Stub", "s") \
V(NATIVE_FUNCTION_TAG, "Function", "f") \
V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile", "lc") \
V(NATIVE_SCRIPT_TAG, "Script", "sc")
V(CODE_CREATION_EVENT, "code-creation") \
V(CODE_MOVE_EVENT, "code-move") \
V(CODE_DELETE_EVENT, "code-delete") \
V(CODE_MOVING_GC, "code-moving-gc") \
V(FUNCTION_CREATION_EVENT, "function-creation") \
V(FUNCTION_MOVE_EVENT, "function-move") \
V(FUNCTION_DELETE_EVENT, "function-delete") \
V(SNAPSHOT_POSITION_EVENT, "snapshot-pos") \
V(TICK_EVENT, "tick") \
V(REPEAT_META_EVENT, "repeat") \
V(BUILTIN_TAG, "Builtin") \
V(CALL_DEBUG_BREAK_TAG, "CallDebugBreak") \
V(CALL_DEBUG_PREPARE_STEP_IN_TAG, "CallDebugPrepareStepIn") \
V(CALL_IC_TAG, "CallIC") \
V(CALL_INITIALIZE_TAG, "CallInitialize") \
V(CALL_MEGAMORPHIC_TAG, "CallMegamorphic") \
V(CALL_MISS_TAG, "CallMiss") \
V(CALL_NORMAL_TAG, "CallNormal") \
V(CALL_PRE_MONOMORPHIC_TAG, "CallPreMonomorphic") \
V(KEYED_CALL_DEBUG_BREAK_TAG, "KeyedCallDebugBreak") \
V(KEYED_CALL_DEBUG_PREPARE_STEP_IN_TAG, \
"KeyedCallDebugPrepareStepIn") \
V(KEYED_CALL_IC_TAG, "KeyedCallIC") \
V(KEYED_CALL_INITIALIZE_TAG, "KeyedCallInitialize") \
V(KEYED_CALL_MEGAMORPHIC_TAG, "KeyedCallMegamorphic") \
V(KEYED_CALL_MISS_TAG, "KeyedCallMiss") \
V(KEYED_CALL_NORMAL_TAG, "KeyedCallNormal") \
V(KEYED_CALL_PRE_MONOMORPHIC_TAG, "KeyedCallPreMonomorphic") \
V(CALLBACK_TAG, "Callback") \
V(EVAL_TAG, "Eval") \
V(FUNCTION_TAG, "Function") \
V(KEYED_LOAD_IC_TAG, "KeyedLoadIC") \
V(KEYED_STORE_IC_TAG, "KeyedStoreIC") \
V(LAZY_COMPILE_TAG, "LazyCompile") \
V(LOAD_IC_TAG, "LoadIC") \
V(REG_EXP_TAG, "RegExp") \
V(SCRIPT_TAG, "Script") \
V(STORE_IC_TAG, "StoreIC") \
V(STUB_TAG, "Stub") \
V(NATIVE_FUNCTION_TAG, "Function") \
V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \
V(NATIVE_SCRIPT_TAG, "Script")
// Note that 'NATIVE_' cases for functions and scripts are mapped onto
// original tags when writing to the log.
class Logger {
public:
#define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item,
#define DECLARE_ENUM(enum_item, ignore) enum_item,
enum LogEventsAndTags {
LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM)
NUMBER_OF_LOG_EVENTS
......@@ -292,9 +288,6 @@ class Logger {
private:
// Size of window used for log records compression.
static const int kCompressionWindowSize = 4;
// Emits the profiler's first message.
static void ProfilerBeginEvent();
......@@ -312,9 +305,6 @@ class Logger {
static void DeleteEventInternal(LogEventsAndTags event,
Address from);
// Emits aliases for compressed messages.
static void LogAliases();
// Emits the source code of a regexp. Used by regexp events.
static void LogRegExpSource(Handle<JSRegExp> regexp);
......@@ -357,15 +347,8 @@ class Logger {
// recent VM states.
static SlidingStateWindow* sliding_state_window_;
// An array of log events names.
static const char** log_events_;
// An instance of helper created if log compression is enabled.
static CompressionHelper* compression_helper_;
// Internal implementation classes with access to
// private members.
friend class CompressionHelper;
friend class EventLog;
friend class TimeLog;
friend class Profiler;
......
......@@ -12,7 +12,6 @@
using v8::internal::CStrVector;
using v8::internal::EmbeddedVector;
using v8::internal::LogDynamicBuffer;
using v8::internal::LogRecordCompressor;
using v8::internal::MutableCStrVector;
using v8::internal::ScopedVector;
using v8::internal::Vector;
......@@ -138,173 +137,4 @@ TEST(DynaBufSealing) {
CHECK_EQ(0, ReadData(&dynabuf, 100 + seal_size, &buf));
}
TEST(CompressorStore) {
LogRecordCompressor comp(2);
const Vector<const char> empty = CStrVector("");
CHECK(comp.Store(empty));
CHECK(!comp.Store(empty));
CHECK(!comp.Store(empty));
const Vector<const char> aaa = CStrVector("aaa");
CHECK(comp.Store(aaa));
CHECK(!comp.Store(aaa));
CHECK(!comp.Store(aaa));
CHECK(comp.Store(empty));
CHECK(!comp.Store(empty));
CHECK(!comp.Store(empty));
}
void CheckCompression(LogRecordCompressor* comp,
const Vector<const char>& after) {
EmbeddedVector<char, 100> result;
CHECK(comp->RetrievePreviousCompressed(&result));
CHECK_EQ(after, result);
}
void CheckCompression(LogRecordCompressor* comp,
const char* after) {
CheckCompression(comp, CStrVector(after));
}
TEST(CompressorNonCompressed) {
LogRecordCompressor comp(0);
CHECK(!comp.RetrievePreviousCompressed(NULL));
const Vector<const char> empty = CStrVector("");
CHECK(comp.Store(empty));
CHECK(!comp.RetrievePreviousCompressed(NULL));
const Vector<const char> a_x_20 = CStrVector("aaaaaaaaaaaaaaaaaaaa");
CHECK(comp.Store(a_x_20));
CheckCompression(&comp, empty);
CheckCompression(&comp, empty);
CHECK(comp.Store(empty));
CheckCompression(&comp, a_x_20);
CheckCompression(&comp, a_x_20);
}
TEST(CompressorSingleLine) {
LogRecordCompressor comp(1);
const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
CHECK(comp.Store(string_1));
const Vector<const char> string_2 = CStrVector("fff,ddd,ccc,bbb,aaa");
CHECK(comp.Store(string_2));
// string_1 hasn't been compressed.
CheckCompression(&comp, string_1);
CheckCompression(&comp, string_1);
const Vector<const char> string_3 = CStrVector("hhh,ggg,ccc,bbb,aaa");
CHECK(comp.Store(string_3));
// string_2 compressed using string_1.
CheckCompression(&comp, "fff#1:3");
CheckCompression(&comp, "fff#1:3");
CHECK(!comp.Store(string_3));
// Expecting no changes.
CheckCompression(&comp, "fff#1:3");
CHECK(!comp.Store(string_3));
// Expecting no changes.
CheckCompression(&comp, "fff#1:3");
const Vector<const char> string_4 = CStrVector("iii,hhh,ggg,ccc,bbb,aaa");
CHECK(comp.Store(string_4));
// string_3 compressed using string_2.
CheckCompression(&comp, "hhh,ggg#1:7");
const Vector<const char> string_5 = CStrVector("nnn,mmm,lll,kkk,jjj");
CHECK(comp.Store(string_5));
// string_4 compressed using string_3.
CheckCompression(&comp, "iii,#1");
const Vector<const char> string_6 = CStrVector("nnn,mmmmmm,lll,kkk,jjj");
CHECK(comp.Store(string_6));
// string_5 hasn't been compressed.
CheckCompression(&comp, string_5);
CHECK(comp.Store(string_5));
// string_6 compressed using string_5.
CheckCompression(&comp, "nnn,mmm#1:4");
const Vector<const char> string_7 = CStrVector("nnnnnn,mmm,lll,kkk,jjj");
CHECK(comp.Store(string_7));
// string_5 compressed using string_6.
CheckCompression(&comp, "nnn,#1:7");
const Vector<const char> string_8 = CStrVector("xxn,mmm,lll,kkk,jjj");
CHECK(comp.Store(string_8));
// string_7 compressed using string_5.
CheckCompression(&comp, "nnn#1");
const Vector<const char> string_9 =
CStrVector("aaaaaaaaaaaaa,bbbbbbbbbbbbbbbbb");
CHECK(comp.Store(string_9));
// string_8 compressed using string_7.
CheckCompression(&comp, "xx#1:5");
const Vector<const char> string_10 =
CStrVector("aaaaaaaaaaaaa,cccccccbbbbbbbbbb");
CHECK(comp.Store(string_10));
// string_9 hasn't been compressed.
CheckCompression(&comp, string_9);
CHECK(comp.Store(string_1));
// string_10 compressed using string_9.
CheckCompression(&comp, "aaaaaaaaaaaaa,ccccccc#1:21");
}
TEST(CompressorMultiLines) {
const int kWindowSize = 3;
LogRecordCompressor comp(kWindowSize);
const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
CHECK(comp.Store(string_1));
const Vector<const char> string_2 = CStrVector("iii,hhh,ggg,fff,aaa");
CHECK(comp.Store(string_2));
const Vector<const char> string_3 = CStrVector("mmm,lll,kkk,jjj,aaa");
CHECK(comp.Store(string_3));
const Vector<const char> string_4 = CStrVector("nnn,hhh,ggg,fff,aaa");
CHECK(comp.Store(string_4));
const Vector<const char> string_5 = CStrVector("ooo,lll,kkk,jjj,aaa");
CHECK(comp.Store(string_5));
// string_4 compressed using string_2.
CheckCompression(&comp, "nnn#2:3");
CHECK(comp.Store(string_1));
// string_5 compressed using string_3.
CheckCompression(&comp, "ooo#2:3");
CHECK(comp.Store(string_4));
// string_1 is out of buffer by now, so it shouldn't be compressed.
CHECK_GE(3, kWindowSize);
CheckCompression(&comp, string_1);
CHECK(comp.Store(string_2));
// string_4 compressed using itself.
CheckCompression(&comp, "#3");
}
TEST(CompressorBestSelection) {
LogRecordCompressor comp(3);
const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
CHECK(comp.Store(string_1));
const Vector<const char> string_2 = CStrVector("ddd,ccc,bbb,aaa");
CHECK(comp.Store(string_2));
const Vector<const char> string_3 = CStrVector("fff,eee,ddd,ccc,bbb,aaa");
CHECK(comp.Store(string_3));
// string_2 compressed using string_1.
CheckCompression(&comp, "#1:4");
const Vector<const char> string_4 = CStrVector("nnn,hhh,ggg,fff,aaa");
CHECK(comp.Store(string_4));
// Compressing string_3 using string_1 gives a better compression than
// using string_2.
CheckCompression(&comp, "fff,#2");
}
TEST(CompressorCompressibility) {
LogRecordCompressor comp(2);
const Vector<const char> string_1 = CStrVector("eee,ddd,ccc,bbb,aaa");
CHECK(comp.Store(string_1));
const Vector<const char> string_2 = CStrVector("ccc,bbb,aaa");
CHECK(comp.Store(string_2));
const Vector<const char> string_3 = CStrVector("aaa");
CHECK(comp.Store(string_3));
// string_2 compressed using string_1.
CheckCompression(&comp, "#1:8");
const Vector<const char> string_4 = CStrVector("xxx");
CHECK(comp.Store(string_4));
// string_3 can't be compressed using string_2 --- too short.
CheckCompression(&comp, string_3);
}
#endif // ENABLE_LOGGING_AND_PROFILING
// Copyright 2009 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.
// Load CSV Parser and Log Reader implementations from <project root>/tools.
// Files: tools/csvparser.js tools/logreader.js
(function testAddressParser() {
var reader = new devtools.profiler.LogReader({});
var parser = reader.createAddressParser('test');
// Test that 0x values are parsed, and prevAddresses_ are untouched.
assertFalse('test' in reader.prevAddresses_);
assertEquals(0, parser('0x0'));
assertFalse('test' in reader.prevAddresses_);
assertEquals(0x100, parser('0x100'));
assertFalse('test' in reader.prevAddresses_);
assertEquals(0xffffffff, parser('0xffffffff'));
assertFalse('test' in reader.prevAddresses_);
// Test that values that has no '+' or '-' prefix are parsed
// and saved to prevAddresses_.
assertEquals(0, parser('0'));
assertEquals(0, reader.prevAddresses_.test);
assertEquals(0x100, parser('100'));
assertEquals(0x100, reader.prevAddresses_.test);
assertEquals(0xffffffff, parser('ffffffff'));
assertEquals(0xffffffff, reader.prevAddresses_.test);
// Test that values prefixed with '+' or '-' are treated as deltas,
// and prevAddresses_ is updated.
// Set base value.
assertEquals(0x100, parser('100'));
assertEquals(0x100, reader.prevAddresses_.test);
assertEquals(0x200, parser('+100'));
assertEquals(0x200, reader.prevAddresses_.test);
assertEquals(0x100, parser('-100'));
assertEquals(0x100, reader.prevAddresses_.test);
})();
(function testAddressParser() {
var reader = new devtools.profiler.LogReader({});
assertEquals([0x10000000, 0x10001000, 0xffff000, 0x10000000],
reader.processStack(0x10000000, 0, ['overflow',
'+1000', '-2000', '+1000']));
})();
(function testExpandBackRef() {
var reader = new devtools.profiler.LogReader({});
assertEquals('aaaaaaaa', reader.expandBackRef_('aaaaaaaa'));
assertEquals('aaaaaaaa', reader.expandBackRef_('#1'));
assertEquals('bbbbaaaa', reader.expandBackRef_('bbbb#2:4'));
assertEquals('"#1:1"', reader.expandBackRef_('"#1:1"'));
})();
......@@ -46,36 +46,6 @@ devtools.profiler.LogReader = function(dispatchTable) {
* @type {Array.<Object>}
*/
this.dispatchTable_ = dispatchTable;
this.dispatchTable_['alias'] =
{ parsers: [null, null], processor: this.processAlias_ };
this.dispatchTable_['repeat'] =
{ parsers: [parseInt, 'var-args'], processor: this.processRepeat_,
backrefs: true };
/**
* A key-value map for aliases. Translates short name -> full name.
* @type {Object}
*/
this.aliases_ = {};
/**
* A key-value map for previous address values.
* @type {Object}
*/
this.prevAddresses_ = {};
/**
* A key-value map for events than can be backreference-compressed.
* @type {Object}
*/
this.backRefsCommands_ = {};
this.initBackRefsCommands_();
/**
* Back references for decompression.
* @type {Array.<string>}
*/
this.backRefs_ = [];
/**
* Current line.
......@@ -91,42 +61,6 @@ devtools.profiler.LogReader = function(dispatchTable) {
};
/**
* Creates a parser for an address entry.
*
* @param {string} addressTag Address tag to perform offset decoding.
* @return {function(string):number} Address parser.
*/
devtools.profiler.LogReader.prototype.createAddressParser = function(
addressTag) {
var self = this;
return (function (str) {
var value = parseInt(str, 16);
var firstChar = str.charAt(0);
if (firstChar == '+' || firstChar == '-') {
var addr = self.prevAddresses_[addressTag];
addr += value;
self.prevAddresses_[addressTag] = addr;
return addr;
} else if (firstChar != '0' || str.charAt(1) != 'x') {
self.prevAddresses_[addressTag] = value;
}
return value;
});
};
/**
* Expands an alias symbol, if applicable.
*
* @param {string} symbol Symbol to expand.
* @return {string} Expanded symbol, or the input symbol itself.
*/
devtools.profiler.LogReader.prototype.expandAlias = function(symbol) {
return symbol in this.aliases_ ? this.aliases_[symbol] : symbol;
};
/**
* Used for printing error messages.
*
......@@ -233,68 +167,6 @@ devtools.profiler.LogReader.prototype.dispatchLogRow_ = function(fields) {
};
/**
* Decompresses a line if it was backreference-compressed.
*
* @param {string} line Possibly compressed line.
* @return {string} Decompressed line.
* @private
*/
devtools.profiler.LogReader.prototype.expandBackRef_ = function(line) {
var backRefPos;
// Filter out case when a regexp is created containing '#'.
if (line.charAt(line.length - 1) != '"'
&& (backRefPos = line.lastIndexOf('#')) != -1) {
var backRef = line.substr(backRefPos + 1);
var backRefIdx = parseInt(backRef, 10) - 1;
var colonPos = backRef.indexOf(':');
var backRefStart =
colonPos != -1 ? parseInt(backRef.substr(colonPos + 1), 10) : 0;
line = line.substr(0, backRefPos) +
this.backRefs_[backRefIdx].substr(backRefStart);
}
this.backRefs_.unshift(line);
if (this.backRefs_.length > 10) {
this.backRefs_.length = 10;
}
return line;
};
/**
* Initializes the map of backward reference compressible commands.
* @private
*/
devtools.profiler.LogReader.prototype.initBackRefsCommands_ = function() {
for (var event in this.dispatchTable_) {
var dispatch = this.dispatchTable_[event];
if (dispatch && dispatch.backrefs) {
this.backRefsCommands_[event] = true;
}
}
};
/**
* Processes alias log record. Adds an alias to a corresponding map.
*
* @param {string} symbol Short name.
* @param {string} expansion Long name.
* @private
*/
devtools.profiler.LogReader.prototype.processAlias_ = function(
symbol, expansion) {
if (expansion in this.dispatchTable_) {
this.dispatchTable_[symbol] = this.dispatchTable_[expansion];
if (expansion in this.backRefsCommands_) {
this.backRefsCommands_[symbol] = true;
}
} else {
this.aliases_[symbol] = expansion;
}
};
/**
* Processes log lines.
*
......@@ -308,10 +180,6 @@ devtools.profiler.LogReader.prototype.processLog_ = function(lines) {
continue;
}
try {
if (line.charAt(0) == '#' ||
line.substr(0, line.indexOf(',')) in this.backRefsCommands_) {
line = this.expandBackRef_(line);
}
var fields = this.csvParser_.parseLine(line);
this.dispatchLogRow_(fields);
} catch (e) {
......@@ -319,20 +187,3 @@ devtools.profiler.LogReader.prototype.processLog_ = function(lines) {
}
}
};
/**
* Processes repeat log record. Expands it according to calls count and
* invokes processing.
*
* @param {number} count Count.
* @param {Array.<string>} cmd Parsed command.
* @private
*/
devtools.profiler.LogReader.prototype.processRepeat_ = function(count, cmd) {
// Replace the repeat-prefixed command from backrefs list with a non-prefixed.
this.backRefs_[0] = cmd.join(',');
for (var i = 0; i < count; ++i) {
this.dispatchLogRow_(cmd);
}
};
......@@ -60,18 +60,17 @@ function inherits(childCtor, parentCtor) {
function SnapshotLogProcessor() {
devtools.profiler.LogReader.call(this, {
'code-creation': {
parsers: [null, this.createAddressParser('code'), parseInt, null],
processor: this.processCodeCreation, backrefs: true },
'code-move': { parsers: [this.createAddressParser('code'),
this.createAddressParser('code-move-to')],
processor: this.processCodeMove, backrefs: true },
'code-delete': { parsers: [this.createAddressParser('code')],
processor: this.processCodeDelete, backrefs: true },
parsers: [null, parseInt, parseInt, null],
processor: this.processCodeCreation },
'code-move': { parsers: [parseInt, parseInt],
processor: this.processCodeMove },
'code-delete': { parsers: [parseInt],
processor: this.processCodeDelete },
'function-creation': null,
'function-move': null,
'function-delete': null,
'snapshot-pos': { parsers: [this.createAddressParser('code'), parseInt],
processor: this.processSnapshotPosition, backrefs: true }});
'snapshot-pos': { parsers: [parseInt, parseInt],
processor: this.processSnapshotPosition }});
Profile.prototype.handleUnknownCode = function(operation, addr) {
var op = devtools.profiler.Profile.Operation;
......@@ -95,8 +94,7 @@ inherits(SnapshotLogProcessor, devtools.profiler.LogReader);
SnapshotLogProcessor.prototype.processCodeCreation = function(
type, start, size, name) {
var entry = this.profile_.addCode(
this.expandAlias(type), name, start, size);
var entry = this.profile_.addCode(type, name, start, size);
};
......@@ -133,33 +131,28 @@ function TickProcessor(
'shared-library': { parsers: [null, parseInt, parseInt],
processor: this.processSharedLibrary },
'code-creation': {
parsers: [null, this.createAddressParser('code'), parseInt, null],
processor: this.processCodeCreation, backrefs: true },
'code-move': { parsers: [this.createAddressParser('code'),
this.createAddressParser('code-move-to')],
processor: this.processCodeMove, backrefs: true },
'code-delete': { parsers: [this.createAddressParser('code')],
processor: this.processCodeDelete, backrefs: true },
'function-creation': { parsers: [this.createAddressParser('code'),
this.createAddressParser('function-obj')],
processor: this.processFunctionCreation, backrefs: true },
'function-move': { parsers: [this.createAddressParser('code'),
this.createAddressParser('code-move-to')],
processor: this.processFunctionMove, backrefs: true },
'function-delete': { parsers: [this.createAddressParser('code')],
processor: this.processFunctionDelete, backrefs: true },
'snapshot-pos': { parsers: [this.createAddressParser('code'), parseInt],
processor: this.processSnapshotPosition, backrefs: true },
'tick': { parsers: [this.createAddressParser('code'),
this.createAddressParser('stack'),
this.createAddressParser('func'), parseInt, 'var-args'],
processor: this.processTick, backrefs: true },
parsers: [null, parseInt, parseInt, null],
processor: this.processCodeCreation },
'code-move': { parsers: [parseInt, parseInt],
processor: this.processCodeMove },
'code-delete': { parsers: [parseInt],
processor: this.processCodeDelete },
'function-creation': { parsers: [parseInt, parseInt],
processor: this.processFunctionCreation },
'function-move': { parsers: [parseInt, parseInt],
processor: this.processFunctionMove },
'function-delete': { parsers: [parseInt],
processor: this.processFunctionDelete },
'snapshot-pos': { parsers: [parseInt, parseInt],
processor: this.processSnapshotPosition },
'tick': { parsers: [parseInt, parseInt, parseInt, parseInt, 'var-args'],
processor: this.processTick },
'heap-sample-begin': { parsers: [null, null, parseInt],
processor: this.processHeapSampleBegin },
'heap-sample-end': { parsers: [null, null],
processor: this.processHeapSampleEnd },
'heap-js-prod-item': { parsers: [null, 'var-args'],
processor: this.processJSProducer, backrefs: true },
processor: this.processJSProducer },
// Ignored events.
'profiler': null,
'heap-sample-stats': null,
......@@ -294,8 +287,7 @@ TickProcessor.prototype.processSharedLibrary = function(
TickProcessor.prototype.processCodeCreation = function(
type, start, size, name) {
name = this.deserializedEntriesNames_[start] || name;
var entry = this.profile_.addCode(
this.expandAlias(type), name, start, size);
var entry = this.profile_.addCode(type, name, start, size);
};
......
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