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 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 void LogMessageBuilder::Append(String* str) { | 266 void LogMessageBuilder::Append(String* str) { |
267 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. | 267 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
268 int length = str->length(); | 268 int length = str->length(); |
269 for (int i = 0; i < length; i++) { | 269 for (int i = 0; i < length; i++) { |
270 Append(static_cast<char>(str->Get(i))); | 270 Append(static_cast<char>(str->Get(i))); |
271 } | 271 } |
272 } | 272 } |
273 | 273 |
274 | 274 |
275 void LogMessageBuilder::AppendAddress(Address addr) { | 275 void LogMessageBuilder::AppendAddress(Address addr) { |
276 Append("0x%" V8PRIxPTR, addr); | 276 static Address last_address_ = NULL; |
| 277 AppendAddress(addr, last_address_); |
| 278 last_address_ = addr; |
277 } | 279 } |
278 | 280 |
279 | 281 |
| 282 void LogMessageBuilder::AppendAddress(Address addr, Address bias) { |
| 283 if (!FLAG_compress_log) { |
| 284 Append("0x%" V8PRIxPTR, addr); |
| 285 } else if (bias == NULL) { |
| 286 Append("%" V8PRIxPTR, addr); |
| 287 } else { |
| 288 uintptr_t delta; |
| 289 char sign; |
| 290 if (addr >= bias) { |
| 291 delta = addr - bias; |
| 292 sign = '+'; |
| 293 } else { |
| 294 delta = bias - addr; |
| 295 sign = '-'; |
| 296 } |
| 297 Append("%c%" V8PRIxPTR, sign, delta); |
| 298 } |
| 299 } |
| 300 |
| 301 |
280 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { | 302 void LogMessageBuilder::AppendDetailed(String* str, bool show_impl_info) { |
281 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. | 303 AssertNoAllocation no_heap_allocation; // Ensure string stay valid. |
282 int len = str->length(); | 304 int len = str->length(); |
283 if (len > 0x1000) | 305 if (len > 0x1000) |
284 len = 0x1000; | 306 len = 0x1000; |
285 if (show_impl_info) { | 307 if (show_impl_info) { |
286 Append(str->IsAsciiRepresentation() ? 'a' : '2'); | 308 Append(str->IsAsciiRepresentation() ? 'a' : '2'); |
287 if (StringShape(str).IsExternal()) | 309 if (StringShape(str).IsExternal()) |
288 Append('e'); | 310 Append('e'); |
289 if (StringShape(str).IsSymbol()) | 311 if (StringShape(str).IsSymbol()) |
(...skipping 24 matching lines...) Expand all Loading... |
314 if (len == 0) return; | 336 if (len == 0) return; |
315 } | 337 } |
316 Vector<char> buf(Log::message_buffer_ + pos_, | 338 Vector<char> buf(Log::message_buffer_ + pos_, |
317 Log::kMessageBufferSize - pos_); | 339 Log::kMessageBufferSize - pos_); |
318 OS::StrNCpy(buf, str, len); | 340 OS::StrNCpy(buf, str, len); |
319 pos_ += len; | 341 pos_ += len; |
320 ASSERT(pos_ <= Log::kMessageBufferSize); | 342 ASSERT(pos_ <= Log::kMessageBufferSize); |
321 } | 343 } |
322 | 344 |
323 | 345 |
| 346 bool LogMessageBuilder::StoreInCompressor(LogRecordCompressor* compressor) { |
| 347 return compressor->Store(Vector<const char>(Log::message_buffer_, pos_)); |
| 348 } |
| 349 |
| 350 |
| 351 bool LogMessageBuilder::RetrieveCompressedPrevious( |
| 352 LogRecordCompressor* compressor, const char* prefix) { |
| 353 pos_ = 0; |
| 354 if (prefix[0] != '\0') Append(prefix); |
| 355 Vector<char> prev_record(Log::message_buffer_ + pos_, |
| 356 Log::kMessageBufferSize - pos_); |
| 357 const bool has_prev = compressor->RetrievePreviousCompressed(&prev_record); |
| 358 if (!has_prev) return false; |
| 359 pos_ += prev_record.length(); |
| 360 return true; |
| 361 } |
| 362 |
| 363 |
324 void LogMessageBuilder::WriteToLogFile() { | 364 void LogMessageBuilder::WriteToLogFile() { |
325 ASSERT(pos_ <= Log::kMessageBufferSize); | 365 ASSERT(pos_ <= Log::kMessageBufferSize); |
326 const int written = Log::Write(Log::message_buffer_, pos_); | 366 const int written = Log::Write(Log::message_buffer_, pos_); |
327 if (written != pos_ && write_failure_handler != NULL) { | 367 if (written != pos_ && write_failure_handler != NULL) { |
328 write_failure_handler(); | 368 write_failure_handler(); |
329 } | 369 } |
330 } | 370 } |
331 | 371 |
| 372 |
| 373 // Formatting string for back references to the whole line. E.g. "#2" means |
| 374 // "the second line above". |
| 375 const char* LogRecordCompressor::kLineBackwardReferenceFormat = "#%d"; |
| 376 |
| 377 // Formatting string for back references. E.g. "#2:10" means |
| 378 // "the second line above, start from char 10 (0-based)". |
| 379 const char* LogRecordCompressor::kBackwardReferenceFormat = "#%d:%d"; |
| 380 |
| 381 |
| 382 LogRecordCompressor::~LogRecordCompressor() { |
| 383 for (int i = 0; i < buffer_.length(); ++i) { |
| 384 buffer_[i].Dispose(); |
| 385 } |
| 386 } |
| 387 |
| 388 |
| 389 static int GetNumberLength(int number) { |
| 390 ASSERT(number >= 0); |
| 391 ASSERT(number < 10000); |
| 392 if (number < 10) return 1; |
| 393 if (number < 100) return 2; |
| 394 if (number < 1000) return 3; |
| 395 return 4; |
| 396 } |
| 397 |
| 398 |
| 399 int LogRecordCompressor::GetBackwardReferenceSize(int distance, int pos) { |
| 400 // See kLineBackwardReferenceFormat and kBackwardReferenceFormat. |
| 401 return pos == 0 ? GetNumberLength(distance) + 1 |
| 402 : GetNumberLength(distance) + GetNumberLength(pos) + 2; |
| 403 } |
| 404 |
| 405 |
| 406 void LogRecordCompressor::PrintBackwardReference(Vector<char> dest, |
| 407 int distance, |
| 408 int pos) { |
| 409 if (pos == 0) { |
| 410 OS::SNPrintF(dest, kLineBackwardReferenceFormat, distance); |
| 411 } else { |
| 412 OS::SNPrintF(dest, kBackwardReferenceFormat, distance, pos); |
| 413 } |
| 414 } |
| 415 |
| 416 |
| 417 bool LogRecordCompressor::Store(const Vector<const char>& record) { |
| 418 // Check if the record is the same as the last stored one. |
| 419 if (curr_ != -1) { |
| 420 Vector<const char>& curr = buffer_[curr_]; |
| 421 if (record.length() == curr.length() |
| 422 && strncmp(record.start(), curr.start(), record.length()) == 0) { |
| 423 return false; |
| 424 } |
| 425 } |
| 426 // buffer_ is circular. |
| 427 prev_ = curr_++; |
| 428 curr_ %= buffer_.length(); |
| 429 Vector<char> record_copy = Vector<char>::New(record.length()); |
| 430 memcpy(record_copy.start(), record.start(), record.length()); |
| 431 buffer_[curr_].Dispose(); |
| 432 buffer_[curr_] = |
| 433 Vector<const char>(record_copy.start(), record_copy.length()); |
| 434 return true; |
| 435 } |
| 436 |
| 437 |
| 438 bool LogRecordCompressor::RetrievePreviousCompressed( |
| 439 Vector<char>* prev_record) { |
| 440 if (prev_ == -1) return false; |
| 441 |
| 442 int index = prev_; |
| 443 // Distance from prev_. |
| 444 int distance = 0; |
| 445 // Best compression result among records in the buffer. |
| 446 struct { |
| 447 intptr_t truncated_len; |
| 448 int distance; |
| 449 int copy_from_pos; |
| 450 int backref_size; |
| 451 } best = {-1, 0, 0, 0}; |
| 452 Vector<const char>& prev = buffer_[prev_]; |
| 453 const char* const prev_start = prev.start(); |
| 454 const char* const prev_end = prev.start() + prev.length(); |
| 455 do { |
| 456 // We're moving backwards until we reach the current record. |
| 457 // Remember that buffer_ is circular. |
| 458 if (--index == -1) index = buffer_.length() - 1; |
| 459 ++distance; |
| 460 if (index == curr_) break; |
| 461 |
| 462 Vector<const char>& data = buffer_[index]; |
| 463 if (data.start() == NULL) break; |
| 464 const char* const data_end = data.start() + data.length(); |
| 465 const char* prev_ptr = prev_end; |
| 466 const char* data_ptr = data_end; |
| 467 // Compare strings backwards, stop on the last matching character. |
| 468 while (prev_ptr != prev_start && data_ptr != data.start() |
| 469 && *(prev_ptr - 1) == *(data_ptr - 1)) { |
| 470 --prev_ptr; |
| 471 --data_ptr; |
| 472 } |
| 473 const intptr_t truncated_len = prev_end - prev_ptr; |
| 474 const int copy_from_pos = static_cast<int>(data_ptr - data.start()); |
| 475 // Check if the length of compressed tail is enough. |
| 476 if (truncated_len <= kMaxBackwardReferenceSize |
| 477 && truncated_len <= GetBackwardReferenceSize(distance, copy_from_pos)) { |
| 478 continue; |
| 479 } |
| 480 |
| 481 // Record compression results. |
| 482 if (truncated_len > best.truncated_len) { |
| 483 best.truncated_len = truncated_len; |
| 484 best.distance = distance; |
| 485 best.copy_from_pos = copy_from_pos; |
| 486 best.backref_size = GetBackwardReferenceSize(distance, copy_from_pos); |
| 487 } |
| 488 } while (true); |
| 489 |
| 490 if (best.distance == 0) { |
| 491 // Can't compress the previous record. Return as is. |
| 492 ASSERT(prev_record->length() >= prev.length()); |
| 493 memcpy(prev_record->start(), prev.start(), prev.length()); |
| 494 prev_record->Truncate(prev.length()); |
| 495 } else { |
| 496 // Copy the uncompressible part unchanged. |
| 497 const intptr_t unchanged_len = prev.length() - best.truncated_len; |
| 498 // + 1 for '\0'. |
| 499 ASSERT(prev_record->length() >= unchanged_len + best.backref_size + 1); |
| 500 memcpy(prev_record->start(), prev.start(), unchanged_len); |
| 501 // Append the backward reference. |
| 502 Vector<char> backref( |
| 503 prev_record->start() + unchanged_len, best.backref_size + 1); |
| 504 PrintBackwardReference(backref, best.distance, best.copy_from_pos); |
| 505 ASSERT(strlen(backref.start()) - best.backref_size == 0); |
| 506 prev_record->Truncate(static_cast<int>(unchanged_len + best.backref_size)); |
| 507 } |
| 508 return true; |
| 509 } |
| 510 |
332 #endif // ENABLE_LOGGING_AND_PROFILING | 511 #endif // ENABLE_LOGGING_AND_PROFILING |
333 | 512 |
334 } } // namespace v8::internal | 513 } } // namespace v8::internal |
OLD | NEW |