| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 private: | 902 private: |
| 899 Code* original_; | 903 Code* original_; |
| 900 ZoneList<Object**> rvalues_; | 904 ZoneList<Object**> rvalues_; |
| 901 ZoneList<RelocInfo> reloc_infos_; | 905 ZoneList<RelocInfo> reloc_infos_; |
| 902 ZoneList<Address> code_entries_; | 906 ZoneList<Address> code_entries_; |
| 903 }; | 907 }; |
| 904 | 908 |
| 905 | 909 |
| 906 // Finds all references to original and replaces them with substitution. | 910 // Finds all references to original and replaces them with substitution. |
| 907 static void ReplaceCodeObject(Code* original, Code* substitution) { | 911 static void ReplaceCodeObject(Code* original, Code* substitution) { |
| 908 ASSERT(!Heap::InNewSpace(substitution)); | 912 ASSERT(!HEAP->InNewSpace(substitution)); |
| 909 | 913 |
| 910 AssertNoAllocation no_allocations_please; | 914 AssertNoAllocation no_allocations_please; |
| 911 | 915 |
| 912 // A zone scope for ReferenceCollectorVisitor. | 916 // A zone scope for ReferenceCollectorVisitor. |
| 913 ZoneScope scope(DELETE_ON_EXIT); | 917 ZoneScope scope(DELETE_ON_EXIT); |
| 914 | 918 |
| 915 ReferenceCollectorVisitor visitor(original); | 919 ReferenceCollectorVisitor visitor(original); |
| 916 | 920 |
| 917 // Iterate over all roots. Stack frames may have pointer into original code, | 921 // Iterate over all roots. Stack frames may have pointer into original code, |
| 918 // so temporary replace the pointers with offset numbers | 922 // so temporary replace the pointers with offset numbers |
| 919 // in prologue/epilogue. | 923 // in prologue/epilogue. |
| 920 { | 924 { |
| 921 Heap::IterateStrongRoots(&visitor, VISIT_ALL); | 925 HEAP->IterateStrongRoots(&visitor, VISIT_ALL); |
| 922 } | 926 } |
| 923 | 927 |
| 924 // Now iterate over all pointers of all objects, including code_target | 928 // Now iterate over all pointers of all objects, including code_target |
| 925 // implicit pointers. | 929 // implicit pointers. |
| 926 HeapIterator iterator; | 930 HeapIterator iterator; |
| 927 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 931 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
| 928 obj->Iterate(&visitor); | 932 obj->Iterate(&visitor); |
| 929 } | 933 } |
| 930 | 934 |
| 931 visitor.Replace(substitution); | 935 visitor.Replace(substitution); |
| 932 } | 936 } |
| 933 | 937 |
| 934 | 938 |
| 935 // Check whether the code is natural function code (not a lazy-compile stub | 939 // Check whether the code is natural function code (not a lazy-compile stub |
| 936 // code). | 940 // code). |
| 937 static bool IsJSFunctionCode(Code* code) { | 941 static bool IsJSFunctionCode(Code* code) { |
| 938 return code->kind() == Code::FUNCTION; | 942 return code->kind() == Code::FUNCTION; |
| 939 } | 943 } |
| 940 | 944 |
| 941 | 945 |
| 942 // Returns true if an instance of candidate were inlined into function's code. | 946 // Returns true if an instance of candidate were inlined into function's code. |
| 943 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { | 947 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { |
| 944 AssertNoAllocation no_gc; | 948 AssertNoAllocation no_gc; |
| 945 | 949 |
| 946 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false; | 950 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false; |
| 947 | 951 |
| 948 DeoptimizationInputData* data = | 952 DeoptimizationInputData* data = |
| 949 DeoptimizationInputData::cast(function->code()->deoptimization_data()); | 953 DeoptimizationInputData::cast(function->code()->deoptimization_data()); |
| 950 | 954 |
| 951 if (data == Heap::empty_fixed_array()) return false; | 955 if (data == HEAP->empty_fixed_array()) return false; |
| 952 | 956 |
| 953 FixedArray* literals = data->LiteralArray(); | 957 FixedArray* literals = data->LiteralArray(); |
| 954 | 958 |
| 955 int inlined_count = data->InlinedFunctionCount()->value(); | 959 int inlined_count = data->InlinedFunctionCount()->value(); |
| 956 for (int i = 0; i < inlined_count; ++i) { | 960 for (int i = 0; i < inlined_count; ++i) { |
| 957 JSFunction* inlined = JSFunction::cast(literals->get(i)); | 961 JSFunction* inlined = JSFunction::cast(literals->get(i)); |
| 958 if (inlined->shared() == candidate) return true; | 962 if (inlined->shared() == candidate) return true; |
| 959 } | 963 } |
| 960 | 964 |
| 961 return false; | 965 return false; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 993 Deoptimizer::VisitAllOptimizedFunctions(&visitor); | 997 Deoptimizer::VisitAllOptimizedFunctions(&visitor); |
| 994 } | 998 } |
| 995 | 999 |
| 996 | 1000 |
| 997 MaybeObject* LiveEdit::ReplaceFunctionCode( | 1001 MaybeObject* LiveEdit::ReplaceFunctionCode( |
| 998 Handle<JSArray> new_compile_info_array, | 1002 Handle<JSArray> new_compile_info_array, |
| 999 Handle<JSArray> shared_info_array) { | 1003 Handle<JSArray> shared_info_array) { |
| 1000 HandleScope scope; | 1004 HandleScope scope; |
| 1001 | 1005 |
| 1002 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { | 1006 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 1003 return Top::ThrowIllegalOperation(); | 1007 return Isolate::Current()->ThrowIllegalOperation(); |
| 1004 } | 1008 } |
| 1005 | 1009 |
| 1006 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); | 1010 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); |
| 1007 SharedInfoWrapper shared_info_wrapper(shared_info_array); | 1011 SharedInfoWrapper shared_info_wrapper(shared_info_array); |
| 1008 | 1012 |
| 1009 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); | 1013 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); |
| 1010 | 1014 |
| 1011 if (IsJSFunctionCode(shared_info->code())) { | 1015 if (IsJSFunctionCode(shared_info->code())) { |
| 1012 ReplaceCodeObject(shared_info->code(), | 1016 ReplaceCodeObject(shared_info->code(), |
| 1013 *(compile_info_wrapper.GetFunctionCode())); | 1017 *(compile_info_wrapper.GetFunctionCode())); |
| 1014 Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo(); | 1018 Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo(); |
| 1015 if (code_scope_info->IsFixedArray()) { | 1019 if (code_scope_info->IsFixedArray()) { |
| 1016 shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info)); | 1020 shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info)); |
| 1017 } | 1021 } |
| 1018 } | 1022 } |
| 1019 | 1023 |
| 1020 if (shared_info->debug_info()->IsDebugInfo()) { | 1024 if (shared_info->debug_info()->IsDebugInfo()) { |
| 1021 Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info())); | 1025 Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info())); |
| 1022 Handle<Code> new_original_code = | 1026 Handle<Code> new_original_code = |
| 1023 Factory::CopyCode(compile_info_wrapper.GetFunctionCode()); | 1027 FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode()); |
| 1024 debug_info->set_original_code(*new_original_code); | 1028 debug_info->set_original_code(*new_original_code); |
| 1025 } | 1029 } |
| 1026 | 1030 |
| 1027 shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); | 1031 shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); |
| 1028 shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); | 1032 shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); |
| 1029 | 1033 |
| 1030 shared_info->set_construct_stub( | 1034 shared_info->set_construct_stub( |
| 1031 Builtins::builtin(Builtins::JSConstructStubGeneric)); | 1035 Isolate::Current()->builtins()->builtin( |
| 1036 Builtins::JSConstructStubGeneric)); |
| 1032 | 1037 |
| 1033 DeoptimizeDependentFunctions(*shared_info); | 1038 DeoptimizeDependentFunctions(*shared_info); |
| 1034 CompilationCache::Remove(shared_info); | 1039 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 1035 | 1040 |
| 1036 return Heap::undefined_value(); | 1041 return HEAP->undefined_value(); |
| 1037 } | 1042 } |
| 1038 | 1043 |
| 1039 | 1044 |
| 1040 MaybeObject* LiveEdit::FunctionSourceUpdated( | 1045 MaybeObject* LiveEdit::FunctionSourceUpdated( |
| 1041 Handle<JSArray> shared_info_array) { | 1046 Handle<JSArray> shared_info_array) { |
| 1042 HandleScope scope; | 1047 HandleScope scope; |
| 1043 | 1048 |
| 1044 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { | 1049 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 1045 return Top::ThrowIllegalOperation(); | 1050 return Isolate::Current()->ThrowIllegalOperation(); |
| 1046 } | 1051 } |
| 1047 | 1052 |
| 1048 SharedInfoWrapper shared_info_wrapper(shared_info_array); | 1053 SharedInfoWrapper shared_info_wrapper(shared_info_array); |
| 1049 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); | 1054 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); |
| 1050 | 1055 |
| 1051 DeoptimizeDependentFunctions(*shared_info); | 1056 DeoptimizeDependentFunctions(*shared_info); |
| 1052 CompilationCache::Remove(shared_info); | 1057 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 1053 | 1058 |
| 1054 return Heap::undefined_value(); | 1059 return HEAP->undefined_value(); |
| 1055 } | 1060 } |
| 1056 | 1061 |
| 1057 | 1062 |
| 1058 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, | 1063 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, |
| 1059 Handle<Object> script_handle) { | 1064 Handle<Object> script_handle) { |
| 1060 Handle<SharedFunctionInfo> shared_info = | 1065 Handle<SharedFunctionInfo> shared_info = |
| 1061 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); | 1066 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); |
| 1062 shared_info->set_script(*script_handle); | 1067 shared_info->set_script(*script_handle); |
| 1063 | 1068 |
| 1064 CompilationCache::Remove(shared_info); | 1069 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 1065 } | 1070 } |
| 1066 | 1071 |
| 1067 | 1072 |
| 1068 // For a script text change (defined as position_change_array), translates | 1073 // For a script text change (defined as position_change_array), translates |
| 1069 // position in unchanged text to position in changed text. | 1074 // position in unchanged text to position in changed text. |
| 1070 // Text change is a set of non-overlapping regions in text, that have changed | 1075 // Text change is a set of non-overlapping regions in text, that have changed |
| 1071 // their contents and length. It is specified as array of groups of 3 numbers: | 1076 // their contents and length. It is specified as array of groups of 3 numbers: |
| 1072 // (change_begin, change_end, change_end_new_position). | 1077 // (change_begin, change_end, change_end_new_position). |
| 1073 // Each group describes a change in text; groups are sorted by change_begin. | 1078 // Each group describes a change in text; groups are sorted by change_begin. |
| 1074 // Only position in text beyond any changes may be successfully translated. | 1079 // Only position in text beyond any changes may be successfully translated. |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1202 Vector<byte> buffer = buffer_writer.GetResult(); | 1207 Vector<byte> buffer = buffer_writer.GetResult(); |
| 1203 | 1208 |
| 1204 if (buffer.length() == code->relocation_size()) { | 1209 if (buffer.length() == code->relocation_size()) { |
| 1205 // Simply patch relocation area of code. | 1210 // Simply patch relocation area of code. |
| 1206 memcpy(code->relocation_start(), buffer.start(), buffer.length()); | 1211 memcpy(code->relocation_start(), buffer.start(), buffer.length()); |
| 1207 return code; | 1212 return code; |
| 1208 } else { | 1213 } else { |
| 1209 // Relocation info section now has different size. We cannot simply | 1214 // Relocation info section now has different size. We cannot simply |
| 1210 // rewrite it inside code object. Instead we have to create a new | 1215 // rewrite it inside code object. Instead we have to create a new |
| 1211 // code object. | 1216 // code object. |
| 1212 Handle<Code> result(Factory::CopyCode(code, buffer)); | 1217 Handle<Code> result(FACTORY->CopyCode(code, buffer)); |
| 1213 return result; | 1218 return result; |
| 1214 } | 1219 } |
| 1215 } | 1220 } |
| 1216 | 1221 |
| 1217 | 1222 |
| 1218 MaybeObject* LiveEdit::PatchFunctionPositions( | 1223 MaybeObject* LiveEdit::PatchFunctionPositions( |
| 1219 Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) { | 1224 Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) { |
| 1220 | 1225 |
| 1221 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { | 1226 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 1222 return Top::ThrowIllegalOperation(); | 1227 return Isolate::Current()->ThrowIllegalOperation(); |
| 1223 } | 1228 } |
| 1224 | 1229 |
| 1225 SharedInfoWrapper shared_info_wrapper(shared_info_array); | 1230 SharedInfoWrapper shared_info_wrapper(shared_info_array); |
| 1226 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo(); | 1231 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo(); |
| 1227 | 1232 |
| 1228 int old_function_start = info->start_position(); | 1233 int old_function_start = info->start_position(); |
| 1229 int new_function_start = TranslatePosition(old_function_start, | 1234 int new_function_start = TranslatePosition(old_function_start, |
| 1230 position_change_array); | 1235 position_change_array); |
| 1231 info->set_start_position(new_function_start); | 1236 info->set_start_position(new_function_start); |
| 1232 info->set_end_position(TranslatePosition(info->end_position(), | 1237 info->set_end_position(TranslatePosition(info->end_position(), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1243 if (*patched_code != info->code()) { | 1248 if (*patched_code != info->code()) { |
| 1244 // Replace all references to the code across the heap. In particular, | 1249 // Replace all references to the code across the heap. In particular, |
| 1245 // some stubs may refer to this code and this code may be being executed | 1250 // some stubs may refer to this code and this code may be being executed |
| 1246 // on stack (it is safe to substitute the code object on stack, because | 1251 // on stack (it is safe to substitute the code object on stack, because |
| 1247 // we only change the structure of rinfo and leave instructions | 1252 // we only change the structure of rinfo and leave instructions |
| 1248 // untouched). | 1253 // untouched). |
| 1249 ReplaceCodeObject(info->code(), *patched_code); | 1254 ReplaceCodeObject(info->code(), *patched_code); |
| 1250 } | 1255 } |
| 1251 } | 1256 } |
| 1252 | 1257 |
| 1253 return Heap::undefined_value(); | 1258 return HEAP->undefined_value(); |
| 1254 } | 1259 } |
| 1255 | 1260 |
| 1256 | 1261 |
| 1257 static Handle<Script> CreateScriptCopy(Handle<Script> original) { | 1262 static Handle<Script> CreateScriptCopy(Handle<Script> original) { |
| 1258 Handle<String> original_source(String::cast(original->source())); | 1263 Handle<String> original_source(String::cast(original->source())); |
| 1259 | 1264 |
| 1260 Handle<Script> copy = Factory::NewScript(original_source); | 1265 Handle<Script> copy = FACTORY->NewScript(original_source); |
| 1261 | 1266 |
| 1262 copy->set_name(original->name()); | 1267 copy->set_name(original->name()); |
| 1263 copy->set_line_offset(original->line_offset()); | 1268 copy->set_line_offset(original->line_offset()); |
| 1264 copy->set_column_offset(original->column_offset()); | 1269 copy->set_column_offset(original->column_offset()); |
| 1265 copy->set_data(original->data()); | 1270 copy->set_data(original->data()); |
| 1266 copy->set_type(original->type()); | 1271 copy->set_type(original->type()); |
| 1267 copy->set_context_data(original->context_data()); | 1272 copy->set_context_data(original->context_data()); |
| 1268 copy->set_compilation_type(original->compilation_type()); | 1273 copy->set_compilation_type(original->compilation_type()); |
| 1269 copy->set_eval_from_shared(original->eval_from_shared()); | 1274 copy->set_eval_from_shared(original->eval_from_shared()); |
| 1270 copy->set_eval_from_instructions_offset( | 1275 copy->set_eval_from_instructions_offset( |
| 1271 original->eval_from_instructions_offset()); | 1276 original->eval_from_instructions_offset()); |
| 1272 | 1277 |
| 1273 return copy; | 1278 return copy; |
| 1274 } | 1279 } |
| 1275 | 1280 |
| 1276 | 1281 |
| 1277 Object* LiveEdit::ChangeScriptSource(Handle<Script> original_script, | 1282 Object* LiveEdit::ChangeScriptSource(Handle<Script> original_script, |
| 1278 Handle<String> new_source, | 1283 Handle<String> new_source, |
| 1279 Handle<Object> old_script_name) { | 1284 Handle<Object> old_script_name) { |
| 1280 Handle<Object> old_script_object; | 1285 Handle<Object> old_script_object; |
| 1281 if (old_script_name->IsString()) { | 1286 if (old_script_name->IsString()) { |
| 1282 Handle<Script> old_script = CreateScriptCopy(original_script); | 1287 Handle<Script> old_script = CreateScriptCopy(original_script); |
| 1283 old_script->set_name(String::cast(*old_script_name)); | 1288 old_script->set_name(String::cast(*old_script_name)); |
| 1284 old_script_object = old_script; | 1289 old_script_object = old_script; |
| 1285 Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING); | 1290 Isolate::Current()->debugger()->OnAfterCompile( |
| 1291 old_script, Debugger::SEND_WHEN_DEBUGGING); |
| 1286 } else { | 1292 } else { |
| 1287 old_script_object = Handle<Object>(Heap::null_value()); | 1293 old_script_object = Handle<Object>(HEAP->null_value()); |
| 1288 } | 1294 } |
| 1289 | 1295 |
| 1290 original_script->set_source(*new_source); | 1296 original_script->set_source(*new_source); |
| 1291 | 1297 |
| 1292 // Drop line ends so that they will be recalculated. | 1298 // Drop line ends so that they will be recalculated. |
| 1293 original_script->set_line_ends(Heap::undefined_value()); | 1299 original_script->set_line_ends(HEAP->undefined_value()); |
| 1294 | 1300 |
| 1295 return *old_script_object; | 1301 return *old_script_object; |
| 1296 } | 1302 } |
| 1297 | 1303 |
| 1298 | 1304 |
| 1299 | 1305 |
| 1300 void LiveEdit::ReplaceRefToNestedFunction( | 1306 void LiveEdit::ReplaceRefToNestedFunction( |
| 1301 Handle<JSValue> parent_function_wrapper, | 1307 Handle<JSValue> parent_function_wrapper, |
| 1302 Handle<JSValue> orig_function_wrapper, | 1308 Handle<JSValue> orig_function_wrapper, |
| 1303 Handle<JSValue> subst_function_wrapper) { | 1309 Handle<JSValue> subst_function_wrapper) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 } | 1350 } |
| 1345 return false; | 1351 return false; |
| 1346 } | 1352 } |
| 1347 | 1353 |
| 1348 | 1354 |
| 1349 // Iterates over handler chain and removes all elements that are inside | 1355 // Iterates over handler chain and removes all elements that are inside |
| 1350 // frames being dropped. | 1356 // frames being dropped. |
| 1351 static bool FixTryCatchHandler(StackFrame* top_frame, | 1357 static bool FixTryCatchHandler(StackFrame* top_frame, |
| 1352 StackFrame* bottom_frame) { | 1358 StackFrame* bottom_frame) { |
| 1353 Address* pointer_address = | 1359 Address* pointer_address = |
| 1354 &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address)); | 1360 &Memory::Address_at(Isolate::Current()->get_address_from_id( |
| 1361 Isolate::k_handler_address)); |
| 1355 | 1362 |
| 1356 while (*pointer_address < top_frame->sp()) { | 1363 while (*pointer_address < top_frame->sp()) { |
| 1357 pointer_address = &Memory::Address_at(*pointer_address); | 1364 pointer_address = &Memory::Address_at(*pointer_address); |
| 1358 } | 1365 } |
| 1359 Address* above_frame_address = pointer_address; | 1366 Address* above_frame_address = pointer_address; |
| 1360 while (*pointer_address < bottom_frame->fp()) { | 1367 while (*pointer_address < bottom_frame->fp()) { |
| 1361 pointer_address = &Memory::Address_at(*pointer_address); | 1368 pointer_address = &Memory::Address_at(*pointer_address); |
| 1362 } | 1369 } |
| 1363 bool change = *above_frame_address != *pointer_address; | 1370 bool change = *above_frame_address != *pointer_address; |
| 1364 *above_frame_address = *pointer_address; | 1371 *above_frame_address = *pointer_address; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1379 return "Stack manipulations are not supported in this architecture."; | 1386 return "Stack manipulations are not supported in this architecture."; |
| 1380 } | 1387 } |
| 1381 | 1388 |
| 1382 StackFrame* pre_top_frame = frames[top_frame_index - 1]; | 1389 StackFrame* pre_top_frame = frames[top_frame_index - 1]; |
| 1383 StackFrame* top_frame = frames[top_frame_index]; | 1390 StackFrame* top_frame = frames[top_frame_index]; |
| 1384 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; | 1391 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; |
| 1385 | 1392 |
| 1386 ASSERT(bottom_js_frame->is_java_script()); | 1393 ASSERT(bottom_js_frame->is_java_script()); |
| 1387 | 1394 |
| 1388 // Check the nature of the top frame. | 1395 // Check the nature of the top frame. |
| 1389 if (pre_top_frame->code()->is_inline_cache_stub() && | 1396 Code* pre_top_frame_code = pre_top_frame->LookupCode(Isolate::Current()); |
| 1390 pre_top_frame->code()->ic_state() == DEBUG_BREAK) { | 1397 if (pre_top_frame_code->is_inline_cache_stub() && |
| 1398 pre_top_frame_code->ic_state() == DEBUG_BREAK) { |
| 1391 // OK, we can drop inline cache calls. | 1399 // OK, we can drop inline cache calls. |
| 1392 *mode = Debug::FRAME_DROPPED_IN_IC_CALL; | 1400 *mode = Debug::FRAME_DROPPED_IN_IC_CALL; |
| 1393 } else if (pre_top_frame->code() == Debug::debug_break_slot()) { | 1401 } else if (pre_top_frame_code == |
| 1402 Isolate::Current()->debug()->debug_break_slot()) { |
| 1394 // OK, we can drop debug break slot. | 1403 // OK, we can drop debug break slot. |
| 1395 *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; | 1404 *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; |
| 1396 } else if (pre_top_frame->code() == | 1405 } else if (pre_top_frame_code == |
| 1397 Builtins::builtin(Builtins::FrameDropper_LiveEdit)) { | 1406 Isolate::Current()->builtins()->builtin( |
| 1407 Builtins::FrameDropper_LiveEdit)) { |
| 1398 // OK, we can drop our own code. | 1408 // OK, we can drop our own code. |
| 1399 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; | 1409 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; |
| 1400 } else if (pre_top_frame->code()->kind() == Code::STUB && | 1410 } else if (pre_top_frame_code->kind() == Code::STUB && |
| 1401 pre_top_frame->code()->major_key()) { | 1411 pre_top_frame_code->major_key()) { |
| 1402 // Entry from our unit tests, it's fine, we support this case. | 1412 // Entry from our unit tests, it's fine, we support this case. |
| 1403 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; | 1413 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; |
| 1404 } else { | 1414 } else { |
| 1405 return "Unknown structure of stack above changing function"; | 1415 return "Unknown structure of stack above changing function"; |
| 1406 } | 1416 } |
| 1407 | 1417 |
| 1408 Address unused_stack_top = top_frame->sp(); | 1418 Address unused_stack_top = top_frame->sp(); |
| 1409 Address unused_stack_bottom = bottom_js_frame->fp() | 1419 Address unused_stack_bottom = bottom_js_frame->fp() |
| 1410 - Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame. | 1420 - Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame. |
| 1411 + kPointerSize; // Bigger address end is exclusive. | 1421 + kPointerSize; // Bigger address end is exclusive. |
| 1412 | 1422 |
| 1413 if (unused_stack_top > unused_stack_bottom) { | 1423 if (unused_stack_top > unused_stack_bottom) { |
| 1414 return "Not enough space for frame dropper frame"; | 1424 return "Not enough space for frame dropper frame"; |
| 1415 } | 1425 } |
| 1416 | 1426 |
| 1417 // Committing now. After this point we should return only NULL value. | 1427 // Committing now. After this point we should return only NULL value. |
| 1418 | 1428 |
| 1419 FixTryCatchHandler(pre_top_frame, bottom_js_frame); | 1429 FixTryCatchHandler(pre_top_frame, bottom_js_frame); |
| 1420 // Make sure FixTryCatchHandler is idempotent. | 1430 // Make sure FixTryCatchHandler is idempotent. |
| 1421 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); | 1431 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); |
| 1422 | 1432 |
| 1423 Handle<Code> code(Builtins::builtin(Builtins::FrameDropper_LiveEdit)); | 1433 Handle<Code> code(Isolate::Current()->builtins()->builtin( |
| 1434 Builtins::FrameDropper_LiveEdit)); |
| 1424 top_frame->set_pc(code->entry()); | 1435 top_frame->set_pc(code->entry()); |
| 1425 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); | 1436 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); |
| 1426 | 1437 |
| 1427 *restarter_frame_function_pointer = | 1438 *restarter_frame_function_pointer = |
| 1428 Debug::SetUpFrameDropperFrame(bottom_js_frame, code); | 1439 Debug::SetUpFrameDropperFrame(bottom_js_frame, code); |
| 1429 | 1440 |
| 1430 ASSERT((**restarter_frame_function_pointer)->IsJSFunction()); | 1441 ASSERT((**restarter_frame_function_pointer)->IsJSFunction()); |
| 1431 | 1442 |
| 1432 for (Address a = unused_stack_top; | 1443 for (Address a = unused_stack_top; |
| 1433 a < unused_stack_bottom; | 1444 a < unused_stack_bottom; |
| 1434 a += kPointerSize) { | 1445 a += kPointerSize) { |
| 1435 Memory::Object_at(a) = Smi::FromInt(0); | 1446 Memory::Object_at(a) = Smi::FromInt(0); |
| 1436 } | 1447 } |
| 1437 | 1448 |
| 1438 return NULL; | 1449 return NULL; |
| 1439 } | 1450 } |
| 1440 | 1451 |
| 1441 | 1452 |
| 1442 static bool IsDropableFrame(StackFrame* frame) { | 1453 static bool IsDropableFrame(StackFrame* frame) { |
| 1443 return !frame->is_exit(); | 1454 return !frame->is_exit(); |
| 1444 } | 1455 } |
| 1445 | 1456 |
| 1446 // Fills result array with statuses of functions. Modifies the stack | 1457 // Fills result array with statuses of functions. Modifies the stack |
| 1447 // removing all listed function if possible and if do_drop is true. | 1458 // removing all listed function if possible and if do_drop is true. |
| 1448 static const char* DropActivationsInActiveThread( | 1459 static const char* DropActivationsInActiveThread( |
| 1449 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) { | 1460 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) { |
| 1450 | 1461 Debug* debug = Isolate::Current()->debug(); |
| 1451 ZoneScope scope(DELETE_ON_EXIT); | 1462 ZoneScope scope(DELETE_ON_EXIT); |
| 1452 Vector<StackFrame*> frames = CreateStackMap(); | 1463 Vector<StackFrame*> frames = CreateStackMap(); |
| 1453 | 1464 |
| 1454 int array_len = Smi::cast(shared_info_array->length())->value(); | 1465 int array_len = Smi::cast(shared_info_array->length())->value(); |
| 1455 | 1466 |
| 1456 int top_frame_index = -1; | 1467 int top_frame_index = -1; |
| 1457 int frame_index = 0; | 1468 int frame_index = 0; |
| 1458 for (; frame_index < frames.length(); frame_index++) { | 1469 for (; frame_index < frames.length(); frame_index++) { |
| 1459 StackFrame* frame = frames[frame_index]; | 1470 StackFrame* frame = frames[frame_index]; |
| 1460 if (frame->id() == Debug::break_frame_id()) { | 1471 if (frame->id() == debug->break_frame_id()) { |
| 1461 top_frame_index = frame_index; | 1472 top_frame_index = frame_index; |
| 1462 break; | 1473 break; |
| 1463 } | 1474 } |
| 1464 if (CheckActivation(shared_info_array, result, frame, | 1475 if (CheckActivation(shared_info_array, result, frame, |
| 1465 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { | 1476 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { |
| 1466 // We are still above break_frame. It is not a target frame, | 1477 // We are still above break_frame. It is not a target frame, |
| 1467 // it is a problem. | 1478 // it is a problem. |
| 1468 return "Debugger mark-up on stack is not found"; | 1479 return "Debugger mark-up on stack is not found"; |
| 1469 } | 1480 } |
| 1470 } | 1481 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1527 } | 1538 } |
| 1528 | 1539 |
| 1529 // Adjust break_frame after some frames has been dropped. | 1540 // Adjust break_frame after some frames has been dropped. |
| 1530 StackFrame::Id new_id = StackFrame::NO_ID; | 1541 StackFrame::Id new_id = StackFrame::NO_ID; |
| 1531 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { | 1542 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { |
| 1532 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) { | 1543 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) { |
| 1533 new_id = frames[i]->id(); | 1544 new_id = frames[i]->id(); |
| 1534 break; | 1545 break; |
| 1535 } | 1546 } |
| 1536 } | 1547 } |
| 1537 Debug::FramesHaveBeenDropped(new_id, drop_mode, | 1548 debug->FramesHaveBeenDropped(new_id, drop_mode, |
| 1538 restarter_frame_function_pointer); | 1549 restarter_frame_function_pointer); |
| 1539 | 1550 |
| 1540 // Replace "blocked on active" with "replaced on active" status. | 1551 // Replace "blocked on active" with "replaced on active" status. |
| 1541 for (int i = 0; i < array_len; i++) { | 1552 for (int i = 0; i < array_len; i++) { |
| 1542 if (result->GetElement(i) == | 1553 if (result->GetElement(i) == |
| 1543 Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { | 1554 Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { |
| 1544 Handle<Object> replaced( | 1555 Handle<Object> replaced( |
| 1545 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK)); | 1556 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK)); |
| 1546 SetElementNonStrict(result, i, replaced); | 1557 SetElementNonStrict(result, i, replaced); |
| 1547 } | 1558 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1572 Handle<JSArray> shared_info_array_; | 1583 Handle<JSArray> shared_info_array_; |
| 1573 Handle<JSArray> result_; | 1584 Handle<JSArray> result_; |
| 1574 bool has_blocked_functions_; | 1585 bool has_blocked_functions_; |
| 1575 }; | 1586 }; |
| 1576 | 1587 |
| 1577 | 1588 |
| 1578 Handle<JSArray> LiveEdit::CheckAndDropActivations( | 1589 Handle<JSArray> LiveEdit::CheckAndDropActivations( |
| 1579 Handle<JSArray> shared_info_array, bool do_drop) { | 1590 Handle<JSArray> shared_info_array, bool do_drop) { |
| 1580 int len = Smi::cast(shared_info_array->length())->value(); | 1591 int len = Smi::cast(shared_info_array->length())->value(); |
| 1581 | 1592 |
| 1582 Handle<JSArray> result = Factory::NewJSArray(len); | 1593 Handle<JSArray> result = FACTORY->NewJSArray(len); |
| 1583 | 1594 |
| 1584 // Fill the default values. | 1595 // Fill the default values. |
| 1585 for (int i = 0; i < len; i++) { | 1596 for (int i = 0; i < len; i++) { |
| 1586 SetElementNonStrict( | 1597 SetElementNonStrict( |
| 1587 result, | 1598 result, |
| 1588 i, | 1599 i, |
| 1589 Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH))); | 1600 Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH))); |
| 1590 } | 1601 } |
| 1591 | 1602 |
| 1592 | 1603 |
| 1593 // First check inactive threads. Fail if some functions are blocked there. | 1604 // First check inactive threads. Fail if some functions are blocked there. |
| 1594 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, | 1605 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, |
| 1595 result); | 1606 result); |
| 1596 ThreadManager::IterateArchivedThreads(&inactive_threads_checker); | 1607 Isolate::Current()->thread_manager()->IterateArchivedThreads( |
| 1608 &inactive_threads_checker); |
| 1597 if (inactive_threads_checker.HasBlockedFunctions()) { | 1609 if (inactive_threads_checker.HasBlockedFunctions()) { |
| 1598 return result; | 1610 return result; |
| 1599 } | 1611 } |
| 1600 | 1612 |
| 1601 // Try to drop activations from the current stack. | 1613 // Try to drop activations from the current stack. |
| 1602 const char* error_message = | 1614 const char* error_message = |
| 1603 DropActivationsInActiveThread(shared_info_array, result, do_drop); | 1615 DropActivationsInActiveThread(shared_info_array, result, do_drop); |
| 1604 if (error_message != NULL) { | 1616 if (error_message != NULL) { |
| 1605 // Add error message as an array extra element. | 1617 // Add error message as an array extra element. |
| 1606 Vector<const char> vector_message(error_message, StrLength(error_message)); | 1618 Vector<const char> vector_message(error_message, StrLength(error_message)); |
| 1607 Handle<String> str = Factory::NewStringFromAscii(vector_message); | 1619 Handle<String> str = FACTORY->NewStringFromAscii(vector_message); |
| 1608 SetElementNonStrict(result, len, str); | 1620 SetElementNonStrict(result, len, str); |
| 1609 } | 1621 } |
| 1610 return result; | 1622 return result; |
| 1611 } | 1623 } |
| 1612 | 1624 |
| 1613 | 1625 |
| 1614 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { | 1626 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, |
| 1615 if (active_function_info_listener != NULL) { | 1627 FunctionLiteral* fun) |
| 1616 active_function_info_listener->FunctionStarted(fun); | 1628 : isolate_(isolate) { |
| 1629 if (isolate_->active_function_info_listener() != NULL) { |
| 1630 isolate_->active_function_info_listener()->FunctionStarted(fun); |
| 1617 } | 1631 } |
| 1618 } | 1632 } |
| 1619 | 1633 |
| 1620 | 1634 |
| 1621 LiveEditFunctionTracker::~LiveEditFunctionTracker() { | 1635 LiveEditFunctionTracker::~LiveEditFunctionTracker() { |
| 1622 if (active_function_info_listener != NULL) { | 1636 if (isolate_->active_function_info_listener() != NULL) { |
| 1623 active_function_info_listener->FunctionDone(); | 1637 isolate_->active_function_info_listener()->FunctionDone(); |
| 1624 } | 1638 } |
| 1625 } | 1639 } |
| 1626 | 1640 |
| 1627 | 1641 |
| 1628 void LiveEditFunctionTracker::RecordFunctionInfo( | 1642 void LiveEditFunctionTracker::RecordFunctionInfo( |
| 1629 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { | 1643 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { |
| 1630 if (active_function_info_listener != NULL) { | 1644 if (isolate_->active_function_info_listener() != NULL) { |
| 1631 active_function_info_listener->FunctionInfo(info, lit->scope()); | 1645 isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope()); |
| 1632 } | 1646 } |
| 1633 } | 1647 } |
| 1634 | 1648 |
| 1635 | 1649 |
| 1636 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { | 1650 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { |
| 1637 active_function_info_listener->FunctionCode(code); | 1651 isolate_->active_function_info_listener()->FunctionCode(code); |
| 1638 } | 1652 } |
| 1639 | 1653 |
| 1640 | 1654 |
| 1641 bool LiveEditFunctionTracker::IsActive() { | 1655 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { |
| 1642 return active_function_info_listener != NULL; | 1656 return isolate->active_function_info_listener() != NULL; |
| 1643 } | 1657 } |
| 1644 | 1658 |
| 1645 | 1659 |
| 1646 #else // ENABLE_DEBUGGER_SUPPORT | 1660 #else // ENABLE_DEBUGGER_SUPPORT |
| 1647 | 1661 |
| 1648 // This ifdef-else-endif section provides working or stub implementation of | 1662 // This ifdef-else-endif section provides working or stub implementation of |
| 1649 // LiveEditFunctionTracker. | 1663 // LiveEditFunctionTracker. |
| 1650 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { | 1664 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate, |
| 1665 FunctionLiteral* fun) { |
| 1651 } | 1666 } |
| 1652 | 1667 |
| 1653 | 1668 |
| 1654 LiveEditFunctionTracker::~LiveEditFunctionTracker() { | 1669 LiveEditFunctionTracker::~LiveEditFunctionTracker() { |
| 1655 } | 1670 } |
| 1656 | 1671 |
| 1657 | 1672 |
| 1658 void LiveEditFunctionTracker::RecordFunctionInfo( | 1673 void LiveEditFunctionTracker::RecordFunctionInfo( |
| 1659 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { | 1674 Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { |
| 1660 } | 1675 } |
| 1661 | 1676 |
| 1662 | 1677 |
| 1663 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { | 1678 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { |
| 1664 } | 1679 } |
| 1665 | 1680 |
| 1666 | 1681 |
| 1667 bool LiveEditFunctionTracker::IsActive() { | 1682 bool LiveEditFunctionTracker::IsActive() { |
| 1668 return false; | 1683 return false; |
| 1669 } | 1684 } |
| 1670 | 1685 |
| 1671 #endif // ENABLE_DEBUGGER_SUPPORT | 1686 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1672 | 1687 |
| 1673 | 1688 |
| 1674 | 1689 |
| 1675 } } // namespace v8::internal | 1690 } } // namespace v8::internal |
| OLD | NEW |