Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(386)

Side by Side Diff: src/liveedit.cc

Issue 7087031: LiveEdit: Optimize compare by stripping common suffix and prefix. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: merge Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/liveedit.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 USE(no_failure); 59 USE(no_failure);
60 } 60 }
61 61
62 // A simple implementation of dynamic programming algorithm. It solves 62 // A simple implementation of dynamic programming algorithm. It solves
63 // the problem of finding the difference of 2 arrays. It uses a table of results 63 // the problem of finding the difference of 2 arrays. It uses a table of results
64 // of subproblems. Each cell contains a number together with 2-bit flag 64 // of subproblems. Each cell contains a number together with 2-bit flag
65 // that helps building the chunk list. 65 // that helps building the chunk list.
66 class Differencer { 66 class Differencer {
67 public: 67 public:
68 explicit Differencer(Comparator::Input* input) 68 explicit Differencer(Comparator::Input* input)
69 : input_(input), len1_(input->getLength1()), len2_(input->getLength2()) { 69 : input_(input), len1_(input->GetLength1()), len2_(input->GetLength2()) {
70 buffer_ = NewArray<int>(len1_ * len2_); 70 buffer_ = NewArray<int>(len1_ * len2_);
71 } 71 }
72 ~Differencer() { 72 ~Differencer() {
73 DeleteArray(buffer_); 73 DeleteArray(buffer_);
74 } 74 }
75 75
76 void Initialize() { 76 void Initialize() {
77 int array_size = len1_ * len2_; 77 int array_size = len1_ * len2_;
78 for (int i = 0; i < array_size; i++) { 78 for (int i = 0; i < array_size; i++) {
79 buffer_[i] = kEmptyCellValue; 79 buffer_[i] = kEmptyCellValue;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 144
145 // Computes result for a subtask and optionally caches it in the buffer table. 145 // Computes result for a subtask and optionally caches it in the buffer table.
146 // All results values are shifted to make space for flags in the lower bits. 146 // All results values are shifted to make space for flags in the lower bits.
147 int CompareUpToTail(int pos1, int pos2) { 147 int CompareUpToTail(int pos1, int pos2) {
148 if (pos1 < len1_) { 148 if (pos1 < len1_) {
149 if (pos2 < len2_) { 149 if (pos2 < len2_) {
150 int cached_res = get_value4(pos1, pos2); 150 int cached_res = get_value4(pos1, pos2);
151 if (cached_res == kEmptyCellValue) { 151 if (cached_res == kEmptyCellValue) {
152 Direction dir; 152 Direction dir;
153 int res; 153 int res;
154 if (input_->equals(pos1, pos2)) { 154 if (input_->Equals(pos1, pos2)) {
155 res = CompareUpToTail(pos1 + 1, pos2 + 1); 155 res = CompareUpToTail(pos1 + 1, pos2 + 1);
156 dir = EQ; 156 dir = EQ;
157 } else { 157 } else {
158 int res1 = CompareUpToTail(pos1 + 1, pos2) + 158 int res1 = CompareUpToTail(pos1 + 1, pos2) +
159 (1 << kDirectionSizeBits); 159 (1 << kDirectionSizeBits);
160 int res2 = CompareUpToTail(pos1, pos2 + 1) + 160 int res2 = CompareUpToTail(pos1, pos2 + 1) +
161 (1 << kDirectionSizeBits); 161 (1 << kDirectionSizeBits);
162 if (res1 == res2) { 162 if (res1 == res2) {
163 res = res1; 163 res = res1;
164 dir = SKIP_ANY; 164 dir = SKIP_ANY;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 Handle<String> s2, int pos2, int len) { 272 Handle<String> s2, int pos2, int len) {
273 for (int i = 0; i < len; i++) { 273 for (int i = 0; i < len; i++) {
274 if (s1->Get(i + pos1) != s2->Get(i + pos2)) { 274 if (s1->Get(i + pos1) != s2->Get(i + pos2)) {
275 return false; 275 return false;
276 } 276 }
277 } 277 }
278 return true; 278 return true;
279 } 279 }
280 280
281 281
282 // Additional to Input interface. Lets switch Input range to subrange.
283 // More elegant way would be to wrap one Input as another Input object
284 // and translate positions there, but that would cost us additional virtual
285 // call per comparison.
286 class SubrangableInput : public Comparator::Input {
287 public:
288 virtual void SetSubrange1(int offset, int len) = 0;
289 virtual void SetSubrange2(int offset, int len) = 0;
290 };
291
292
293 class SubrangableOutput : public Comparator::Output {
294 public:
295 virtual void SetSubrange1(int offset, int len) = 0;
296 virtual void SetSubrange2(int offset, int len) = 0;
297 };
298
299
300 static int min(int a, int b) {
301 return a < b ? a : b;
302 }
303
304
305 // Finds common prefix and suffix in input. This parts shouldn't take space in
306 // linear programming table. Enable subranging in input and output.
307 static void NarrowDownInput(SubrangableInput* input,
308 SubrangableOutput* output) {
309 const int len1 = input->GetLength1();
310 const int len2 = input->GetLength2();
311
312 int common_prefix_len;
313 int common_suffix_len;
314
315 {
316 common_prefix_len = 0;
317 int prefix_limit = min(len1, len2);
318 while (common_prefix_len < prefix_limit &&
319 input->Equals(common_prefix_len, common_prefix_len)) {
320 common_prefix_len++;
321 }
322
323 common_suffix_len = 0;
324 int suffix_limit = min(len1 - common_prefix_len, len2 - common_prefix_len);
325
326 while (common_suffix_len < suffix_limit &&
327 input->Equals(len1 - common_suffix_len - 1,
328 len2 - common_suffix_len - 1)) {
329 common_suffix_len++;
330 }
331 }
332
333 if (common_prefix_len > 0 || common_suffix_len > 0) {
334 int new_len1 = len1 - common_suffix_len - common_prefix_len;
335 int new_len2 = len2 - common_suffix_len - common_prefix_len;
336
337 input->SetSubrange1(common_prefix_len, new_len1);
338 input->SetSubrange2(common_prefix_len, new_len2);
339
340 output->SetSubrange1(common_prefix_len, new_len1);
341 output->SetSubrange2(common_prefix_len, new_len2);
342 }
343 }
344
345
282 // A helper class that writes chunk numbers into JSArray. 346 // A helper class that writes chunk numbers into JSArray.
283 // Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end). 347 // Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end).
284 class CompareOutputArrayWriter { 348 class CompareOutputArrayWriter {
285 public: 349 public:
286 CompareOutputArrayWriter() 350 CompareOutputArrayWriter()
287 : array_(FACTORY->NewJSArray(10)), current_size_(0) {} 351 : array_(FACTORY->NewJSArray(10)), current_size_(0) {}
288 352
289 Handle<JSArray> GetResult() { 353 Handle<JSArray> GetResult() {
290 return array_; 354 return array_;
291 } 355 }
(...skipping 20 matching lines...) Expand all
312 // Represents 2 strings as 2 arrays of tokens. 376 // Represents 2 strings as 2 arrays of tokens.
313 // TODO(LiveEdit): Currently it's actually an array of charactres. 377 // TODO(LiveEdit): Currently it's actually an array of charactres.
314 // Make array of tokens instead. 378 // Make array of tokens instead.
315 class TokensCompareInput : public Comparator::Input { 379 class TokensCompareInput : public Comparator::Input {
316 public: 380 public:
317 TokensCompareInput(Handle<String> s1, int offset1, int len1, 381 TokensCompareInput(Handle<String> s1, int offset1, int len1,
318 Handle<String> s2, int offset2, int len2) 382 Handle<String> s2, int offset2, int len2)
319 : s1_(s1), offset1_(offset1), len1_(len1), 383 : s1_(s1), offset1_(offset1), len1_(len1),
320 s2_(s2), offset2_(offset2), len2_(len2) { 384 s2_(s2), offset2_(offset2), len2_(len2) {
321 } 385 }
322 virtual int getLength1() { 386 virtual int GetLength1() {
323 return len1_; 387 return len1_;
324 } 388 }
325 virtual int getLength2() { 389 virtual int GetLength2() {
326 return len2_; 390 return len2_;
327 } 391 }
328 bool equals(int index1, int index2) { 392 bool Equals(int index1, int index2) {
329 return s1_->Get(offset1_ + index1) == s2_->Get(offset2_ + index2); 393 return s1_->Get(offset1_ + index1) == s2_->Get(offset2_ + index2);
330 } 394 }
331 395
332 private: 396 private:
333 Handle<String> s1_; 397 Handle<String> s1_;
334 int offset1_; 398 int offset1_;
335 int len1_; 399 int len1_;
336 Handle<String> s2_; 400 Handle<String> s2_;
337 int offset2_; 401 int offset2_;
338 int len2_; 402 int len2_;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 Handle<FixedArray> ends_array_; 458 Handle<FixedArray> ends_array_;
395 int string_len_; 459 int string_len_;
396 460
397 int GetPosAfterNewLine(int index) { 461 int GetPosAfterNewLine(int index) {
398 return Smi::cast(ends_array_->get(index))->value() + 1; 462 return Smi::cast(ends_array_->get(index))->value() + 1;
399 } 463 }
400 }; 464 };
401 465
402 466
403 // Represents 2 strings as 2 arrays of lines. 467 // Represents 2 strings as 2 arrays of lines.
404 class LineArrayCompareInput : public Comparator::Input { 468 class LineArrayCompareInput : public SubrangableInput {
405 public: 469 public:
406 LineArrayCompareInput(Handle<String> s1, Handle<String> s2, 470 LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
407 LineEndsWrapper line_ends1, LineEndsWrapper line_ends2) 471 LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
408 : s1_(s1), s2_(s2), line_ends1_(line_ends1), 472 : s1_(s1), s2_(s2), line_ends1_(line_ends1),
409 line_ends2_(line_ends2) { 473 line_ends2_(line_ends2),
474 subrange_offset1_(0), subrange_offset2_(0),
475 subrange_len1_(line_ends1_.length()),
476 subrange_len2_(line_ends2_.length()) {
410 } 477 }
411 int getLength1() { 478 int GetLength1() {
412 return line_ends1_.length(); 479 return subrange_len1_;
413 } 480 }
414 int getLength2() { 481 int GetLength2() {
415 return line_ends2_.length(); 482 return subrange_len2_;
416 } 483 }
417 bool equals(int index1, int index2) { 484 bool Equals(int index1, int index2) {
485 index1 += subrange_offset1_;
486 index2 += subrange_offset2_;
487
418 int line_start1 = line_ends1_.GetLineStart(index1); 488 int line_start1 = line_ends1_.GetLineStart(index1);
419 int line_start2 = line_ends2_.GetLineStart(index2); 489 int line_start2 = line_ends2_.GetLineStart(index2);
420 int line_end1 = line_ends1_.GetLineEnd(index1); 490 int line_end1 = line_ends1_.GetLineEnd(index1);
421 int line_end2 = line_ends2_.GetLineEnd(index2); 491 int line_end2 = line_ends2_.GetLineEnd(index2);
422 int len1 = line_end1 - line_start1; 492 int len1 = line_end1 - line_start1;
423 int len2 = line_end2 - line_start2; 493 int len2 = line_end2 - line_start2;
424 if (len1 != len2) { 494 if (len1 != len2) {
425 return false; 495 return false;
426 } 496 }
427 return CompareSubstrings(s1_, line_start1, s2_, line_start2, 497 return CompareSubstrings(s1_, line_start1, s2_, line_start2,
428 len1); 498 len1);
429 } 499 }
500 void SetSubrange1(int offset, int len) {
501 subrange_offset1_ = offset;
502 subrange_len1_ = len;
503 }
504 void SetSubrange2(int offset, int len) {
505 subrange_offset2_ = offset;
506 subrange_len2_ = len;
507 }
430 508
431 private: 509 private:
432 Handle<String> s1_; 510 Handle<String> s1_;
433 Handle<String> s2_; 511 Handle<String> s2_;
434 LineEndsWrapper line_ends1_; 512 LineEndsWrapper line_ends1_;
435 LineEndsWrapper line_ends2_; 513 LineEndsWrapper line_ends2_;
514 int subrange_offset1_;
515 int subrange_offset2_;
516 int subrange_len1_;
517 int subrange_len2_;
436 }; 518 };
437 519
438 520
439 // Stores compare result in JSArray. For each chunk tries to conduct 521 // Stores compare result in JSArray. For each chunk tries to conduct
440 // a fine-grained nested diff token-wise. 522 // a fine-grained nested diff token-wise.
441 class TokenizingLineArrayCompareOutput : public Comparator::Output { 523 class TokenizingLineArrayCompareOutput : public SubrangableOutput {
442 public: 524 public:
443 TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1, 525 TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1,
444 LineEndsWrapper line_ends2, 526 LineEndsWrapper line_ends2,
445 Handle<String> s1, Handle<String> s2) 527 Handle<String> s1, Handle<String> s2)
446 : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2) { 528 : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2),
529 subrange_offset1_(0), subrange_offset2_(0) {
447 } 530 }
448 531
449 void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) { 532 void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
533 line_pos1 += subrange_offset1_;
534 line_pos2 += subrange_offset2_;
535
450 int char_pos1 = line_ends1_.GetLineStart(line_pos1); 536 int char_pos1 = line_ends1_.GetLineStart(line_pos1);
451 int char_pos2 = line_ends2_.GetLineStart(line_pos2); 537 int char_pos2 = line_ends2_.GetLineStart(line_pos2);
452 int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1; 538 int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
453 int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2; 539 int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
454 540
455 if (char_len1 < CHUNK_LEN_LIMIT && char_len2 < CHUNK_LEN_LIMIT) { 541 if (char_len1 < CHUNK_LEN_LIMIT && char_len2 < CHUNK_LEN_LIMIT) {
456 // Chunk is small enough to conduct a nested token-level diff. 542 // Chunk is small enough to conduct a nested token-level diff.
457 HandleScope subTaskScope; 543 HandleScope subTaskScope;
458 544
459 TokensCompareInput tokens_input(s1_, char_pos1, char_len1, 545 TokensCompareInput tokens_input(s1_, char_pos1, char_len1,
460 s2_, char_pos2, char_len2); 546 s2_, char_pos2, char_len2);
461 TokensCompareOutput tokens_output(&array_writer_, char_pos1, 547 TokensCompareOutput tokens_output(&array_writer_, char_pos1,
462 char_pos2); 548 char_pos2);
463 549
464 Comparator::CalculateDifference(&tokens_input, &tokens_output); 550 Comparator::CalculateDifference(&tokens_input, &tokens_output);
465 } else { 551 } else {
466 array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2); 552 array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2);
467 } 553 }
468 } 554 }
555 void SetSubrange1(int offset, int len) {
556 subrange_offset1_ = offset;
557 }
558 void SetSubrange2(int offset, int len) {
559 subrange_offset2_ = offset;
560 }
469 561
470 Handle<JSArray> GetResult() { 562 Handle<JSArray> GetResult() {
471 return array_writer_.GetResult(); 563 return array_writer_.GetResult();
472 } 564 }
473 565
474 private: 566 private:
475 static const int CHUNK_LEN_LIMIT = 800; 567 static const int CHUNK_LEN_LIMIT = 800;
476 568
477 CompareOutputArrayWriter array_writer_; 569 CompareOutputArrayWriter array_writer_;
478 LineEndsWrapper line_ends1_; 570 LineEndsWrapper line_ends1_;
479 LineEndsWrapper line_ends2_; 571 LineEndsWrapper line_ends2_;
480 Handle<String> s1_; 572 Handle<String> s1_;
481 Handle<String> s2_; 573 Handle<String> s2_;
574 int subrange_offset1_;
575 int subrange_offset2_;
482 }; 576 };
483 577
484 578
485 Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1, 579 Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
486 Handle<String> s2) { 580 Handle<String> s2) {
487 s1 = FlattenGetString(s1); 581 s1 = FlattenGetString(s1);
488 s2 = FlattenGetString(s2); 582 s2 = FlattenGetString(s2);
489 583
490 LineEndsWrapper line_ends1(s1); 584 LineEndsWrapper line_ends1(s1);
491 LineEndsWrapper line_ends2(s2); 585 LineEndsWrapper line_ends2(s2);
492 586
493 LineArrayCompareInput input(s1, s2, line_ends1, line_ends2); 587 LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
494 TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2); 588 TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
495 589
590 NarrowDownInput(&input, &output);
591
496 Comparator::CalculateDifference(&input, &output); 592 Comparator::CalculateDifference(&input, &output);
497 593
498 return output.GetResult(); 594 return output.GetResult();
499 } 595 }
500 596
501 597
502 static void CompileScriptForTracker(Isolate* isolate, Handle<Script> script) { 598 static void CompileScriptForTracker(Isolate* isolate, Handle<Script> script) {
503 // TODO(635): support extensions. 599 // TODO(635): support extensions.
504 PostponeInterruptsScope postpone(isolate); 600 PostponeInterruptsScope postpone(isolate);
505 601
(...skipping 1176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 1778
1683 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 1779 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
1684 return false; 1780 return false;
1685 } 1781 }
1686 1782
1687 #endif // ENABLE_DEBUGGER_SUPPORT 1783 #endif // ENABLE_DEBUGGER_SUPPORT
1688 1784
1689 1785
1690 1786
1691 } } // namespace v8::internal 1787 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/liveedit.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698