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

Side by Side Diff: src/liveedit.cc

Issue 1148007: Merge bleeding_edge from version 2.1.3 up to revision 4205... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 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
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 SharedFunctionInfo::cast(array->GetElement(i))); 339 SharedFunctionInfo::cast(array->GetElement(i)));
340 SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(); 340 SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
341 Handle<String> name_handle(String::cast(info->name())); 341 Handle<String> name_handle(String::cast(info->name()));
342 info_wrapper.SetProperties(name_handle, info->start_position(), 342 info_wrapper.SetProperties(name_handle, info->start_position(),
343 info->end_position(), info); 343 info->end_position(), info);
344 array->SetElement(i, *(info_wrapper.GetJSArray())); 344 array->SetElement(i, *(info_wrapper.GetJSArray()));
345 } 345 }
346 } 346 }
347 347
348 348
349 // Visitor that collects all references to a particular code object,
350 // including "CODE_TARGET" references in other code objects.
351 // It works in context of ZoneScope.
352 class ReferenceCollectorVisitor : public ObjectVisitor {
353 public:
354 explicit ReferenceCollectorVisitor(Code* original)
355 : original_(original), rvalues_(10), reloc_infos_(10) {
356 }
357
358 virtual void VisitPointers(Object** start, Object** end) {
359 for (Object** p = start; p < end; p++) {
360 if (*p == original_) {
361 rvalues_.Add(p);
362 }
363 }
364 }
365
366 void VisitCodeTarget(RelocInfo* rinfo) {
367 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
368 if (Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
369 reloc_infos_.Add(*rinfo);
370 }
371 }
372
373 virtual void VisitDebugTarget(RelocInfo* rinfo) {
374 VisitCodeTarget(rinfo);
375 }
376
377 // Post-visiting method that iterates over all collected references and
378 // modifies them.
379 void Replace(Code* substitution) {
380 for (int i = 0; i < rvalues_.length(); i++) {
381 *(rvalues_[i]) = substitution;
382 }
383 for (int i = 0; i < reloc_infos_.length(); i++) {
384 reloc_infos_[i].set_target_address(substitution->instruction_start());
385 }
386 }
387
388 private:
389 Code* original_;
390 ZoneList<Object**> rvalues_;
391 ZoneList<RelocInfo> reloc_infos_;
392 };
393
394
395 class FrameCookingThreadVisitor : public ThreadVisitor {
396 public:
397 void VisitThread(ThreadLocalTop* top) {
398 StackFrame::CookFramesForThread(top);
399 }
400 };
401
402 class FrameUncookingThreadVisitor : public ThreadVisitor {
403 public:
404 void VisitThread(ThreadLocalTop* top) {
405 StackFrame::UncookFramesForThread(top);
406 }
407 };
408
409 static void IterateAllThreads(ThreadVisitor* visitor) {
410 Top::IterateThread(visitor);
411 ThreadManager::IterateThreads(visitor);
412 }
413
414 // Finds all references to original and replaces them with substitution.
415 static void ReplaceCodeObject(Code* original, Code* substitution) {
416 ASSERT(!Heap::InNewSpace(substitution));
417
418 AssertNoAllocation no_allocations_please;
419
420 // A zone scope for ReferenceCollectorVisitor.
421 ZoneScope scope(DELETE_ON_EXIT);
422
423 ReferenceCollectorVisitor visitor(original);
424
425 // Iterate over all roots. Stack frames may have pointer into original code,
426 // so temporary replace the pointers with offset numbers
427 // in prologue/epilogue.
428 {
429 FrameCookingThreadVisitor cooking_visitor;
430 IterateAllThreads(&cooking_visitor);
431
432 Heap::IterateStrongRoots(&visitor, VISIT_ALL);
433
434 FrameUncookingThreadVisitor uncooking_visitor;
435 IterateAllThreads(&uncooking_visitor);
436 }
437
438 // Now iterate over all pointers of all objects, including code_target
439 // implicit pointers.
440 HeapIterator iterator;
441 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
442 obj->Iterate(&visitor);
443 }
444
445 visitor.Replace(substitution);
446 }
447
448
349 void LiveEdit::ReplaceFunctionCode(Handle<JSArray> new_compile_info_array, 449 void LiveEdit::ReplaceFunctionCode(Handle<JSArray> new_compile_info_array,
350 Handle<JSArray> shared_info_array) { 450 Handle<JSArray> shared_info_array) {
351 HandleScope scope; 451 HandleScope scope;
352 452
353 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); 453 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
354 SharedInfoWrapper shared_info_wrapper(shared_info_array); 454 SharedInfoWrapper shared_info_wrapper(shared_info_array);
355 455
356 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); 456 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
357 457
358 shared_info->set_code(*(compile_info_wrapper.GetFunctionCode()), 458 ReplaceCodeObject(shared_info->code(),
359 UPDATE_WRITE_BARRIER); 459 *(compile_info_wrapper.GetFunctionCode()));
460
360 shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); 461 shared_info->set_start_position(compile_info_wrapper.GetStartPosition());
361 shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); 462 shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
362 // update breakpoints, original code, constructor stub 463 // update breakpoints, original code, constructor stub
363 } 464 }
364 465
365 466
366 void LiveEdit::RelinkFunctionToScript(Handle<JSArray> shared_info_array, 467 void LiveEdit::RelinkFunctionToScript(Handle<JSArray> shared_info_array,
367 Handle<Script> script_handle) { 468 Handle<Script> script_handle) {
368 SharedInfoWrapper shared_info_wrapper(shared_info_array); 469 SharedInfoWrapper shared_info_wrapper(shared_info_array);
369 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); 470 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
(...skipping 12 matching lines...) Expand all
382 // If a positions is inside some region that changed, result is currently 483 // If a positions is inside some region that changed, result is currently
383 // undefined. 484 // undefined.
384 static int TranslatePosition(int original_position, 485 static int TranslatePosition(int original_position,
385 Handle<JSArray> position_change_array) { 486 Handle<JSArray> position_change_array) {
386 int position_diff = 0; 487 int position_diff = 0;
387 int array_len = Smi::cast(position_change_array->length())->value(); 488 int array_len = Smi::cast(position_change_array->length())->value();
388 // TODO(635): binary search may be used here 489 // TODO(635): binary search may be used here
389 for (int i = 0; i < array_len; i += 3) { 490 for (int i = 0; i < array_len; i += 3) {
390 int chunk_start = 491 int chunk_start =
391 Smi::cast(position_change_array->GetElement(i))->value(); 492 Smi::cast(position_change_array->GetElement(i))->value();
493 if (original_position < chunk_start) {
494 break;
495 }
392 int chunk_end = 496 int chunk_end =
393 Smi::cast(position_change_array->GetElement(i + 1))->value(); 497 Smi::cast(position_change_array->GetElement(i + 1))->value();
498 // Position mustn't be inside a chunk.
499 ASSERT(original_position >= chunk_end);
394 int chunk_changed_end = 500 int chunk_changed_end =
395 Smi::cast(position_change_array->GetElement(i + 2))->value(); 501 Smi::cast(position_change_array->GetElement(i + 2))->value();
396 position_diff = chunk_changed_end - chunk_end; 502 position_diff = chunk_changed_end - chunk_end;
397 if (original_position < chunk_start) {
398 break;
399 }
400 // Position mustn't be inside a chunk.
401 ASSERT(original_position >= chunk_end);
402 } 503 }
403 504
404 return original_position + position_diff; 505 return original_position + position_diff;
405 } 506 }
406 507
407 508
509 // Auto-growing buffer for writing relocation info code section. This buffer
510 // is a simplified version of buffer from Assembler. Unlike Assembler, this
511 // class is platform-independent and it works without dealing with instructions.
512 // As specified by RelocInfo format, the buffer is filled in reversed order:
513 // from upper to lower addresses.
514 // It uses NewArray/DeleteArray for memory management.
515 class RelocInfoBuffer {
516 public:
517 RelocInfoBuffer(int buffer_initial_capicity, byte* pc) {
518 buffer_size_ = buffer_initial_capicity + kBufferGap;
519 buffer_ = NewArray<byte>(buffer_size_);
520
521 reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc);
522 }
523 ~RelocInfoBuffer() {
524 DeleteArray(buffer_);
525 }
526
527 // As specified by RelocInfo format, the buffer is filled in reversed order:
528 // from upper to lower addresses.
529 void Write(const RelocInfo* rinfo) {
530 if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) {
531 Grow();
532 }
533 reloc_info_writer_.Write(rinfo);
534 }
535
536 Vector<byte> GetResult() {
537 // Return the bytes from pos up to end of buffer.
538 return Vector<byte>(reloc_info_writer_.pos(),
539 buffer_ + buffer_size_ - reloc_info_writer_.pos());
540 }
541
542 private:
543 void Grow() {
544 // Compute new buffer size.
545 int new_buffer_size;
546 if (buffer_size_ < 2 * KB) {
547 new_buffer_size = 4 * KB;
548 } else {
549 new_buffer_size = 2 * buffer_size_;
550 }
551 // Some internal data structures overflow for very large buffers,
552 // they must ensure that kMaximalBufferSize is not too large.
553 if (new_buffer_size > kMaximalBufferSize) {
554 V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer");
555 }
556
557 // Setup new buffer.
558 byte* new_buffer = NewArray<byte>(new_buffer_size);
559
560 // Copy the data.
561 int curently_used_size = buffer_ + buffer_size_ - reloc_info_writer_.pos();
562 memmove(new_buffer + new_buffer_size - curently_used_size,
563 reloc_info_writer_.pos(), curently_used_size);
564
565 reloc_info_writer_.Reposition(
566 new_buffer + new_buffer_size - curently_used_size,
567 reloc_info_writer_.last_pc());
568
569 DeleteArray(buffer_);
570 buffer_ = new_buffer;
571 buffer_size_ = new_buffer_size;
572 }
573
574 RelocInfoWriter reloc_info_writer_;
575 byte* buffer_;
576 int buffer_size_;
577
578 static const int kBufferGap = 8;
579 static const int kMaximalBufferSize = 512*MB;
580 };
581
582 // Patch positions in code (changes relocation info section) and possibly
583 // returns new instance of code.
584 static Handle<Code> PatchPositionsInCode(Handle<Code> code,
585 Handle<JSArray> position_change_array) {
586
587 RelocInfoBuffer buffer_writer(code->relocation_size(),
588 code->instruction_start());
589
590 {
591 AssertNoAllocation no_allocations_please;
592 for (RelocIterator it(*code); !it.done(); it.next()) {
593 RelocInfo* rinfo = it.rinfo();
594 if (RelocInfo::IsPosition(rinfo->rmode())) {
595 int position = static_cast<int>(rinfo->data());
596 int new_position = TranslatePosition(position,
597 position_change_array);
598 if (position != new_position) {
599 RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position);
600 buffer_writer.Write(&info_copy);
601 continue;
602 }
603 }
604 buffer_writer.Write(it.rinfo());
605 }
606 }
607
608 Vector<byte> buffer = buffer_writer.GetResult();
609
610 if (buffer.length() == code->relocation_size()) {
611 // Simply patch relocation area of code.
612 memcpy(code->relocation_start(), buffer.start(), buffer.length());
613 return code;
614 } else {
615 // Relocation info section now has different size. We cannot simply
616 // rewrite it inside code object. Instead we have to create a new
617 // code object.
618 Handle<Code> result(Factory::CopyCode(code, buffer));
619 return result;
620 }
621 }
622
623
408 void LiveEdit::PatchFunctionPositions(Handle<JSArray> shared_info_array, 624 void LiveEdit::PatchFunctionPositions(Handle<JSArray> shared_info_array,
409 Handle<JSArray> position_change_array) { 625 Handle<JSArray> position_change_array) {
410 SharedInfoWrapper shared_info_wrapper(shared_info_array); 626 SharedInfoWrapper shared_info_wrapper(shared_info_array);
411 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo(); 627 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
412 628
413 info->set_start_position(TranslatePosition(info->start_position(), 629 info->set_start_position(TranslatePosition(info->start_position(),
414 position_change_array)); 630 position_change_array));
415 info->set_end_position(TranslatePosition(info->end_position(), 631 info->set_end_position(TranslatePosition(info->end_position(),
416 position_change_array)); 632 position_change_array));
417 633
418 // Also patch rinfos (both in working code and original code), breakpoints. 634 info->set_function_token_position(
635 TranslatePosition(info->function_token_position(),
636 position_change_array));
637
638 // Patch relocation info section of the code.
639 Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()),
640 position_change_array);
641 if (*patched_code != info->code()) {
642 // Replace all references to the code across the heap. In particular,
643 // some stubs may refer to this code and this code may be being executed
644 // on stack (it is safe to substitute the code object on stack, because
645 // we only change the structure of rinfo and leave instructions untouched).
646 ReplaceCodeObject(info->code(), *patched_code);
647 }
648
649 if (info->debug_info()->IsDebugInfo()) {
650 Handle<DebugInfo> debug_info(DebugInfo::cast(info->debug_info()));
651 Handle<Code> patched_orig_code =
652 PatchPositionsInCode(Handle<Code>(debug_info->original_code()),
653 position_change_array);
654 if (*patched_orig_code != debug_info->original_code()) {
655 // Do not use expensive ReplaceCodeObject for original_code, because we
656 // do not expect any other references except this one.
657 debug_info->set_original_code(*patched_orig_code);
658 }
659
660 Handle<FixedArray> break_point_infos(debug_info->break_points());
661 for (int i = 0; i < break_point_infos->length(); i++) {
662 if (!break_point_infos->get(i)->IsBreakPointInfo()) {
663 continue;
664 }
665 Handle<BreakPointInfo> info(
666 BreakPointInfo::cast(break_point_infos->get(i)));
667 int new_position = TranslatePosition(info->source_position()->value(),
668 position_change_array);
669 info->set_source_position(Smi::FromInt(new_position));
670 }
671 }
672 // TODO(635): Also patch breakpoint objects in JS.
419 } 673 }
420 674
421 675
422 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { 676 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
423 if (active_function_info_listener != NULL) { 677 if (active_function_info_listener != NULL) {
424 active_function_info_listener->FunctionStarted(fun); 678 active_function_info_listener->FunctionStarted(fun);
425 } 679 }
426 } 680 }
427 681
428 682
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 728
475 bool LiveEditFunctionTracker::IsActive() { 729 bool LiveEditFunctionTracker::IsActive() {
476 return false; 730 return false;
477 } 731 }
478 732
479 #endif // ENABLE_DEBUGGER_SUPPORT 733 #endif // ENABLE_DEBUGGER_SUPPORT
480 734
481 735
482 736
483 } } // namespace v8::internal 737 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698