| OLD | NEW |
| 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 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 | 261 |
| 262 void Comparator::CalculateDifference(Comparator::Input* input, | 262 void Comparator::CalculateDifference(Comparator::Input* input, |
| 263 Comparator::Output* result_writer) { | 263 Comparator::Output* result_writer) { |
| 264 Differencer differencer(input); | 264 Differencer differencer(input); |
| 265 differencer.Initialize(); | 265 differencer.Initialize(); |
| 266 differencer.FillTable(); | 266 differencer.FillTable(); |
| 267 differencer.SaveResult(result_writer); | 267 differencer.SaveResult(result_writer); |
| 268 } | 268 } |
| 269 | 269 |
| 270 | 270 |
| 271 static bool CompareSubstrings(Handle<String> s1, int pos1, | 271 static bool CompareSubstrings(Isolate* isolate, Handle<String> s1, int pos1, |
| 272 Handle<String> s2, int pos2, int len) { | 272 Handle<String> s2, int pos2, int len) { |
| 273 static StringInputBuffer buf1; | 273 StringInputBuffer& buf1 = *isolate->liveedit_compare_substrings_buf1(); |
| 274 static StringInputBuffer buf2; | 274 StringInputBuffer& buf2 = *isolate->liveedit_compare_substrings_buf2(); |
| 275 buf1.Reset(*s1); | 275 buf1.Reset(*s1); |
| 276 buf1.Seek(pos1); | 276 buf1.Seek(pos1); |
| 277 buf2.Reset(*s2); | 277 buf2.Reset(*s2); |
| 278 buf2.Seek(pos2); | 278 buf2.Seek(pos2); |
| 279 for (int i = 0; i < len; i++) { | 279 for (int i = 0; i < len; i++) { |
| 280 ASSERT(buf1.has_more() && buf2.has_more()); | 280 ASSERT(buf1.has_more() && buf2.has_more()); |
| 281 if (buf1.GetNext() != buf2.GetNext()) { | 281 if (buf1.GetNext() != buf2.GetNext()) { |
| 282 return false; | 282 return false; |
| 283 } | 283 } |
| 284 } | 284 } |
| 285 return true; | 285 return true; |
| 286 } | 286 } |
| 287 | 287 |
| 288 | 288 |
| 289 // A helper class that writes chunk numbers into JSArray. | 289 // A helper class that writes chunk numbers into JSArray. |
| 290 // Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end). | 290 // Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end). |
| 291 class CompareOutputArrayWriter { | 291 class CompareOutputArrayWriter { |
| 292 public: | 292 public: |
| 293 CompareOutputArrayWriter() | 293 CompareOutputArrayWriter() |
| 294 : array_(Factory::NewJSArray(10)), current_size_(0) {} | 294 : array_(FACTORY->NewJSArray(10)), current_size_(0) {} |
| 295 | 295 |
| 296 Handle<JSArray> GetResult() { | 296 Handle<JSArray> GetResult() { |
| 297 return array_; | 297 return array_; |
| 298 } | 298 } |
| 299 | 299 |
| 300 void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) { | 300 void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) { |
| 301 SetElementNonStrict(array_, | 301 SetElementNonStrict(array_, |
| 302 current_size_, | 302 current_size_, |
| 303 Handle<Object>(Smi::FromInt(char_pos1))); | 303 Handle<Object>(Smi::FromInt(char_pos1))); |
| 304 SetElementNonStrict(array_, | 304 SetElementNonStrict(array_, |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 | 403 |
| 404 int GetPosAfterNewLine(int index) { | 404 int GetPosAfterNewLine(int index) { |
| 405 return Smi::cast(ends_array_->get(index))->value() + 1; | 405 return Smi::cast(ends_array_->get(index))->value() + 1; |
| 406 } | 406 } |
| 407 }; | 407 }; |
| 408 | 408 |
| 409 | 409 |
| 410 // Represents 2 strings as 2 arrays of lines. | 410 // Represents 2 strings as 2 arrays of lines. |
| 411 class LineArrayCompareInput : public Comparator::Input { | 411 class LineArrayCompareInput : public Comparator::Input { |
| 412 public: | 412 public: |
| 413 LineArrayCompareInput(Handle<String> s1, Handle<String> s2, | 413 LineArrayCompareInput(Isolate* isolate, Handle<String> s1, Handle<String> s2, |
| 414 LineEndsWrapper line_ends1, LineEndsWrapper line_ends2) | 414 LineEndsWrapper line_ends1, LineEndsWrapper line_ends2) |
| 415 : s1_(s1), s2_(s2), line_ends1_(line_ends1), line_ends2_(line_ends2) { | 415 : isolate_(isolate), s1_(s1), s2_(s2), line_ends1_(line_ends1), |
| 416 line_ends2_(line_ends2) { |
| 416 } | 417 } |
| 417 int getLength1() { | 418 int getLength1() { |
| 418 return line_ends1_.length(); | 419 return line_ends1_.length(); |
| 419 } | 420 } |
| 420 int getLength2() { | 421 int getLength2() { |
| 421 return line_ends2_.length(); | 422 return line_ends2_.length(); |
| 422 } | 423 } |
| 423 bool equals(int index1, int index2) { | 424 bool equals(int index1, int index2) { |
| 424 int line_start1 = line_ends1_.GetLineStart(index1); | 425 int line_start1 = line_ends1_.GetLineStart(index1); |
| 425 int line_start2 = line_ends2_.GetLineStart(index2); | 426 int line_start2 = line_ends2_.GetLineStart(index2); |
| 426 int line_end1 = line_ends1_.GetLineEnd(index1); | 427 int line_end1 = line_ends1_.GetLineEnd(index1); |
| 427 int line_end2 = line_ends2_.GetLineEnd(index2); | 428 int line_end2 = line_ends2_.GetLineEnd(index2); |
| 428 int len1 = line_end1 - line_start1; | 429 int len1 = line_end1 - line_start1; |
| 429 int len2 = line_end2 - line_start2; | 430 int len2 = line_end2 - line_start2; |
| 430 if (len1 != len2) { | 431 if (len1 != len2) { |
| 431 return false; | 432 return false; |
| 432 } | 433 } |
| 433 return CompareSubstrings(s1_, line_start1, s2_, line_start2, len1); | 434 return CompareSubstrings(isolate_, s1_, line_start1, s2_, line_start2, |
| 435 len1); |
| 434 } | 436 } |
| 435 | 437 |
| 436 private: | 438 private: |
| 439 Isolate* isolate_; |
| 437 Handle<String> s1_; | 440 Handle<String> s1_; |
| 438 Handle<String> s2_; | 441 Handle<String> s2_; |
| 439 LineEndsWrapper line_ends1_; | 442 LineEndsWrapper line_ends1_; |
| 440 LineEndsWrapper line_ends2_; | 443 LineEndsWrapper line_ends2_; |
| 441 }; | 444 }; |
| 442 | 445 |
| 443 | 446 |
| 444 // Stores compare result in JSArray. For each chunk tries to conduct | 447 // Stores compare result in JSArray. For each chunk tries to conduct |
| 445 // a fine-grained nested diff token-wise. | 448 // a fine-grained nested diff token-wise. |
| 446 class TokenizingLineArrayCompareOutput : public Comparator::Output { | 449 class TokenizingLineArrayCompareOutput : public Comparator::Output { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 Handle<String> s1_; | 488 Handle<String> s1_; |
| 486 Handle<String> s2_; | 489 Handle<String> s2_; |
| 487 }; | 490 }; |
| 488 | 491 |
| 489 | 492 |
| 490 Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1, | 493 Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1, |
| 491 Handle<String> s2) { | 494 Handle<String> s2) { |
| 492 LineEndsWrapper line_ends1(s1); | 495 LineEndsWrapper line_ends1(s1); |
| 493 LineEndsWrapper line_ends2(s2); | 496 LineEndsWrapper line_ends2(s2); |
| 494 | 497 |
| 495 LineArrayCompareInput input(s1, s2, line_ends1, line_ends2); | 498 LineArrayCompareInput |
| 499 input(Isolate::Current(), s1, s2, line_ends1, line_ends2); |
| 496 TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2); | 500 TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2); |
| 497 | 501 |
| 498 Comparator::CalculateDifference(&input, &output); | 502 Comparator::CalculateDifference(&input, &output); |
| 499 | 503 |
| 500 return output.GetResult(); | 504 return output.GetResult(); |
| 501 } | 505 } |
| 502 | 506 |
| 503 | 507 |
| 504 static void CompileScriptForTracker(Handle<Script> script) { | 508 static void CompileScriptForTracker(Isolate* isolate, Handle<Script> script) { |
| 505 // TODO(635): support extensions. | 509 // TODO(635): support extensions. |
| 506 PostponeInterruptsScope postpone; | 510 PostponeInterruptsScope postpone(isolate); |
| 507 | 511 |
| 508 // Build AST. | 512 // Build AST. |
| 509 CompilationInfo info(script); | 513 CompilationInfo info(script); |
| 510 info.MarkAsGlobal(); | 514 info.MarkAsGlobal(); |
| 511 if (ParserApi::Parse(&info)) { | 515 if (ParserApi::Parse(&info)) { |
| 512 // Compile the code. | 516 // Compile the code. |
| 513 LiveEditFunctionTracker tracker(info.function()); | 517 LiveEditFunctionTracker tracker(info.isolate(), info.function()); |
| 514 if (Compiler::MakeCodeForLiveEdit(&info)) { | 518 if (Compiler::MakeCodeForLiveEdit(&info)) { |
| 515 ASSERT(!info.code().is_null()); | 519 ASSERT(!info.code().is_null()); |
| 516 tracker.RecordRootFunctionInfo(info.code()); | 520 tracker.RecordRootFunctionInfo(info.code()); |
| 517 } else { | 521 } else { |
| 518 Top::StackOverflow(); | 522 info.isolate()->StackOverflow(); |
| 519 } | 523 } |
| 520 } | 524 } |
| 521 } | 525 } |
| 522 | 526 |
| 523 | 527 |
| 524 // Unwraps JSValue object, returning its field "value" | 528 // Unwraps JSValue object, returning its field "value" |
| 525 static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) { | 529 static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) { |
| 526 return Handle<Object>(jsValue->value()); | 530 return Handle<Object>(jsValue->value()); |
| 527 } | 531 } |
| 528 | 532 |
| 529 | 533 |
| 530 // Wraps any object into a OpaqueReference, that will hide the object | 534 // Wraps any object into a OpaqueReference, that will hide the object |
| 531 // from JavaScript. | 535 // from JavaScript. |
| 532 static Handle<JSValue> WrapInJSValue(Object* object) { | 536 static Handle<JSValue> WrapInJSValue(Object* object) { |
| 533 Handle<JSFunction> constructor = Top::opaque_reference_function(); | 537 Handle<JSFunction> constructor = |
| 538 Isolate::Current()->opaque_reference_function(); |
| 534 Handle<JSValue> result = | 539 Handle<JSValue> result = |
| 535 Handle<JSValue>::cast(Factory::NewJSObject(constructor)); | 540 Handle<JSValue>::cast(FACTORY->NewJSObject(constructor)); |
| 536 result->set_value(object); | 541 result->set_value(object); |
| 537 return result; | 542 return result; |
| 538 } | 543 } |
| 539 | 544 |
| 540 | 545 |
| 541 // Simple helper class that creates more or less typed structures over | 546 // Simple helper class that creates more or less typed structures over |
| 542 // JSArray object. This is an adhoc method of passing structures from C++ | 547 // JSArray object. This is an adhoc method of passing structures from C++ |
| 543 // to JavaScript. | 548 // to JavaScript. |
| 544 template<typename S> | 549 template<typename S> |
| 545 class JSArrayBasedStruct { | 550 class JSArrayBasedStruct { |
| 546 public: | 551 public: |
| 547 static S Create() { | 552 static S Create() { |
| 548 Handle<JSArray> array = Factory::NewJSArray(S::kSize_); | 553 Handle<JSArray> array = FACTORY->NewJSArray(S::kSize_); |
| 549 return S(array); | 554 return S(array); |
| 550 } | 555 } |
| 551 static S cast(Object* object) { | 556 static S cast(Object* object) { |
| 552 JSArray* array = JSArray::cast(object); | 557 JSArray* array = JSArray::cast(object); |
| 553 Handle<JSArray> array_handle(array); | 558 Handle<JSArray> array_handle(array); |
| 554 return S(array_handle); | 559 return S(array_handle); |
| 555 } | 560 } |
| 556 explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) { | 561 explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) { |
| 557 } | 562 } |
| 558 Handle<JSArray> GetJSArray() { | 563 Handle<JSArray> GetJSArray() { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 | 693 |
| 689 friend class JSArrayBasedStruct<SharedInfoWrapper>; | 694 friend class JSArrayBasedStruct<SharedInfoWrapper>; |
| 690 }; | 695 }; |
| 691 | 696 |
| 692 | 697 |
| 693 class FunctionInfoListener { | 698 class FunctionInfoListener { |
| 694 public: | 699 public: |
| 695 FunctionInfoListener() { | 700 FunctionInfoListener() { |
| 696 current_parent_index_ = -1; | 701 current_parent_index_ = -1; |
| 697 len_ = 0; | 702 len_ = 0; |
| 698 result_ = Factory::NewJSArray(10); | 703 result_ = FACTORY->NewJSArray(10); |
| 699 } | 704 } |
| 700 | 705 |
| 701 void FunctionStarted(FunctionLiteral* fun) { | 706 void FunctionStarted(FunctionLiteral* fun) { |
| 702 HandleScope scope; | 707 HandleScope scope; |
| 703 FunctionInfoWrapper info = FunctionInfoWrapper::Create(); | 708 FunctionInfoWrapper info = FunctionInfoWrapper::Create(); |
| 704 info.SetInitialProperties(fun->name(), fun->start_position(), | 709 info.SetInitialProperties(fun->name(), fun->start_position(), |
| 705 fun->end_position(), fun->num_parameters(), | 710 fun->end_position(), fun->num_parameters(), |
| 706 current_parent_index_); | 711 current_parent_index_); |
| 707 current_parent_index_ = len_; | 712 current_parent_index_ = len_; |
| 708 SetElementNonStrict(result_, len_, info.GetJSArray()); | 713 SetElementNonStrict(result_, len_, info.GetJSArray()); |
| 709 len_++; | 714 len_++; |
| 710 } | 715 } |
| 711 | 716 |
| 712 void FunctionDone() { | 717 void FunctionDone() { |
| 713 HandleScope scope; | 718 HandleScope scope; |
| 714 FunctionInfoWrapper info = | 719 FunctionInfoWrapper info = |
| 715 FunctionInfoWrapper::cast( | 720 FunctionInfoWrapper::cast( |
| 716 result_->GetElementNoExceptionThrown(current_parent_index_)); | 721 result_->GetElementNoExceptionThrown(current_parent_index_)); |
| 717 current_parent_index_ = info.GetParentIndex(); | 722 current_parent_index_ = info.GetParentIndex(); |
| 718 } | 723 } |
| 719 | 724 |
| 720 // Saves only function code, because for a script function we | 725 // Saves only function code, because for a script function we |
| 721 // may never create a SharedFunctionInfo object. | 726 // may never create a SharedFunctionInfo object. |
| 722 void FunctionCode(Handle<Code> function_code) { | 727 void FunctionCode(Handle<Code> function_code) { |
| 723 FunctionInfoWrapper info = | 728 FunctionInfoWrapper info = |
| 724 FunctionInfoWrapper::cast( | 729 FunctionInfoWrapper::cast( |
| 725 result_->GetElementNoExceptionThrown(current_parent_index_)); | 730 result_->GetElementNoExceptionThrown(current_parent_index_)); |
| 726 info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value())); | 731 info.SetFunctionCode(function_code, Handle<Object>(HEAP->null_value())); |
| 727 } | 732 } |
| 728 | 733 |
| 729 // Saves full information about a function: its code, its scope info | 734 // Saves full information about a function: its code, its scope info |
| 730 // and a SharedFunctionInfo object. | 735 // and a SharedFunctionInfo object. |
| 731 void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) { | 736 void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) { |
| 732 if (!shared->IsSharedFunctionInfo()) { | 737 if (!shared->IsSharedFunctionInfo()) { |
| 733 return; | 738 return; |
| 734 } | 739 } |
| 735 FunctionInfoWrapper info = | 740 FunctionInfoWrapper info = |
| 736 FunctionInfoWrapper::cast( | 741 FunctionInfoWrapper::cast( |
| 737 result_->GetElementNoExceptionThrown(current_parent_index_)); | 742 result_->GetElementNoExceptionThrown(current_parent_index_)); |
| 738 info.SetFunctionCode(Handle<Code>(shared->code()), | 743 info.SetFunctionCode(Handle<Code>(shared->code()), |
| 739 Handle<Object>(shared->scope_info())); | 744 Handle<Object>(shared->scope_info())); |
| 740 info.SetSharedFunctionInfo(shared); | 745 info.SetSharedFunctionInfo(shared); |
| 741 | 746 |
| 742 Handle<Object> scope_info_list(SerializeFunctionScope(scope)); | 747 Handle<Object> scope_info_list(SerializeFunctionScope(scope)); |
| 743 info.SetOuterScopeInfo(scope_info_list); | 748 info.SetOuterScopeInfo(scope_info_list); |
| 744 } | 749 } |
| 745 | 750 |
| 746 Handle<JSArray> GetResult() { return result_; } | 751 Handle<JSArray> GetResult() { return result_; } |
| 747 | 752 |
| 748 private: | 753 private: |
| 749 Object* SerializeFunctionScope(Scope* scope) { | 754 Object* SerializeFunctionScope(Scope* scope) { |
| 750 HandleScope handle_scope; | 755 HandleScope handle_scope; |
| 751 | 756 |
| 752 Handle<JSArray> scope_info_list = Factory::NewJSArray(10); | 757 Handle<JSArray> scope_info_list = FACTORY->NewJSArray(10); |
| 753 int scope_info_length = 0; | 758 int scope_info_length = 0; |
| 754 | 759 |
| 755 // Saves some description of scope. It stores name and indexes of | 760 // Saves some description of scope. It stores name and indexes of |
| 756 // variables in the whole scope chain. Null-named slots delimit | 761 // variables in the whole scope chain. Null-named slots delimit |
| 757 // scopes of this chain. | 762 // scopes of this chain. |
| 758 Scope* outer_scope = scope->outer_scope(); | 763 Scope* outer_scope = scope->outer_scope(); |
| 759 if (outer_scope == NULL) { | 764 if (outer_scope == NULL) { |
| 760 return Heap::undefined_value(); | 765 return HEAP->undefined_value(); |
| 761 } | 766 } |
| 762 do { | 767 do { |
| 763 ZoneList<Variable*> list(10); | 768 ZoneList<Variable*> list(10); |
| 764 outer_scope->CollectUsedVariables(&list); | 769 outer_scope->CollectUsedVariables(&list); |
| 765 int j = 0; | 770 int j = 0; |
| 766 for (int i = 0; i < list.length(); i++) { | 771 for (int i = 0; i < list.length(); i++) { |
| 767 Variable* var1 = list[i]; | 772 Variable* var1 = list[i]; |
| 768 Slot* slot = var1->AsSlot(); | 773 Slot* slot = var1->AsSlot(); |
| 769 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 774 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 770 if (j != i) { | 775 if (j != i) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 790 list[i]->name()); | 795 list[i]->name()); |
| 791 scope_info_length++; | 796 scope_info_length++; |
| 792 SetElementNonStrict( | 797 SetElementNonStrict( |
| 793 scope_info_list, | 798 scope_info_list, |
| 794 scope_info_length, | 799 scope_info_length, |
| 795 Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index()))); | 800 Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index()))); |
| 796 scope_info_length++; | 801 scope_info_length++; |
| 797 } | 802 } |
| 798 SetElementNonStrict(scope_info_list, | 803 SetElementNonStrict(scope_info_list, |
| 799 scope_info_length, | 804 scope_info_length, |
| 800 Handle<Object>(Heap::null_value())); | 805 Handle<Object>(HEAP->null_value())); |
| 801 scope_info_length++; | 806 scope_info_length++; |
| 802 | 807 |
| 803 outer_scope = outer_scope->outer_scope(); | 808 outer_scope = outer_scope->outer_scope(); |
| 804 } while (outer_scope != NULL); | 809 } while (outer_scope != NULL); |
| 805 | 810 |
| 806 return *scope_info_list; | 811 return *scope_info_list; |
| 807 } | 812 } |
| 808 | 813 |
| 809 Handle<JSArray> result_; | 814 Handle<JSArray> result_; |
| 810 int len_; | 815 int len_; |
| 811 int current_parent_index_; | 816 int current_parent_index_; |
| 812 }; | 817 }; |
| 813 | 818 |
| 814 | 819 |
| 815 static FunctionInfoListener* active_function_info_listener = NULL; | |
| 816 | |
| 817 JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script, | 820 JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script, |
| 818 Handle<String> source) { | 821 Handle<String> source) { |
| 822 Isolate* isolate = Isolate::Current(); |
| 819 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 823 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
| 820 | 824 |
| 821 FunctionInfoListener listener; | 825 FunctionInfoListener listener; |
| 822 Handle<Object> original_source = Handle<Object>(script->source()); | 826 Handle<Object> original_source = Handle<Object>(script->source()); |
| 823 script->set_source(*source); | 827 script->set_source(*source); |
| 824 active_function_info_listener = &listener; | 828 isolate->set_active_function_info_listener(&listener); |
| 825 CompileScriptForTracker(script); | 829 CompileScriptForTracker(isolate, script); |
| 826 active_function_info_listener = NULL; | 830 isolate->set_active_function_info_listener(NULL); |
| 827 script->set_source(*original_source); | 831 script->set_source(*original_source); |
| 828 | 832 |
| 829 return *(listener.GetResult()); | 833 return *(listener.GetResult()); |
| 830 } | 834 } |
| 831 | 835 |
| 832 | 836 |
| 833 void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) { | 837 void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) { |
| 834 HandleScope scope; | 838 HandleScope scope; |
| 835 int len = Smi::cast(array->length())->value(); | 839 int len = Smi::cast(array->length())->value(); |
| 836 for (int i = 0; i < len; i++) { | 840 for (int i = 0; i < len; i++) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 // Post-visiting method that iterates over all collected references and | 886 // Post-visiting method that iterates over all collected references and |
| 883 // modifies them. | 887 // modifies them. |
| 884 void Replace(Code* substitution) { | 888 void Replace(Code* substitution) { |
| 885 for (int i = 0; i < rvalues_.length(); i++) { | 889 for (int i = 0; i < rvalues_.length(); i++) { |
| 886 *(rvalues_[i]) = substitution; | 890 *(rvalues_[i]) = substitution; |
| 887 } | 891 } |
| 888 Address substitution_entry = substitution->instruction_start(); | 892 Address substitution_entry = substitution->instruction_start(); |
| 889 for (int i = 0; i < reloc_infos_.length(); i++) { | 893 for (int i = 0; i < reloc_infos_.length(); i++) { |
| 890 reloc_infos_[i].set_target_address(substitution_entry, NULL); | 894 reloc_infos_[i].set_target_address(substitution_entry, NULL); |
| 891 // TODO(gc) more precise barrier. | 895 // TODO(gc) more precise barrier. |
| 892 IncrementalMarking::RecordWriteOf(substitution); | 896 // TODO(gc) ISOLATES MERGE: code object should have heap() accessor. |
| 897 substitution->GetHeap()->incremental_marking()->RecordWriteOf( |
| 898 substitution); |
| 893 } | 899 } |
| 894 for (int i = 0; i < code_entries_.length(); i++) { | 900 for (int i = 0; i < code_entries_.length(); i++) { |
| 895 Address entry = code_entries_[i]; | 901 Address entry = code_entries_[i]; |
| 896 Memory::Address_at(entry) = substitution_entry; | 902 Memory::Address_at(entry) = substitution_entry; |
| 897 } | 903 } |
| 898 } | 904 } |
| 899 | 905 |
| 900 private: | 906 private: |
| 901 Code* original_; | 907 Code* original_; |
| 902 ZoneList<Object**> rvalues_; | 908 ZoneList<Object**> rvalues_; |
| 903 ZoneList<RelocInfo> reloc_infos_; | 909 ZoneList<RelocInfo> reloc_infos_; |
| 904 ZoneList<Address> code_entries_; | 910 ZoneList<Address> code_entries_; |
| 905 }; | 911 }; |
| 906 | 912 |
| 907 | 913 |
| 908 // Finds all references to original and replaces them with substitution. | 914 // Finds all references to original and replaces them with substitution. |
| 909 static void ReplaceCodeObject(Code* original, Code* substitution) { | 915 static void ReplaceCodeObject(Code* original, Code* substitution) { |
| 910 ASSERT(!Heap::InNewSpace(substitution)); | 916 ASSERT(!HEAP->InNewSpace(substitution)); |
| 911 | 917 |
| 912 HeapIterator iterator; | 918 HeapIterator iterator; |
| 913 AssertNoAllocation no_allocations_please; | 919 AssertNoAllocation no_allocations_please; |
| 914 | 920 |
| 915 // A zone scope for ReferenceCollectorVisitor. | 921 // A zone scope for ReferenceCollectorVisitor. |
| 916 ZoneScope scope(DELETE_ON_EXIT); | 922 ZoneScope scope(DELETE_ON_EXIT); |
| 917 | 923 |
| 918 ReferenceCollectorVisitor visitor(original); | 924 ReferenceCollectorVisitor visitor(original); |
| 919 | 925 |
| 920 // Iterate over all roots. Stack frames may have pointer into original code, | 926 // Iterate over all roots. Stack frames may have pointer into original code, |
| 921 // so temporary replace the pointers with offset numbers | 927 // so temporary replace the pointers with offset numbers |
| 922 // in prologue/epilogue. | 928 // in prologue/epilogue. |
| 923 { | 929 { |
| 924 Heap::IterateStrongRoots(&visitor, VISIT_ALL); | 930 HEAP->IterateStrongRoots(&visitor, VISIT_ALL); |
| 925 } | 931 } |
| 926 | 932 |
| 927 // Now iterate over all pointers of all objects, including code_target | 933 // Now iterate over all pointers of all objects, including code_target |
| 928 // implicit pointers. | 934 // implicit pointers. |
| 929 for (HeapObject* obj = iterator.Next(); obj != NULL; obj = iterator.Next()) { | 935 for (HeapObject* obj = iterator.Next(); obj != NULL; obj = iterator.Next()) { |
| 930 obj->Iterate(&visitor); | 936 obj->Iterate(&visitor); |
| 931 } | 937 } |
| 932 | 938 |
| 933 visitor.Replace(substitution); | 939 visitor.Replace(substitution); |
| 934 } | 940 } |
| 935 | 941 |
| 936 | 942 |
| 937 // Check whether the code is natural function code (not a lazy-compile stub | 943 // Check whether the code is natural function code (not a lazy-compile stub |
| 938 // code). | 944 // code). |
| 939 static bool IsJSFunctionCode(Code* code) { | 945 static bool IsJSFunctionCode(Code* code) { |
| 940 return code->kind() == Code::FUNCTION; | 946 return code->kind() == Code::FUNCTION; |
| 941 } | 947 } |
| 942 | 948 |
| 943 | 949 |
| 944 // Returns true if an instance of candidate were inlined into function's code. | 950 // Returns true if an instance of candidate were inlined into function's code. |
| 945 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { | 951 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { |
| 946 AssertNoAllocation no_gc; | 952 AssertNoAllocation no_gc; |
| 947 | 953 |
| 948 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false; | 954 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false; |
| 949 | 955 |
| 950 DeoptimizationInputData* data = | 956 DeoptimizationInputData* data = |
| 951 DeoptimizationInputData::cast(function->code()->deoptimization_data()); | 957 DeoptimizationInputData::cast(function->code()->deoptimization_data()); |
| 952 | 958 |
| 953 if (data == Heap::empty_fixed_array()) return false; | 959 if (data == HEAP->empty_fixed_array()) return false; |
| 954 | 960 |
| 955 FixedArray* literals = data->LiteralArray(); | 961 FixedArray* literals = data->LiteralArray(); |
| 956 | 962 |
| 957 int inlined_count = data->InlinedFunctionCount()->value(); | 963 int inlined_count = data->InlinedFunctionCount()->value(); |
| 958 for (int i = 0; i < inlined_count; ++i) { | 964 for (int i = 0; i < inlined_count; ++i) { |
| 959 JSFunction* inlined = JSFunction::cast(literals->get(i)); | 965 JSFunction* inlined = JSFunction::cast(literals->get(i)); |
| 960 if (inlined->shared() == candidate) return true; | 966 if (inlined->shared() == candidate) return true; |
| 961 } | 967 } |
| 962 | 968 |
| 963 return false; | 969 return false; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 Deoptimizer::VisitAllOptimizedFunctions(&visitor); | 1001 Deoptimizer::VisitAllOptimizedFunctions(&visitor); |
| 996 } | 1002 } |
| 997 | 1003 |
| 998 | 1004 |
| 999 MaybeObject* LiveEdit::ReplaceFunctionCode( | 1005 MaybeObject* LiveEdit::ReplaceFunctionCode( |
| 1000 Handle<JSArray> new_compile_info_array, | 1006 Handle<JSArray> new_compile_info_array, |
| 1001 Handle<JSArray> shared_info_array) { | 1007 Handle<JSArray> shared_info_array) { |
| 1002 HandleScope scope; | 1008 HandleScope scope; |
| 1003 | 1009 |
| 1004 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { | 1010 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 1005 return Top::ThrowIllegalOperation(); | 1011 return Isolate::Current()->ThrowIllegalOperation(); |
| 1006 } | 1012 } |
| 1007 | 1013 |
| 1008 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); | 1014 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); |
| 1009 SharedInfoWrapper shared_info_wrapper(shared_info_array); | 1015 SharedInfoWrapper shared_info_wrapper(shared_info_array); |
| 1010 | 1016 |
| 1011 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); | 1017 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); |
| 1012 | 1018 |
| 1013 Heap::EnsureHeapIsIterable(); | 1019 HEAP->EnsureHeapIsIterable(); |
| 1014 | 1020 |
| 1015 if (IsJSFunctionCode(shared_info->code())) { | 1021 if (IsJSFunctionCode(shared_info->code())) { |
| 1016 ReplaceCodeObject(shared_info->code(), | 1022 ReplaceCodeObject(shared_info->code(), |
| 1017 *(compile_info_wrapper.GetFunctionCode())); | 1023 *(compile_info_wrapper.GetFunctionCode())); |
| 1018 Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo(); | 1024 Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo(); |
| 1019 if (code_scope_info->IsFixedArray()) { | 1025 if (code_scope_info->IsFixedArray()) { |
| 1020 shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info)); | 1026 shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info)); |
| 1021 } | 1027 } |
| 1022 } | 1028 } |
| 1023 | 1029 |
| 1024 if (shared_info->debug_info()->IsDebugInfo()) { | 1030 if (shared_info->debug_info()->IsDebugInfo()) { |
| 1025 Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info())); | 1031 Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info())); |
| 1026 Handle<Code> new_original_code = | 1032 Handle<Code> new_original_code = |
| 1027 Factory::CopyCode(compile_info_wrapper.GetFunctionCode()); | 1033 FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode()); |
| 1028 debug_info->set_original_code(*new_original_code); | 1034 debug_info->set_original_code(*new_original_code); |
| 1029 } | 1035 } |
| 1030 | 1036 |
| 1031 shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); | 1037 shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); |
| 1032 shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); | 1038 shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); |
| 1033 | 1039 |
| 1034 shared_info->set_construct_stub( | 1040 shared_info->set_construct_stub( |
| 1035 Builtins::builtin(Builtins::JSConstructStubGeneric)); | 1041 Isolate::Current()->builtins()->builtin( |
| 1042 Builtins::JSConstructStubGeneric)); |
| 1036 | 1043 |
| 1037 DeoptimizeDependentFunctions(*shared_info); | 1044 DeoptimizeDependentFunctions(*shared_info); |
| 1038 CompilationCache::Remove(shared_info); | 1045 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 1039 | 1046 |
| 1040 return Heap::undefined_value(); | 1047 return HEAP->undefined_value(); |
| 1041 } | 1048 } |
| 1042 | 1049 |
| 1043 | 1050 |
| 1044 MaybeObject* LiveEdit::FunctionSourceUpdated( | 1051 MaybeObject* LiveEdit::FunctionSourceUpdated( |
| 1045 Handle<JSArray> shared_info_array) { | 1052 Handle<JSArray> shared_info_array) { |
| 1046 HandleScope scope; | 1053 HandleScope scope; |
| 1047 | 1054 |
| 1048 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { | 1055 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 1049 return Top::ThrowIllegalOperation(); | 1056 return Isolate::Current()->ThrowIllegalOperation(); |
| 1050 } | 1057 } |
| 1051 | 1058 |
| 1052 SharedInfoWrapper shared_info_wrapper(shared_info_array); | 1059 SharedInfoWrapper shared_info_wrapper(shared_info_array); |
| 1053 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); | 1060 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); |
| 1054 | 1061 |
| 1055 DeoptimizeDependentFunctions(*shared_info); | 1062 DeoptimizeDependentFunctions(*shared_info); |
| 1056 CompilationCache::Remove(shared_info); | 1063 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 1057 | 1064 |
| 1058 return Heap::undefined_value(); | 1065 return HEAP->undefined_value(); |
| 1059 } | 1066 } |
| 1060 | 1067 |
| 1061 | 1068 |
| 1062 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, | 1069 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, |
| 1063 Handle<Object> script_handle) { | 1070 Handle<Object> script_handle) { |
| 1064 Handle<SharedFunctionInfo> shared_info = | 1071 Handle<SharedFunctionInfo> shared_info = |
| 1065 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); | 1072 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); |
| 1066 shared_info->set_script(*script_handle); | 1073 shared_info->set_script(*script_handle); |
| 1067 | 1074 |
| 1068 CompilationCache::Remove(shared_info); | 1075 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 1069 } | 1076 } |
| 1070 | 1077 |
| 1071 | 1078 |
| 1072 // For a script text change (defined as position_change_array), translates | 1079 // For a script text change (defined as position_change_array), translates |
| 1073 // position in unchanged text to position in changed text. | 1080 // position in unchanged text to position in changed text. |
| 1074 // Text change is a set of non-overlapping regions in text, that have changed | 1081 // Text change is a set of non-overlapping regions in text, that have changed |
| 1075 // their contents and length. It is specified as array of groups of 3 numbers: | 1082 // their contents and length. It is specified as array of groups of 3 numbers: |
| 1076 // (change_begin, change_end, change_end_new_position). | 1083 // (change_begin, change_end, change_end_new_position). |
| 1077 // Each group describes a change in text; groups are sorted by change_begin. | 1084 // Each group describes a change in text; groups are sorted by change_begin. |
| 1078 // Only position in text beyond any changes may be successfully translated. | 1085 // Only position in text beyond any changes may be successfully translated. |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1207 Vector<byte> buffer = buffer_writer.GetResult(); | 1214 Vector<byte> buffer = buffer_writer.GetResult(); |
| 1208 | 1215 |
| 1209 if (buffer.length() == code->relocation_size()) { | 1216 if (buffer.length() == code->relocation_size()) { |
| 1210 // Simply patch relocation area of code. | 1217 // Simply patch relocation area of code. |
| 1211 memcpy(code->relocation_start(), buffer.start(), buffer.length()); | 1218 memcpy(code->relocation_start(), buffer.start(), buffer.length()); |
| 1212 return code; | 1219 return code; |
| 1213 } else { | 1220 } else { |
| 1214 // Relocation info section now has different size. We cannot simply | 1221 // Relocation info section now has different size. We cannot simply |
| 1215 // rewrite it inside code object. Instead we have to create a new | 1222 // rewrite it inside code object. Instead we have to create a new |
| 1216 // code object. | 1223 // code object. |
| 1217 Handle<Code> result(Factory::CopyCode(code, buffer)); | 1224 Handle<Code> result(FACTORY->CopyCode(code, buffer)); |
| 1218 return result; | 1225 return result; |
| 1219 } | 1226 } |
| 1220 } | 1227 } |
| 1221 | 1228 |
| 1222 | 1229 |
| 1223 MaybeObject* LiveEdit::PatchFunctionPositions( | 1230 MaybeObject* LiveEdit::PatchFunctionPositions( |
| 1224 Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) { | 1231 Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) { |
| 1225 | 1232 |
| 1226 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { | 1233 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 1227 return Top::ThrowIllegalOperation(); | 1234 return Isolate::Current()->ThrowIllegalOperation(); |
| 1228 } | 1235 } |
| 1229 | 1236 |
| 1230 SharedInfoWrapper shared_info_wrapper(shared_info_array); | 1237 SharedInfoWrapper shared_info_wrapper(shared_info_array); |
| 1231 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo(); | 1238 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo(); |
| 1232 | 1239 |
| 1233 int old_function_start = info->start_position(); | 1240 int old_function_start = info->start_position(); |
| 1234 int new_function_start = TranslatePosition(old_function_start, | 1241 int new_function_start = TranslatePosition(old_function_start, |
| 1235 position_change_array); | 1242 position_change_array); |
| 1236 info->set_start_position(new_function_start); | 1243 info->set_start_position(new_function_start); |
| 1237 info->set_end_position(TranslatePosition(info->end_position(), | 1244 info->set_end_position(TranslatePosition(info->end_position(), |
| 1238 position_change_array)); | 1245 position_change_array)); |
| 1239 | 1246 |
| 1240 info->set_function_token_position( | 1247 info->set_function_token_position( |
| 1241 TranslatePosition(info->function_token_position(), | 1248 TranslatePosition(info->function_token_position(), |
| 1242 position_change_array)); | 1249 position_change_array)); |
| 1243 | 1250 |
| 1244 Heap::EnsureHeapIsIterable(); | 1251 HEAP->EnsureHeapIsIterable(); |
| 1245 | 1252 |
| 1246 if (IsJSFunctionCode(info->code())) { | 1253 if (IsJSFunctionCode(info->code())) { |
| 1247 // Patch relocation info section of the code. | 1254 // Patch relocation info section of the code. |
| 1248 Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()), | 1255 Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()), |
| 1249 position_change_array); | 1256 position_change_array); |
| 1250 if (*patched_code != info->code()) { | 1257 if (*patched_code != info->code()) { |
| 1251 // Replace all references to the code across the heap. In particular, | 1258 // Replace all references to the code across the heap. In particular, |
| 1252 // some stubs may refer to this code and this code may be being executed | 1259 // some stubs may refer to this code and this code may be being executed |
| 1253 // on stack (it is safe to substitute the code object on stack, because | 1260 // on stack (it is safe to substitute the code object on stack, because |
| 1254 // we only change the structure of rinfo and leave instructions | 1261 // we only change the structure of rinfo and leave instructions |
| 1255 // untouched). | 1262 // untouched). |
| 1256 ReplaceCodeObject(info->code(), *patched_code); | 1263 ReplaceCodeObject(info->code(), *patched_code); |
| 1257 } | 1264 } |
| 1258 } | 1265 } |
| 1259 | 1266 |
| 1260 return Heap::undefined_value(); | 1267 return HEAP->undefined_value(); |
| 1261 } | 1268 } |
| 1262 | 1269 |
| 1263 | 1270 |
| 1264 static Handle<Script> CreateScriptCopy(Handle<Script> original) { | 1271 static Handle<Script> CreateScriptCopy(Handle<Script> original) { |
| 1265 Handle<String> original_source(String::cast(original->source())); | 1272 Handle<String> original_source(String::cast(original->source())); |
| 1266 | 1273 |
| 1267 Handle<Script> copy = Factory::NewScript(original_source); | 1274 Handle<Script> copy = FACTORY->NewScript(original_source); |
| 1268 | 1275 |
| 1269 copy->set_name(original->name()); | 1276 copy->set_name(original->name()); |
| 1270 copy->set_line_offset(original->line_offset()); | 1277 copy->set_line_offset(original->line_offset()); |
| 1271 copy->set_column_offset(original->column_offset()); | 1278 copy->set_column_offset(original->column_offset()); |
| 1272 copy->set_data(original->data()); | 1279 copy->set_data(original->data()); |
| 1273 copy->set_type(original->type()); | 1280 copy->set_type(original->type()); |
| 1274 copy->set_context_data(original->context_data()); | 1281 copy->set_context_data(original->context_data()); |
| 1275 copy->set_compilation_type(original->compilation_type()); | 1282 copy->set_compilation_type(original->compilation_type()); |
| 1276 copy->set_eval_from_shared(original->eval_from_shared()); | 1283 copy->set_eval_from_shared(original->eval_from_shared()); |
| 1277 copy->set_eval_from_instructions_offset( | 1284 copy->set_eval_from_instructions_offset( |
| 1278 original->eval_from_instructions_offset()); | 1285 original->eval_from_instructions_offset()); |
| 1279 | 1286 |
| 1280 return copy; | 1287 return copy; |
| 1281 } | 1288 } |
| 1282 | 1289 |
| 1283 | 1290 |
| 1284 Object* LiveEdit::ChangeScriptSource(Handle<Script> original_script, | 1291 Object* LiveEdit::ChangeScriptSource(Handle<Script> original_script, |
| 1285 Handle<String> new_source, | 1292 Handle<String> new_source, |
| 1286 Handle<Object> old_script_name) { | 1293 Handle<Object> old_script_name) { |
| 1287 Handle<Object> old_script_object; | 1294 Handle<Object> old_script_object; |
| 1288 if (old_script_name->IsString()) { | 1295 if (old_script_name->IsString()) { |
| 1289 Handle<Script> old_script = CreateScriptCopy(original_script); | 1296 Handle<Script> old_script = CreateScriptCopy(original_script); |
| 1290 old_script->set_name(String::cast(*old_script_name)); | 1297 old_script->set_name(String::cast(*old_script_name)); |
| 1291 old_script_object = old_script; | 1298 old_script_object = old_script; |
| 1292 Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING); | 1299 Isolate::Current()->debugger()->OnAfterCompile( |
| 1300 old_script, Debugger::SEND_WHEN_DEBUGGING); |
| 1293 } else { | 1301 } else { |
| 1294 old_script_object = Handle<Object>(Heap::null_value()); | 1302 old_script_object = Handle<Object>(HEAP->null_value()); |
| 1295 } | 1303 } |
| 1296 | 1304 |
| 1297 original_script->set_source(*new_source); | 1305 original_script->set_source(*new_source); |
| 1298 | 1306 |
| 1299 // Drop line ends so that they will be recalculated. | 1307 // Drop line ends so that they will be recalculated. |
| 1300 original_script->set_line_ends(Heap::undefined_value()); | 1308 original_script->set_line_ends(HEAP->undefined_value()); |
| 1301 | 1309 |
| 1302 return *old_script_object; | 1310 return *old_script_object; |
| 1303 } | 1311 } |
| 1304 | 1312 |
| 1305 | 1313 |
| 1306 | 1314 |
| 1307 void LiveEdit::ReplaceRefToNestedFunction( | 1315 void LiveEdit::ReplaceRefToNestedFunction( |
| 1308 Handle<JSValue> parent_function_wrapper, | 1316 Handle<JSValue> parent_function_wrapper, |
| 1309 Handle<JSValue> orig_function_wrapper, | 1317 Handle<JSValue> orig_function_wrapper, |
| 1310 Handle<JSValue> subst_function_wrapper) { | 1318 Handle<JSValue> subst_function_wrapper) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 } | 1359 } |
| 1352 return false; | 1360 return false; |
| 1353 } | 1361 } |
| 1354 | 1362 |
| 1355 | 1363 |
| 1356 // Iterates over handler chain and removes all elements that are inside | 1364 // Iterates over handler chain and removes all elements that are inside |
| 1357 // frames being dropped. | 1365 // frames being dropped. |
| 1358 static bool FixTryCatchHandler(StackFrame* top_frame, | 1366 static bool FixTryCatchHandler(StackFrame* top_frame, |
| 1359 StackFrame* bottom_frame) { | 1367 StackFrame* bottom_frame) { |
| 1360 Address* pointer_address = | 1368 Address* pointer_address = |
| 1361 &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address)); | 1369 &Memory::Address_at(Isolate::Current()->get_address_from_id( |
| 1370 Isolate::k_handler_address)); |
| 1362 | 1371 |
| 1363 while (*pointer_address < top_frame->sp()) { | 1372 while (*pointer_address < top_frame->sp()) { |
| 1364 pointer_address = &Memory::Address_at(*pointer_address); | 1373 pointer_address = &Memory::Address_at(*pointer_address); |
| 1365 } | 1374 } |
| 1366 Address* above_frame_address = pointer_address; | 1375 Address* above_frame_address = pointer_address; |
| 1367 while (*pointer_address < bottom_frame->fp()) { | 1376 while (*pointer_address < bottom_frame->fp()) { |
| 1368 pointer_address = &Memory::Address_at(*pointer_address); | 1377 pointer_address = &Memory::Address_at(*pointer_address); |
| 1369 } | 1378 } |
| 1370 bool change = *above_frame_address != *pointer_address; | 1379 bool change = *above_frame_address != *pointer_address; |
| 1371 *above_frame_address = *pointer_address; | 1380 *above_frame_address = *pointer_address; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1386 return "Stack manipulations are not supported in this architecture."; | 1395 return "Stack manipulations are not supported in this architecture."; |
| 1387 } | 1396 } |
| 1388 | 1397 |
| 1389 StackFrame* pre_top_frame = frames[top_frame_index - 1]; | 1398 StackFrame* pre_top_frame = frames[top_frame_index - 1]; |
| 1390 StackFrame* top_frame = frames[top_frame_index]; | 1399 StackFrame* top_frame = frames[top_frame_index]; |
| 1391 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; | 1400 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; |
| 1392 | 1401 |
| 1393 ASSERT(bottom_js_frame->is_java_script()); | 1402 ASSERT(bottom_js_frame->is_java_script()); |
| 1394 | 1403 |
| 1395 // Check the nature of the top frame. | 1404 // Check the nature of the top frame. |
| 1396 if (pre_top_frame->code()->is_inline_cache_stub() && | 1405 Code* pre_top_frame_code = pre_top_frame->LookupCode(Isolate::Current()); |
| 1397 pre_top_frame->code()->ic_state() == DEBUG_BREAK) { | 1406 if (pre_top_frame_code->is_inline_cache_stub() && |
| 1407 pre_top_frame_code->ic_state() == DEBUG_BREAK) { |
| 1398 // OK, we can drop inline cache calls. | 1408 // OK, we can drop inline cache calls. |
| 1399 *mode = Debug::FRAME_DROPPED_IN_IC_CALL; | 1409 *mode = Debug::FRAME_DROPPED_IN_IC_CALL; |
| 1400 } else if (pre_top_frame->code() == Debug::debug_break_slot()) { | 1410 } else if (pre_top_frame_code == |
| 1411 Isolate::Current()->debug()->debug_break_slot()) { |
| 1401 // OK, we can drop debug break slot. | 1412 // OK, we can drop debug break slot. |
| 1402 *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; | 1413 *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; |
| 1403 } else if (pre_top_frame->code() == | 1414 } else if (pre_top_frame_code == |
| 1404 Builtins::builtin(Builtins::FrameDropper_LiveEdit)) { | 1415 Isolate::Current()->builtins()->builtin( |
| 1416 Builtins::FrameDropper_LiveEdit)) { |
| 1405 // OK, we can drop our own code. | 1417 // OK, we can drop our own code. |
| 1406 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; | 1418 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; |
| 1407 } else if (pre_top_frame->code()->kind() == Code::STUB && | 1419 } else if (pre_top_frame_code->kind() == Code::STUB && |
| 1408 pre_top_frame->code()->major_key()) { | 1420 pre_top_frame_code->major_key()) { |
| 1409 // Entry from our unit tests, it's fine, we support this case. | 1421 // Entry from our unit tests, it's fine, we support this case. |
| 1410 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; | 1422 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; |
| 1411 } else { | 1423 } else { |
| 1412 return "Unknown structure of stack above changing function"; | 1424 return "Unknown structure of stack above changing function"; |
| 1413 } | 1425 } |
| 1414 | 1426 |
| 1415 Address unused_stack_top = top_frame->sp(); | 1427 Address unused_stack_top = top_frame->sp(); |
| 1416 Address unused_stack_bottom = bottom_js_frame->fp() | 1428 Address unused_stack_bottom = bottom_js_frame->fp() |
| 1417 - Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame. | 1429 - Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame. |
| 1418 + kPointerSize; // Bigger address end is exclusive. | 1430 + kPointerSize; // Bigger address end is exclusive. |
| 1419 | 1431 |
| 1420 if (unused_stack_top > unused_stack_bottom) { | 1432 if (unused_stack_top > unused_stack_bottom) { |
| 1421 return "Not enough space for frame dropper frame"; | 1433 return "Not enough space for frame dropper frame"; |
| 1422 } | 1434 } |
| 1423 | 1435 |
| 1424 // Committing now. After this point we should return only NULL value. | 1436 // Committing now. After this point we should return only NULL value. |
| 1425 | 1437 |
| 1426 FixTryCatchHandler(pre_top_frame, bottom_js_frame); | 1438 FixTryCatchHandler(pre_top_frame, bottom_js_frame); |
| 1427 // Make sure FixTryCatchHandler is idempotent. | 1439 // Make sure FixTryCatchHandler is idempotent. |
| 1428 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); | 1440 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); |
| 1429 | 1441 |
| 1430 Handle<Code> code(Builtins::builtin(Builtins::FrameDropper_LiveEdit)); | 1442 Handle<Code> code(Isolate::Current()->builtins()->builtin( |
| 1443 Builtins::FrameDropper_LiveEdit)); |
| 1431 top_frame->set_pc(code->entry()); | 1444 top_frame->set_pc(code->entry()); |
| 1432 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); | 1445 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); |
| 1433 | 1446 |
| 1434 *restarter_frame_function_pointer = | 1447 *restarter_frame_function_pointer = |
| 1435 Debug::SetUpFrameDropperFrame(bottom_js_frame, code); | 1448 Debug::SetUpFrameDropperFrame(bottom_js_frame, code); |
| 1436 | 1449 |
| 1437 ASSERT((**restarter_frame_function_pointer)->IsJSFunction()); | 1450 ASSERT((**restarter_frame_function_pointer)->IsJSFunction()); |
| 1438 | 1451 |
| 1439 for (Address a = unused_stack_top; | 1452 for (Address a = unused_stack_top; |
| 1440 a < unused_stack_bottom; | 1453 a < unused_stack_bottom; |
| 1441 a += kPointerSize) { | 1454 a += kPointerSize) { |
| 1442 Memory::Object_at(a) = Smi::FromInt(0); | 1455 Memory::Object_at(a) = Smi::FromInt(0); |
| 1443 } | 1456 } |
| 1444 | 1457 |
| 1445 return NULL; | 1458 return NULL; |
| 1446 } | 1459 } |
| 1447 | 1460 |
| 1448 | 1461 |
| 1449 static bool IsDropableFrame(StackFrame* frame) { | 1462 static bool IsDropableFrame(StackFrame* frame) { |
| 1450 return !frame->is_exit(); | 1463 return !frame->is_exit(); |
| 1451 } | 1464 } |
| 1452 | 1465 |
| 1453 // Fills result array with statuses of functions. Modifies the stack | 1466 // Fills result array with statuses of functions. Modifies the stack |
| 1454 // removing all listed function if possible and if do_drop is true. | 1467 // removing all listed function if possible and if do_drop is true. |
| 1455 static const char* DropActivationsInActiveThread( | 1468 static const char* DropActivationsInActiveThread( |
| 1456 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) { | 1469 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) { |
| 1457 | 1470 Debug* debug = Isolate::Current()->debug(); |
| 1458 ZoneScope scope(DELETE_ON_EXIT); | 1471 ZoneScope scope(DELETE_ON_EXIT); |
| 1459 Vector<StackFrame*> frames = CreateStackMap(); | 1472 Vector<StackFrame*> frames = CreateStackMap(); |
| 1460 | 1473 |
| 1461 int array_len = Smi::cast(shared_info_array->length())->value(); | 1474 int array_len = Smi::cast(shared_info_array->length())->value(); |
| 1462 | 1475 |
| 1463 int top_frame_index = -1; | 1476 int top_frame_index = -1; |
| 1464 int frame_index = 0; | 1477 int frame_index = 0; |
| 1465 for (; frame_index < frames.length(); frame_index++) { | 1478 for (; frame_index < frames.length(); frame_index++) { |
| 1466 StackFrame* frame = frames[frame_index]; | 1479 StackFrame* frame = frames[frame_index]; |
| 1467 if (frame->id() == Debug::break_frame_id()) { | 1480 if (frame->id() == debug->break_frame_id()) { |
| 1468 top_frame_index = frame_index; | 1481 top_frame_index = frame_index; |
| 1469 break; | 1482 break; |
| 1470 } | 1483 } |
| 1471 if (CheckActivation(shared_info_array, result, frame, | 1484 if (CheckActivation(shared_info_array, result, frame, |
| 1472 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { | 1485 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
| 1473 // We are still above break_frame. It is not a target frame, | 1486 // We are still above break_frame. It is not a target frame, |
| 1474 // it is a problem. | 1487 // it is a problem. |
| 1475 return "Debugger mark-up on stack is not found"; | 1488 return "Debugger mark-up on stack is not found"; |
| 1476 } | 1489 } |
| 1477 } | 1490 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 } | 1547 } |
| 1535 | 1548 |
| 1536 // Adjust break_frame after some frames has been dropped. | 1549 // Adjust break_frame after some frames has been dropped. |
| 1537 StackFrame::Id new_id = StackFrame::NO_ID; | 1550 StackFrame::Id new_id = StackFrame::NO_ID; |
| 1538 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { | 1551 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { |
| 1539 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) { | 1552 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) { |
| 1540 new_id = frames[i]->id(); | 1553 new_id = frames[i]->id(); |
| 1541 break; | 1554 break; |
| 1542 } | 1555 } |
| 1543 } | 1556 } |
| 1544 Debug::FramesHaveBeenDropped(new_id, drop_mode, | 1557 debug->FramesHaveBeenDropped(new_id, drop_mode, |
| 1545 restarter_frame_function_pointer); | 1558 restarter_frame_function_pointer); |
| 1546 | 1559 |
| 1547 // Replace "blocked on active" with "replaced on active" status. | 1560 // Replace "blocked on active" with "replaced on active" status. |
| 1548 for (int i = 0; i < array_len; i++) { | 1561 for (int i = 0; i < array_len; i++) { |
| 1549 if (result->GetElement(i) == | 1562 if (result->GetElement(i) == |
| 1550 Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { | 1563 Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { |
| 1551 Handle<Object> replaced( | 1564 Handle<Object> replaced( |
| 1552 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK)); | 1565 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK)); |
| 1553 SetElementNonStrict(result, i, replaced); | 1566 SetElementNonStrict(result, i, replaced); |
| 1554 } | 1567 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1579 Handle<JSArray> shared_info_array_; | 1592 Handle<JSArray> shared_info_array_; |
| 1580 Handle<JSArray> result_; | 1593 Handle<JSArray> result_; |
| 1581 bool has_blocked_functions_; | 1594 bool has_blocked_functions_; |
| 1582 }; | 1595 }; |
| 1583 | 1596 |
| 1584 | 1597 |
| 1585 Handle<JSArray> LiveEdit::CheckAndDropActivations( | 1598 Handle<JSArray> LiveEdit::CheckAndDropActivations( |
| 1586 Handle<JSArray> shared_info_array, bool do_drop) { | 1599 Handle<JSArray> shared_info_array, bool do_drop) { |
| 1587 int len = Smi::cast(shared_info_array->length())->value(); | 1600 int len = Smi::cast(shared_info_array->length())->value(); |
| 1588 | 1601 |
| 1589 Handle<JSArray> result = Factory::NewJSArray(len); | 1602 Handle<JSArray> result = FACTORY->NewJSArray(len); |
| 1590 | 1603 |
| 1591 // Fill the default values. | 1604 // Fill the default values. |
| 1592 for (int i = 0; i < len; i++) { | 1605 for (int i = 0; i < len; i++) { |
| 1593 SetElementNonStrict( | 1606 SetElementNonStrict( |
| 1594 result, | 1607 result, |
| 1595 i, | 1608 i, |
| 1596 Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH))); | 1609 Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH))); |
| 1597 } | 1610 } |
| 1598 | 1611 |
| 1599 | 1612 |
| 1600 // First check inactive threads. Fail if some functions are blocked there. | 1613 // First check inactive threads. Fail if some functions are blocked there. |
| 1601 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, | 1614 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, |
| 1602 result); | 1615 result); |
| 1603 ThreadManager::IterateArchivedThreads(&inactive_threads_checker); | 1616 Isolate::Current()->thread_manager()->IterateArchivedThreads( |
| 1617 &inactive_threads_checker); |
| 1604 if (inactive_threads_checker.HasBlockedFunctions()) { | 1618 if (inactive_threads_checker.HasBlockedFunctions()) { |
| 1605 return result; | 1619 return result; |
| 1606 } | 1620 } |
| 1607 | 1621 |
| 1608 // Try to drop activations from the current stack. | 1622 // Try to drop activations from the current stack. |
| 1609 const char* error_message = | 1623 const char* error_message = |
| 1610 DropActivationsInActiveThread(shared_info_array, result, do_drop); | 1624 DropActivationsInActiveThread(shared_info_array, result, do_drop); |
| 1611 if (error_message != NULL) { | 1625 if (error_message != NULL) { |
| 1612 // Add error message as an array extra element. | 1626 // Add error message as an array extra element. |
| 1613 Vector<const char> vector_message(error_message, StrLength(error_message)); | 1627 Vector<const char> vector_message(error_message, StrLength(error_message)); |
| 1614 Handle<String> str = Factory::NewStringFromAscii(vector_message); | 1628 Handle<String> str = FACTORY->NewStringFromAscii(vector_message); |
| 1615 SetElementNonStrict(result, len, str); | 1629 SetElementNonStrict(result, len, str); |
| 1616 } | 1630 } |
| 1617 return result; | 1631 return result; |
| 1618 } | 1632 } |
| 1619 | 1633 |
| 1620 | 1634 |
| 1621 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { | 1635 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, |
| 1622 if (active_function_info_listener != NULL) { | 1636 FunctionLiteral* fun) |
| 1623 active_function_info_listener->FunctionStarted(fun); | 1637 : isolate_(isolate) { |
| 1638 if (isolate_->active_function_info_listener() != NULL) { |
| 1639 isolate_->active_function_info_listener()->FunctionStarted(fun); |
| 1624 } | 1640 } |
| 1625 } | 1641 } |
| 1626 | 1642 |
| 1627 | 1643 |
| 1628 LiveEditFunctionTracker::~LiveEditFunctionTracker() { | 1644 LiveEditFunctionTracker::~LiveEditFunctionTracker() { |
| 1629 if (active_function_info_listener != NULL) { | 1645 if (isolate_->active_function_info_listener() != NULL) { |
| 1630 active_function_info_listener->FunctionDone(); | 1646 isolate_->active_function_info_listener()->FunctionDone(); |
| 1631 } | 1647 } |
| 1632 } | 1648 } |
| 1633 | 1649 |
| 1634 | 1650 |
| 1635 void LiveEditFunctionTracker::RecordFunctionInfo( | 1651 void LiveEditFunctionTracker::RecordFunctionInfo( |
| 1636 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { | 1652 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { |
| 1637 if (active_function_info_listener != NULL) { | 1653 if (isolate_->active_function_info_listener() != NULL) { |
| 1638 active_function_info_listener->FunctionInfo(info, lit->scope()); | 1654 isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope()); |
| 1639 } | 1655 } |
| 1640 } | 1656 } |
| 1641 | 1657 |
| 1642 | 1658 |
| 1643 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { | 1659 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { |
| 1644 active_function_info_listener->FunctionCode(code); | 1660 isolate_->active_function_info_listener()->FunctionCode(code); |
| 1645 } | 1661 } |
| 1646 | 1662 |
| 1647 | 1663 |
| 1648 bool LiveEditFunctionTracker::IsActive() { | 1664 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { |
| 1649 return active_function_info_listener != NULL; | 1665 return isolate->active_function_info_listener() != NULL; |
| 1650 } | 1666 } |
| 1651 | 1667 |
| 1652 | 1668 |
| 1653 #else // ENABLE_DEBUGGER_SUPPORT | 1669 #else // ENABLE_DEBUGGER_SUPPORT |
| 1654 | 1670 |
| 1655 // This ifdef-else-endif section provides working or stub implementation of | 1671 // This ifdef-else-endif section provides working or stub implementation of |
| 1656 // LiveEditFunctionTracker. | 1672 // LiveEditFunctionTracker. |
| 1657 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { | 1673 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, |
| 1674 FunctionLiteral* fun) { |
| 1658 } | 1675 } |
| 1659 | 1676 |
| 1660 | 1677 |
| 1661 LiveEditFunctionTracker::~LiveEditFunctionTracker() { | 1678 LiveEditFunctionTracker::~LiveEditFunctionTracker() { |
| 1662 } | 1679 } |
| 1663 | 1680 |
| 1664 | 1681 |
| 1665 void LiveEditFunctionTracker::RecordFunctionInfo( | 1682 void LiveEditFunctionTracker::RecordFunctionInfo( |
| 1666 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { | 1683 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { |
| 1667 } | 1684 } |
| 1668 | 1685 |
| 1669 | 1686 |
| 1670 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { | 1687 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { |
| 1671 } | 1688 } |
| 1672 | 1689 |
| 1673 | 1690 |
| 1674 bool LiveEditFunctionTracker::IsActive() { | 1691 bool LiveEditFunctionTracker::IsActive() { |
| 1675 return false; | 1692 return false; |
| 1676 } | 1693 } |
| 1677 | 1694 |
| 1678 #endif // ENABLE_DEBUGGER_SUPPORT | 1695 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1679 | 1696 |
| 1680 | 1697 |
| 1681 | 1698 |
| 1682 } } // namespace v8::internal | 1699 } } // namespace v8::internal |
| OLD | NEW |