| 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 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 void LogMessageBuilder::Append(String* str) { | 349 void LogMessageBuilder::Append(String* str) { |
| 350 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. | 350 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
| 351 int length = str->length(); | 351 int length = str->length(); |
| 352 for (int i = 0; i < length; i++) { | 352 for (int i = 0; i < length; i++) { |
| 353 Append(static_cast<char>(str->Get(i))); | 353 Append(static_cast<char>(str->Get(i))); |
| 354 } | 354 } |
| 355 } | 355 } |
| 356 | 356 |
| 357 | 357 |
| 358 void LogMessageBuilder::AppendAddress(Address addr) { | 358 void LogMessageBuilder::AppendAddress(Address addr) { |
| 359 AppendAddress(addr, log_->logger_->last_address_); | 359 Append("0x%" V8PRIxPTR, addr); |
| 360 log_->logger_->last_address_ = addr; | |
| 361 } | |
| 362 | |
| 363 | |
| 364 void LogMessageBuilder::AppendAddress(Address addr, Address bias) { | |
| 365 if (!FLAG_compress_log) { | |
| 366 Append("0x%" V8PRIxPTR, addr); | |
| 367 } else if (bias == NULL) { | |
| 368 Append("%" V8PRIxPTR, addr); | |
| 369 } else { | |
| 370 uintptr_t delta; | |
| 371 char sign; | |
| 372 if (addr >= bias) { | |
| 373 delta = addr - bias; | |
| 374 sign = '+'; | |
| 375 } else { | |
| 376 delta = bias - addr; | |
| 377 sign = '-'; | |
| 378 } | |
| 379 Append("%c%" V8PRIxPTR, sign, delta); | |
| 380 } | |
| 381 } | 360 } |
| 382 | 361 |
| 383 | 362 |
| 384 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { | 363 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { |
| 385 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. | 364 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
| 386 int len = str->length(); | 365 int len = str->length(); |
| 387 if (len > 0x1000) | 366 if (len > 0x1000) |
| 388 len = 0x1000; | 367 len = 0x1000; |
| 389 if (show_impl_info) { | 368 if (show_impl_info) { |
| 390 Append(str->IsAsciiRepresentation() ? 'a' : '2'); | 369 Append(str->IsAsciiRepresentation() ? 'a' : '2'); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 418 if (len == 0) return; | 397 if (len == 0) return; |
| 419 } | 398 } |
| 420 Vector<char> buf(log_->message_buffer_ + pos_, | 399 Vector<char> buf(log_->message_buffer_ + pos_, |
| 421 Log::kMessageBufferSize - pos_); | 400 Log::kMessageBufferSize - pos_); |
| 422 OS::StrNCpy(buf, str, len); | 401 OS::StrNCpy(buf, str, len); |
| 423 pos_ += len; | 402 pos_ += len; |
| 424 ASSERT(pos_ <= Log::kMessageBufferSize); | 403 ASSERT(pos_ <= Log::kMessageBufferSize); |
| 425 } | 404 } |
| 426 | 405 |
| 427 | 406 |
| 428 bool LogMessageBuilder::StoreInCompressor(LogRecordCompressor* compressor) { | |
| 429 return compressor->Store(Vector<const char>(log_->message_buffer_, pos_)); | |
| 430 } | |
| 431 | |
| 432 | |
| 433 bool LogMessageBuilder::RetrieveCompressedPrevious( | |
| 434 LogRecordCompressor* compressor, const char* prefix) { | |
| 435 pos_ = 0; | |
| 436 if (prefix[0] != '\0') Append(prefix); | |
| 437 Vector<char> prev_record(log_->message_buffer_ + pos_, | |
| 438 Log::kMessageBufferSize - pos_); | |
| 439 const bool has_prev = compressor->RetrievePreviousCompressed(&prev_record); | |
| 440 if (!has_prev) return false; | |
| 441 pos_ += prev_record.length(); | |
| 442 return true; | |
| 443 } | |
| 444 | |
| 445 | |
| 446 void LogMessageBuilder::WriteToLogFile() { | 407 void LogMessageBuilder::WriteToLogFile() { |
| 447 ASSERT(pos_ <= Log::kMessageBufferSize); | 408 ASSERT(pos_ <= Log::kMessageBufferSize); |
| 448 const int written = log_->write_to_file_ ? | 409 const int written = log_->write_to_file_ ? |
| 449 log_->WriteToFile(log_->message_buffer_, pos_) : | 410 log_->WriteToFile(log_->message_buffer_, pos_) : |
| 450 log_->WriteToMemory(log_->message_buffer_, pos_); | 411 log_->WriteToMemory(log_->message_buffer_, pos_); |
| 451 if (written != pos_) { | 412 if (written != pos_) { |
| 452 log_->stop(); | 413 log_->stop(); |
| 453 log_->logger_->LogFailure(); | 414 log_->logger_->LogFailure(); |
| 454 } | 415 } |
| 455 } | 416 } |
| 456 | 417 |
| 457 | 418 |
| 458 // Formatting string for back references to the whole line. E.g. "#2" means | |
| 459 // "the second line above". | |
| 460 const char* const LogRecordCompressor::kLineBackwardReferenceFormat = "#%d"; | |
| 461 | |
| 462 // Formatting string for back references. E.g. "#2:10" means | |
| 463 // "the second line above, start from char 10 (0-based)". | |
| 464 const char* const LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d"; | |
| 465 | |
| 466 | |
| 467 LogRecordCompressor::~LogRecordCompressor() { | |
| 468 for (int i = 0; i < buffer_.length(); ++i) { | |
| 469 buffer_[i].Dispose(); | |
| 470 } | |
| 471 } | |
| 472 | |
| 473 | |
| 474 static int GetNumberLength(int number) { | |
| 475 ASSERT(number >= 0); | |
| 476 ASSERT(number < 10000); | |
| 477 if (number < 10) return 1; | |
| 478 if (number < 100) return 2; | |
| 479 if (number < 1000) return 3; | |
| 480 return 4; | |
| 481 } | |
| 482 | |
| 483 | |
| 484 int LogRecordCompressor::GetBackwardReferenceSize(int distance, int pos) { | |
| 485 // See kLineBackwardReferenceFormat and kBackwardReferenceFormat. | |
| 486 return pos == 0 ? GetNumberLength(distance) + 1 | |
| 487 : GetNumberLength(distance) + GetNumberLength(pos) + 2; | |
| 488 } | |
| 489 | |
| 490 | |
| 491 void LogRecordCompressor::PrintBackwardReference(Vector<char> dest, | |
| 492 int distance, | |
| 493 int pos) { | |
| 494 if (pos == 0) { | |
| 495 OS::SNPrintF(dest, kLineBackwardReferenceFormat, distance); | |
| 496 } else { | |
| 497 OS::SNPrintF(dest, kBackwardReferenceFormat, distance, pos); | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 | |
| 502 bool LogRecordCompressor::Store(const Vector<const char>& record) { | |
| 503 // Check if the record is the same as the last stored one. | |
| 504 if (curr_ != -1) { | |
| 505 Vector<const char>& curr = buffer_[curr_]; | |
| 506 if (record.length() == curr.length() | |
| 507 && strncmp(record.start(), curr.start(), record.length()) == 0) { | |
| 508 return false; | |
| 509 } | |
| 510 } | |
| 511 // buffer_ is circular. | |
| 512 prev_ = curr_++; | |
| 513 curr_ %= buffer_.length(); | |
| 514 Vector<char> record_copy = Vector<char>::New(record.length()); | |
| 515 memcpy(record_copy.start(), record.start(), record.length()); | |
| 516 buffer_[curr_].Dispose(); | |
| 517 buffer_[curr_] = | |
| 518 Vector<const char>(record_copy.start(), record_copy.length()); | |
| 519 return true; | |
| 520 } | |
| 521 | |
| 522 | |
| 523 bool LogRecordCompressor::RetrievePreviousCompressed( | |
| 524 Vector<char>* prev_record) { | |
| 525 if (prev_ == -1) return false; | |
| 526 | |
| 527 int index = prev_; | |
| 528 // Distance from prev_. | |
| 529 int distance = 0; | |
| 530 // Best compression result among records in the buffer. | |
| 531 struct { | |
| 532 intptr_t truncated_len; | |
| 533 int distance; | |
| 534 int copy_from_pos; | |
| 535 int backref_size; | |
| 536 } best = {-1, 0, 0, 0}; | |
| 537 Vector<const char>& prev = buffer_[prev_]; | |
| 538 const char* const prev_start = prev.start(); | |
| 539 const char* const prev_end = prev.start() + prev.length(); | |
| 540 do { | |
| 541 // We're moving backwards until we reach the current record. | |
| 542 // Remember that buffer_ is circular. | |
| 543 if (--index == -1) index = buffer_.length() - 1; | |
| 544 ++distance; | |
| 545 if (index == curr_) break; | |
| 546 | |
| 547 Vector<const char>& data = buffer_[index]; | |
| 548 if (data.start() == NULL) break; | |
| 549 const char* const data_end = data.start() + data.length(); | |
| 550 const char* prev_ptr = prev_end; | |
| 551 const char* data_ptr = data_end; | |
| 552 // Compare strings backwards, stop on the last matching character. | |
| 553 while (prev_ptr != prev_start && data_ptr != data.start() | |
| 554 && *(prev_ptr - 1) == *(data_ptr - 1)) { | |
| 555 --prev_ptr; | |
| 556 --data_ptr; | |
| 557 } | |
| 558 const intptr_t truncated_len = prev_end - prev_ptr; | |
| 559 const int copy_from_pos = static_cast<int>(data_ptr - data.start()); | |
| 560 // Check if the length of compressed tail is enough. | |
| 561 if (truncated_len <= kMaxBackwardReferenceSize | |
| 562 && truncated_len <= GetBackwardReferenceSize(distance, copy_from_pos)) { | |
| 563 continue; | |
| 564 } | |
| 565 | |
| 566 // Record compression results. | |
| 567 if (truncated_len > best.truncated_len) { | |
| 568 best.truncated_len = truncated_len; | |
| 569 best.distance = distance; | |
| 570 best.copy_from_pos = copy_from_pos; | |
| 571 best.backref_size = GetBackwardReferenceSize(distance, copy_from_pos); | |
| 572 } | |
| 573 } while (true); | |
| 574 | |
| 575 if (best.distance == 0) { | |
| 576 // Can't compress the previous record. Return as is. | |
| 577 ASSERT(prev_record->length() >= prev.length()); | |
| 578 memcpy(prev_record->start(), prev.start(), prev.length()); | |
| 579 prev_record->Truncate(prev.length()); | |
| 580 } else { | |
| 581 // Copy the uncompressible part unchanged. | |
| 582 const intptr_t unchanged_len = prev.length() - best.truncated_len; | |
| 583 // + 1 for '\0'. | |
| 584 ASSERT(prev_record->length() >= unchanged_len + best.backref_size + 1); | |
| 585 memcpy(prev_record->start(), prev.start(), unchanged_len); | |
| 586 // Append the backward reference. | |
| 587 Vector<char> backref( | |
| 588 prev_record->start() + unchanged_len, best.backref_size + 1); | |
| 589 PrintBackwardReference(backref, best.distance, best.copy_from_pos); | |
| 590 ASSERT(strlen(backref.start()) - best.backref_size == 0); | |
| 591 prev_record->Truncate(static_cast<int>(unchanged_len + best.backref_size)); | |
| 592 } | |
| 593 return true; | |
| 594 } | |
| 595 | |
| 596 #endif // ENABLE_LOGGING_AND_PROFILING | 419 #endif // ENABLE_LOGGING_AND_PROFILING |
| 597 | 420 |
| 598 } } // namespace v8::internal | 421 } } // namespace v8::internal |
| OLD | NEW |