| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 | 120 |
| 121 | 121 |
| 122 bool Log::is_stopped_ = false; | 122 bool Log::is_stopped_ = false; |
| 123 Log::WritePtr Log::Write = NULL; | 123 Log::WritePtr Log::Write = NULL; |
| 124 FILE* Log::output_handle_ = NULL; | 124 FILE* Log::output_handle_ = NULL; |
| 125 LogDynamicBuffer* Log::output_buffer_ = NULL; | 125 LogDynamicBuffer* Log::output_buffer_ = NULL; |
| 126 // Must be the same message as in Logger::PauseProfiler. | 126 // Must be the same message as in Logger::PauseProfiler. |
| 127 const char* Log::kDynamicBufferSeal = "profiler,\"pause\"\n"; | 127 const char* Log::kDynamicBufferSeal = "profiler,\"pause\"\n"; |
| 128 Mutex* Log::mutex_ = NULL; | 128 Mutex* Log::mutex_ = NULL; |
| 129 char* Log::message_buffer_ = NULL; | 129 char* Log::message_buffer_ = NULL; |
| 130 LogRecordCompressor* Log::record_compressor_ = NULL; | |
| 131 // Must be the same as compressed tick event name from Logger. | |
| 132 const char* Log::kCompressedTickEventName = "t,"; | |
| 133 | 130 |
| 134 | 131 |
| 135 void Log::Init() { | 132 void Log::Init() { |
| 136 mutex_ = OS::CreateMutex(); | 133 mutex_ = OS::CreateMutex(); |
| 137 message_buffer_ = NewArray<char>(kMessageBufferSize); | 134 message_buffer_ = NewArray<char>(kMessageBufferSize); |
| 138 if (FLAG_compress_log) { | |
| 139 record_compressor_ = new LogRecordCompressor( | |
| 140 kRecordCompressorWindow, strlen(kCompressedTickEventName)); | |
| 141 } | |
| 142 } | 135 } |
| 143 | 136 |
| 144 | 137 |
| 145 void Log::OpenStdout() { | 138 void Log::OpenStdout() { |
| 146 ASSERT(!IsEnabled()); | 139 ASSERT(!IsEnabled()); |
| 147 output_handle_ = stdout; | 140 output_handle_ = stdout; |
| 148 Write = WriteToFile; | 141 Write = WriteToFile; |
| 149 Init(); | 142 Init(); |
| 150 } | 143 } |
| 151 | 144 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 173 fclose(output_handle_); | 166 fclose(output_handle_); |
| 174 output_handle_ = NULL; | 167 output_handle_ = NULL; |
| 175 } else if (Write == WriteToMemory) { | 168 } else if (Write == WriteToMemory) { |
| 176 delete output_buffer_; | 169 delete output_buffer_; |
| 177 output_buffer_ = NULL; | 170 output_buffer_ = NULL; |
| 178 } else { | 171 } else { |
| 179 ASSERT(Write == NULL); | 172 ASSERT(Write == NULL); |
| 180 } | 173 } |
| 181 Write = NULL; | 174 Write = NULL; |
| 182 | 175 |
| 183 delete record_compressor_; | |
| 184 record_compressor_ = NULL; | |
| 185 | |
| 186 DeleteArray(message_buffer_); | 176 DeleteArray(message_buffer_); |
| 187 message_buffer_ = NULL; | 177 message_buffer_ = NULL; |
| 188 | 178 |
| 189 delete mutex_; | 179 delete mutex_; |
| 190 mutex_ = NULL; | 180 mutex_ = NULL; |
| 191 | 181 |
| 192 is_stopped_ = false; | 182 is_stopped_ = false; |
| 193 } | 183 } |
| 194 | 184 |
| 195 | 185 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 | 246 |
| 257 void LogMessageBuilder::Append(String* str) { | 247 void LogMessageBuilder::Append(String* str) { |
| 258 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. | 248 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
| 259 int length = str->length(); | 249 int length = str->length(); |
| 260 for (int i = 0; i < length; i++) { | 250 for (int i = 0; i < length; i++) { |
| 261 Append(static_cast<char>(str->Get(i))); | 251 Append(static_cast<char>(str->Get(i))); |
| 262 } | 252 } |
| 263 } | 253 } |
| 264 | 254 |
| 265 | 255 |
| 256 void LogMessageBuilder::AppendAddress(Address addr) { |
| 257 static Address last_address_ = NULL; |
| 258 AppendAddress(addr, last_address_); |
| 259 last_address_ = addr; |
| 260 } |
| 261 |
| 262 |
| 263 void LogMessageBuilder::AppendAddress(Address addr, Address bias) { |
| 264 if (!FLAG_compress_log || bias == NULL) { |
| 265 Append("0x%" V8PRIxPTR, addr); |
| 266 } else { |
| 267 intptr_t delta = addr - bias; |
| 268 // To avoid printing negative offsets in an unsigned form, |
| 269 // we are printing an absolute value with a sign. |
| 270 const char sign = delta >= 0 ? '+' : '-'; |
| 271 if (sign == '-') { delta = -delta; } |
| 272 Append("%c%" V8PRIxPTR, sign, delta); |
| 273 } |
| 274 } |
| 275 |
| 276 |
| 266 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { | 277 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { |
| 267 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. | 278 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
| 268 int len = str->length(); | 279 int len = str->length(); |
| 269 if (len > 0x1000) | 280 if (len > 0x1000) |
| 270 len = 0x1000; | 281 len = 0x1000; |
| 271 if (show_impl_info) { | 282 if (show_impl_info) { |
| 272 Append(str->IsAsciiRepresentation() ? 'a' : '2'); | 283 Append(str->IsAsciiRepresentation() ? 'a' : '2'); |
| 273 if (StringShape(str).IsExternal()) | 284 if (StringShape(str).IsExternal()) |
| 274 Append('e'); | 285 Append('e'); |
| 275 if (StringShape(str).IsSymbol()) | 286 if (StringShape(str).IsSymbol()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 286 Append("\\,"); | 297 Append("\\,"); |
| 287 } else if (c == '\\') { | 298 } else if (c == '\\') { |
| 288 Append("\\\\"); | 299 Append("\\\\"); |
| 289 } else { | 300 } else { |
| 290 Append("%lc", c); | 301 Append("%lc", c); |
| 291 } | 302 } |
| 292 } | 303 } |
| 293 } | 304 } |
| 294 | 305 |
| 295 | 306 |
| 296 bool LogMessageBuilder::StoreInCompressor() { | 307 bool LogMessageBuilder::StoreInCompressor(LogRecordCompressor* compressor) { |
| 297 if (!FLAG_compress_log) return true; | 308 return compressor->Store(Vector<const char>(Log::message_buffer_, pos_)); |
| 298 ASSERT(Log::record_compressor_ != NULL); | |
| 299 return Log::record_compressor_->Store( | |
| 300 Vector<const char>(Log::message_buffer_, pos_)); | |
| 301 } | 309 } |
| 302 | 310 |
| 303 | 311 |
| 304 bool LogMessageBuilder::RetrieveCompressedPrevious(const char* prefix) { | 312 bool LogMessageBuilder::RetrieveCompressedPrevious( |
| 305 if (!FLAG_compress_log) return true; | 313 LogRecordCompressor* compressor, const char* prefix) { |
| 306 ASSERT(Log::record_compressor_ != NULL); | |
| 307 pos_ = 0; | 314 pos_ = 0; |
| 308 if (prefix[0] != '\0') Append(prefix); | 315 if (prefix[0] != '\0') Append(prefix); |
| 309 Vector<char> prev_record(Log::message_buffer_ + pos_, | 316 Vector<char> prev_record(Log::message_buffer_ + pos_, |
| 310 Log::kMessageBufferSize - pos_); | 317 Log::kMessageBufferSize - pos_); |
| 311 const bool has_previous = | 318 const bool has_prev = compressor->RetrievePreviousCompressed(&prev_record); |
| 312 Log::record_compressor_->RetrievePreviousCompressed(&prev_record); | 319 if (!has_prev) return false; |
| 313 if (!has_previous) return false; | |
| 314 pos_ += prev_record.length(); | 320 pos_ += prev_record.length(); |
| 315 return true; | 321 return true; |
| 316 } | 322 } |
| 317 | 323 |
| 318 | 324 |
| 319 void LogMessageBuilder::WriteToLogFile() { | 325 void LogMessageBuilder::WriteToLogFile() { |
| 320 ASSERT(pos_ <= Log::kMessageBufferSize); | 326 ASSERT(pos_ <= Log::kMessageBufferSize); |
| 321 const int written = Log::Write(Log::message_buffer_, pos_); | 327 const int written = Log::Write(Log::message_buffer_, pos_); |
| 322 if (written != pos_ && write_failure_handler != NULL) { | 328 if (written != pos_ && write_failure_handler != NULL) { |
| 323 write_failure_handler(); | 329 write_failure_handler(); |
| 324 } | 330 } |
| 325 } | 331 } |
| 326 | 332 |
| 327 | 333 |
| 328 void LogMessageBuilder::WriteCStringToLogFile(const char* str) { | 334 void LogMessageBuilder::WriteCStringToLogFile(const char* str) { |
| 329 const int len = strlen(str); | 335 const int len = strlen(str); |
| 330 const int written = Log::Write(str, len); | 336 const int written = Log::Write(str, len); |
| 331 if (written != len && write_failure_handler != NULL) { | 337 if (written != len && write_failure_handler != NULL) { |
| 332 write_failure_handler(); | 338 write_failure_handler(); |
| 333 } | 339 } |
| 334 } | 340 } |
| 335 | 341 |
| 336 | 342 |
| 343 // Formatting string for back references to the whole line. E.g. "#2" means |
| 344 // "the second line above". |
| 345 const char* LogRecordCompressor::kLineBackwardReferenceFormat = "#%d"; |
| 346 |
| 337 // Formatting string for back references. E.g. "#2:10" means | 347 // Formatting string for back references. E.g. "#2:10" means |
| 338 // "the second line above, start from char 10 (0-based)". | 348 // "the second line above, start from char 10 (0-based)". |
| 339 const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d"; | 349 const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d"; |
| 340 | 350 |
| 341 | 351 |
| 342 LogRecordCompressor::~LogRecordCompressor() { | 352 LogRecordCompressor::~LogRecordCompressor() { |
| 343 for (int i = 0; i < buffer_.length(); ++i) { | 353 for (int i = 0; i < buffer_.length(); ++i) { |
| 344 buffer_[i].Dispose(); | 354 buffer_[i].Dispose(); |
| 345 } | 355 } |
| 346 } | 356 } |
| 347 | 357 |
| 348 | 358 |
| 359 static int GetNumberLength(int number) { |
| 360 ASSERT(number >= 0); |
| 361 ASSERT(number < 10000); |
| 362 if (number < 10) return 1; |
| 363 if (number < 100) return 2; |
| 364 if (number < 1000) return 3; |
| 365 return 4; |
| 366 } |
| 367 |
| 368 |
| 369 int LogRecordCompressor::GetBackwardReferenceSize(int distance, int pos) { |
| 370 // See kLineBackwardReferenceFormat and kBackwardReferenceFormat. |
| 371 return pos == 0 ? GetNumberLength(distance) + 1 |
| 372 : GetNumberLength(distance) + GetNumberLength(pos) + 2; |
| 373 } |
| 374 |
| 375 |
| 376 void LogRecordCompressor::PrintBackwardReference(Vector<char> dest, |
| 377 int distance, |
| 378 int pos) { |
| 379 if (pos == 0) { |
| 380 OS::SNPrintF(dest, kLineBackwardReferenceFormat, distance); |
| 381 } else { |
| 382 OS::SNPrintF(dest, kBackwardReferenceFormat, distance, pos); |
| 383 } |
| 384 } |
| 385 |
| 386 |
| 349 bool LogRecordCompressor::Store(const Vector<const char>& record) { | 387 bool LogRecordCompressor::Store(const Vector<const char>& record) { |
| 350 // Check if the record is the same as the last stored one. | 388 // Check if the record is the same as the last stored one. |
| 351 if (curr_ != -1) { | 389 if (curr_ != -1) { |
| 352 Vector<const char>& curr = buffer_[curr_]; | 390 Vector<const char>& curr = buffer_[curr_]; |
| 353 if (record.length() == curr.length() | 391 if (record.length() == curr.length() |
| 354 && strncmp(record.start(), curr.start(), record.length()) == 0) { | 392 && strncmp(record.start(), curr.start(), record.length()) == 0) { |
| 355 return false; | 393 return false; |
| 356 } | 394 } |
| 357 } | 395 } |
| 358 // buffer_ is circular. | 396 // buffer_ is circular. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 372 if (prev_ == -1) return false; | 410 if (prev_ == -1) return false; |
| 373 | 411 |
| 374 int index = prev_; | 412 int index = prev_; |
| 375 // Distance from prev_. | 413 // Distance from prev_. |
| 376 int distance = 0; | 414 int distance = 0; |
| 377 // Best compression result among records in the buffer. | 415 // Best compression result among records in the buffer. |
| 378 struct { | 416 struct { |
| 379 intptr_t truncated_len; | 417 intptr_t truncated_len; |
| 380 int distance; | 418 int distance; |
| 381 int copy_from_pos; | 419 int copy_from_pos; |
| 382 } best = {-1, 0, 0}; | 420 int backref_size; |
| 421 } best = {-1, 0, 0, 0}; |
| 383 Vector<const char>& prev = buffer_[prev_]; | 422 Vector<const char>& prev = buffer_[prev_]; |
| 384 const char* const prev_start = prev.start() + start_pos_; | 423 const char* const prev_start = prev.start(); |
| 385 const char* const prev_end = prev.start() + prev.length(); | 424 const char* const prev_end = prev.start() + prev.length(); |
| 386 do { | 425 do { |
| 387 // We're moving backwards until we reach the current record. | 426 // We're moving backwards until we reach the current record. |
| 388 // Remember that buffer_ is circular. | 427 // Remember that buffer_ is circular. |
| 389 if (--index == -1) index = buffer_.length() - 1; | 428 if (--index == -1) index = buffer_.length() - 1; |
| 390 ++distance; | 429 ++distance; |
| 391 if (index == curr_) break; | 430 if (index == curr_) break; |
| 392 | 431 |
| 393 Vector<const char>& data = buffer_[index]; | 432 Vector<const char>& data = buffer_[index]; |
| 394 if (data.start() == NULL) break; | 433 if (data.start() == NULL) break; |
| 395 const char* const data_end = data.start() + data.length(); | 434 const char* const data_end = data.start() + data.length(); |
| 396 const char* prev_ptr = prev_end; | 435 const char* prev_ptr = prev_end; |
| 397 const char* data_ptr = data_end; | 436 const char* data_ptr = data_end; |
| 398 // Compare strings backwards, stop on the last matching character. | 437 // Compare strings backwards, stop on the last matching character. |
| 399 while (prev_ptr != prev_start && data_ptr != data.start() | 438 while (prev_ptr != prev_start && data_ptr != data.start() |
| 400 && *(prev_ptr - 1) == *(data_ptr - 1)) { | 439 && *(prev_ptr - 1) == *(data_ptr - 1)) { |
| 401 --prev_ptr; | 440 --prev_ptr; |
| 402 --data_ptr; | 441 --data_ptr; |
| 403 } | 442 } |
| 404 const intptr_t truncated_len = prev_end - prev_ptr; | 443 const intptr_t truncated_len = prev_end - prev_ptr; |
| 405 if (truncated_len < kUncompressibleBound) continue; | 444 const int copy_from_pos = data_ptr - data.start(); |
| 445 // Check if the length of compressed tail is enough. |
| 446 if (truncated_len <= kMaxBackwardReferenceSize |
| 447 && truncated_len <= GetBackwardReferenceSize(distance, copy_from_pos)) { |
| 448 continue; |
| 449 } |
| 406 | 450 |
| 407 // Record compression results. | 451 // Record compression results. |
| 408 if (truncated_len > best.truncated_len) { | 452 if (truncated_len > best.truncated_len) { |
| 409 best.truncated_len = truncated_len; | 453 best.truncated_len = truncated_len; |
| 410 best.distance = distance; | 454 best.distance = distance; |
| 411 best.copy_from_pos = data_ptr - data.start(); | 455 best.copy_from_pos = copy_from_pos; |
| 456 best.backref_size = GetBackwardReferenceSize(distance, copy_from_pos); |
| 412 } | 457 } |
| 413 } while (true); | 458 } while (true); |
| 414 | 459 |
| 415 if (best.distance == 0) { | 460 if (best.distance == 0) { |
| 416 // Can't compress the previous record. Return as is. | 461 // Can't compress the previous record. Return as is. |
| 417 ASSERT(prev_record->length() >= prev.length()); | 462 ASSERT(prev_record->length() >= prev.length()); |
| 418 memcpy(prev_record->start(), prev.start(), prev.length()); | 463 memcpy(prev_record->start(), prev.start(), prev.length()); |
| 419 prev_record->Truncate(prev.length()); | 464 prev_record->Truncate(prev.length()); |
| 420 } else { | 465 } else { |
| 421 // Copy the uncompressible part unchanged. | 466 // Copy the uncompressible part unchanged. |
| 422 const intptr_t unchanged_len = prev.length() - best.truncated_len; | 467 const intptr_t unchanged_len = prev.length() - best.truncated_len; |
| 423 ASSERT(prev_record->length() >= unchanged_len + kUncompressibleBound); | 468 // + 1 for '\0'. |
| 469 ASSERT(prev_record->length() >= unchanged_len + best.backref_size + 1); |
| 424 memcpy(prev_record->start(), prev.start(), unchanged_len); | 470 memcpy(prev_record->start(), prev.start(), unchanged_len); |
| 425 // Append the backward reference. | 471 // Append the backward reference. |
| 426 Vector<char> patch(prev_record->start() + unchanged_len, | 472 Vector<char> backref( |
| 427 kUncompressibleBound); | 473 prev_record->start() + unchanged_len, best.backref_size + 1); |
| 428 OS::SNPrintF(patch, kBackwardReferenceFormat, | 474 PrintBackwardReference(backref, best.distance, best.copy_from_pos); |
| 429 best.distance, best.copy_from_pos); | 475 ASSERT(strlen(backref.start()) - best.backref_size == 0); |
| 430 prev_record->Truncate(unchanged_len + strlen(patch.start())); | 476 prev_record->Truncate(unchanged_len + best.backref_size); |
| 431 } | 477 } |
| 432 return true; | 478 return true; |
| 433 } | 479 } |
| 434 | 480 |
| 435 #endif // ENABLE_LOGGING_AND_PROFILING | 481 #endif // ENABLE_LOGGING_AND_PROFILING |
| 436 | 482 |
| 437 } } // namespace v8::internal | 483 } } // namespace v8::internal |
| OLD | NEW |