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

Side by Side Diff: src/liveedit.cc

Issue 2943002: Reimplement stack manipulations for LiveEdit (Closed)
Patch Set: follow codereview Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 private: 573 private:
574 static const int kFunctionNameOffset_ = 0; 574 static const int kFunctionNameOffset_ = 0;
575 static const int kStartPositionOffset_ = 1; 575 static const int kStartPositionOffset_ = 1;
576 static const int kEndPositionOffset_ = 2; 576 static const int kEndPositionOffset_ = 2;
577 static const int kSharedInfoOffset_ = 3; 577 static const int kSharedInfoOffset_ = 3;
578 static const int kSize_ = 4; 578 static const int kSize_ = 4;
579 579
580 friend class JSArrayBasedStruct<SharedInfoWrapper>; 580 friend class JSArrayBasedStruct<SharedInfoWrapper>;
581 }; 581 };
582 582
583 // Data describing possible stack manipulations or a failure descriptions.
584 // The function index is used both in success/failure cases.
585 class StackManipulationInfo : public JSArrayBasedStruct<StackManipulationInfo> {
586 public:
587 static Handle<JSArray> CreateError(const char* error_message,
588 int function_index) {
589 StackManipulationInfo info = StackManipulationInfo::Create();
590 info.SetProperties(error_message, function_index,
591 Handle<Object>(Heap::undefined_value()));
592 return info.GetJSArray();
593 }
594
595 static Handle<JSArray> CreateSuccess(int bottom_function_index,
596 Handle<Object> drop_data) {
597 StackManipulationInfo info = StackManipulationInfo::Create();
598 info.SetProperties(NULL, bottom_function_index, drop_data);
599 return info.GetJSArray();
600 }
601
602 static Handle<JSArray> CreateEmpty() {
603 StackManipulationInfo info = StackManipulationInfo::Create();
604 return info.GetJSArray();
605 }
606
607 explicit StackManipulationInfo(Handle<JSArray> array)
608 : JSArrayBasedStruct<StackManipulationInfo>(array) {
609 }
610
611 private:
612 void SetProperties(const char* error_message, int function_index,
613 Handle<Object> drop_data) {
614 HandleScope scope;
615 if (error_message == NULL) {
616 this->SetField(kErrorMessageOffset_,
617 Handle<Object>(Heap::undefined_value()));
618 } else {
619 Handle<String> message_string =
620 Factory::NewStringFromAscii(CStrVector(error_message));
621 this->SetField(kErrorMessageOffset_, message_string);
622 }
623 this->SetField(kBottomFunctionIndexOffset_,
624 Handle<Object>(Smi::FromInt(function_index)));
625 Handle<JSValue> drop_data_wrapper = WrapInJSValue(*drop_data);
626 this->SetField(kDropDataOffset_, drop_data_wrapper);
627 }
628
629 static const int kErrorMessageOffset_ = 0;
630 static const int kBottomFunctionIndexOffset_ = 1;
631 static const int kDropDataOffset_ = 2;
632 static const int kSize_ = 3;
633
634 friend class JSArrayBasedStruct<StackManipulationInfo>;
635 };
636
583 class FunctionInfoListener { 637 class FunctionInfoListener {
584 public: 638 public:
585 FunctionInfoListener() { 639 FunctionInfoListener() {
586 current_parent_index_ = -1; 640 current_parent_index_ = -1;
587 len_ = 0; 641 len_ = 0;
588 result_ = Factory::NewJSArray(10); 642 result_ = Factory::NewJSArray(10);
589 } 643 }
590 644
591 void FunctionStarted(FunctionLiteral* fun) { 645 void FunctionStarted(FunctionLiteral* fun) {
592 HandleScope scope; 646 HandleScope scope;
593 FunctionInfoWrapper info = FunctionInfoWrapper::Create(); 647 FunctionInfoWrapper info = FunctionInfoWrapper::Create();
594 info.SetInitialProperties(fun->name(), fun->start_position(), 648 info.SetInitialProperties(fun->name(), fun->start_position(),
595 fun->end_position(), fun->num_parameters(), 649 fun->end_position(), fun->num_parameters(),
596 current_parent_index_); 650 current_parent_index_);
597 current_parent_index_ = len_; 651 current_parent_index_ = len_;
598 SetElement(result_, len_, info.GetJSArray()); 652 SetElement(result_, len_, info.GetJSArray());
599 len_++; 653 len_++;
600 } 654 }
601 655
602 void FunctionDone() { 656 void FunctionDone() {
603 HandleScope scope; 657 HandleScope scope;
604 FunctionInfoWrapper info = 658 FunctionInfoWrapper info =
605 FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_)); 659 FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_));
606 current_parent_index_ = info.GetParentIndex(); 660 current_parent_index_ = info.GetParentIndex();
607 } 661 }
608 662
609 // TODO(LiveEdit): Move private method below. 663 // TODO(LiveEdit): Move private method below.
610 // This private section was created here to avoid moving the function 664 // This private section was created here to avoid moving the function
611 // to keep already complex diff simpler. 665 // to keep already complex diff simpler.
612 private: 666 private:
613 Object* SerializeFunctionScope(Scope* scope) { 667 Object* SerializeFunctionScope(Scope* scope) {
614 HandleScope handle_scope; 668 HandleScope handle_scope;
615 669
616 Handle<JSArray> scope_info_list = Factory::NewJSArray(10); 670 Handle<JSArray> scope_info_list = Factory::NewJSArray(10);
617 int scope_info_length = 0; 671 int scope_info_length = 0;
618 672
619 // Saves some description of scope. It stores name and indexes of 673 // Saves some description of scope. It stores name and indexes of
620 // variables in the whole scope chain. Null-named slots delimit 674 // variables in the whole scope chain. Null-named slots delimit
621 // scopes of this chain. 675 // scopes of this chain.
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 void VisitThread(ThreadLocalTop* top) { 844 void VisitThread(ThreadLocalTop* top) {
791 StackFrame::UncookFramesForThread(top); 845 StackFrame::UncookFramesForThread(top);
792 } 846 }
793 }; 847 };
794 848
795 static void IterateAllThreads(ThreadVisitor* visitor) { 849 static void IterateAllThreads(ThreadVisitor* visitor) {
796 Top::IterateThread(visitor); 850 Top::IterateThread(visitor);
797 ThreadManager::IterateArchivedThreads(visitor); 851 ThreadManager::IterateArchivedThreads(visitor);
798 } 852 }
799 853
854 // Forward declarations. Introduced to keep functions in the same order
855 // to simplify diff during a complex source modification.
856 // TODO(LiveEdit): reorder functions and get rid of forward declarations
857 static void PerformActiveStackModification(
858 ByteArray* stack_manipulation_data,
859 SharedFunctionInfo* expected_function);
860 static void AddRestarterRInfo(Handle<Code> code, int patch_pc,
861 int source_position);
862
863 static Handle<Code> PatchCodeWithRestarter(Handle<Code> code,
864 int function_source_pos);
865
866
867
800 // Finds all references to original and replaces them with substitution. 868 // Finds all references to original and replaces them with substitution.
801 static void ReplaceCodeObject(Code* original, Code* substitution) { 869 // Performs stack manipulation (if data is provided) in the same transaction.
870 static void ReplaceCodeObject(Code* original, Code* substitution,
871 ByteArray* stack_manipulation_data,
872 SharedFunctionInfo* function) {
802 ASSERT(!Heap::InNewSpace(substitution)); 873 ASSERT(!Heap::InNewSpace(substitution));
803 874
804 AssertNoAllocation no_allocations_please; 875 AssertNoAllocation no_allocations_please;
805 876
806 // A zone scope for ReferenceCollectorVisitor. 877 // A zone scope for ReferenceCollectorVisitor.
807 ZoneScope scope(DELETE_ON_EXIT); 878 ZoneScope scope(DELETE_ON_EXIT);
808 879
809 ReferenceCollectorVisitor visitor(original); 880 ReferenceCollectorVisitor visitor(original);
810 881
811 // Iterate over all roots. Stack frames may have pointer into original code, 882 // Iterate over all roots. Stack frames may have pointer into original code,
(...skipping 10 matching lines...) Expand all
822 } 893 }
823 894
824 // Now iterate over all pointers of all objects, including code_target 895 // Now iterate over all pointers of all objects, including code_target
825 // implicit pointers. 896 // implicit pointers.
826 HeapIterator iterator; 897 HeapIterator iterator;
827 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { 898 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
828 obj->Iterate(&visitor); 899 obj->Iterate(&visitor);
829 } 900 }
830 901
831 visitor.Replace(substitution); 902 visitor.Replace(substitution);
903
904 if (stack_manipulation_data != NULL) {
905 // Performs stack manipulations for the cases when the actually function was
906 // on stack. The manipulations are expected to restart this function.
907 PerformActiveStackModification(stack_manipulation_data, function);
908 }
832 } 909 }
833 910
834 911
835 // Check whether the code is natural function code (not a lazy-compile stub 912 // Check whether the code is natural function code (not a lazy-compile stub
836 // code). 913 // code).
837 static bool IsJSFunctionCode(Code* code) { 914 static bool IsJSFunctionCode(Code* code) {
838 return code->kind() == Code::FUNCTION; 915 return code->kind() == Code::FUNCTION;
839 } 916 }
840 917
841 918
842 Object* LiveEdit::ReplaceFunctionCode(Handle<JSArray> new_compile_info_array, 919 Object* LiveEdit::ReplaceFunctionCode(
843 Handle<JSArray> shared_info_array) { 920 Handle<JSArray> new_compile_info_array,
921 Handle<JSArray> shared_info_array,
922 Handle<ByteArray> stack_manipulation_data) {
923
844 HandleScope scope; 924 HandleScope scope;
845
846 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { 925 if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
847 return Top::ThrowIllegalOperation(); 926 return Top::ThrowIllegalOperation();
848 } 927 }
849 928
850 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); 929 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
851 SharedInfoWrapper shared_info_wrapper(shared_info_array); 930 SharedInfoWrapper shared_info_wrapper(shared_info_array);
852 931
853 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); 932 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
854 933
934 Handle<Code> new_code = compile_info_wrapper.GetFunctionCode();
935
936 shared_info->set_start_position(compile_info_wrapper.GetStartPosition());
937 shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
938
855 if (IsJSFunctionCode(shared_info->code())) { 939 if (IsJSFunctionCode(shared_info->code())) {
856 ReplaceCodeObject(shared_info->code(), 940 if (stack_manipulation_data.is_null()) {
857 *(compile_info_wrapper.GetFunctionCode())); 941 ReplaceCodeObject(shared_info->code(), *new_code, NULL, NULL);
942 } else {
943 new_code = PatchCodeWithRestarter(new_code,
944 shared_info->start_position());
945 ReplaceCodeObject(shared_info->code(), *new_code,
946 *stack_manipulation_data, *shared_info);
947 }
858 } 948 }
859 949
860 if (shared_info->debug_info()->IsDebugInfo()) { 950 if (shared_info->debug_info()->IsDebugInfo()) {
861 Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info())); 951 Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
862 Handle<Code> new_original_code = 952 Handle<Code> new_original_code = Factory::CopyCode(new_code);
863 Factory::CopyCode(compile_info_wrapper.GetFunctionCode());
864 debug_info->set_original_code(*new_original_code); 953 debug_info->set_original_code(*new_original_code);
865 } 954 }
866 955
867 shared_info->set_start_position(compile_info_wrapper.GetStartPosition());
868 shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
869
870 shared_info->set_construct_stub( 956 shared_info->set_construct_stub(
871 Builtins::builtin(Builtins::JSConstructStubGeneric)); 957 Builtins::builtin(Builtins::JSConstructStubGeneric));
872 958
873 return Heap::undefined_value(); 959 return Heap::undefined_value();
874 } 960 }
875 961
876 962
963 // Returns the offset of restarted patch within the code or -1. Technically
964 // patch offset is not its starting point.
965 static int GetRestarterPatchOffset(Code* code) {
966 Handle<Code> restarter_patch(
967 Builtins::builtin(Builtins::RestarterPatch_LiveEdit));
968 int patch_len = restarter_patch->instruction_size();
969 if (code->instruction_size() < patch_len) {
970 return -1;
971 }
972 Address pos1 = code->instruction_start() + code->instruction_size();
973 Address pos2 = restarter_patch->instruction_start() + patch_len;
974
975 for (int i = 0; i < patch_len; i++) {
976 pos1--;
977 pos2--;
978 if (*pos1 != *pos2) {
979 return -1;
980 }
981 }
982 return code->instruction_size() - patch_len;
983 }
984
985
986 bool LiveEdit::IsAtFrameResetPatch(const JavaScriptFrame* frame) {
987 return frame->fp() == Debug::GetRestartedFrameFp();
988 }
989
990
991 Address LiveEdit::GetRestarterPatchEntryPoint(Code* code) {
992 int entry_offset = GetRestarterPatchOffset(code);
993 ASSERT(entry_offset != -1);
994 return code->instruction_start() + entry_offset +
995 Debug::kFrameRestarterEntryOffset;
996 }
997
998
999 // Returns patched code instruction offset from entry point.
1000 static Handle<Code> PatchCodeWithRestarter(Handle<Code> code,
1001 int function_source_pos) {
1002 if (GetRestarterPatchOffset(*code) == -1) {
1003 Handle<Code> restarter_patch(
1004 Builtins::builtin(Builtins::RestarterPatch_LiveEdit));
1005 Handle<Code> patched_code = Factory::AddPatchToCode(code, restarter_patch);
1006 AddRestarterRInfo(patched_code, code->instruction_size(),
1007 function_source_pos);
1008 code = patched_code;
1009 }
1010 return code;
1011 }
1012
1013
877 // TODO(635): Eval caches its scripts (same text -- same compiled info). 1014 // TODO(635): Eval caches its scripts (same text -- same compiled info).
878 // Make sure we clear such caches. 1015 // Make sure we clear such caches.
879 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, 1016 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
880 Handle<Object> script_handle) { 1017 Handle<Object> script_handle) {
881 Handle<SharedFunctionInfo> shared_info = 1018 Handle<SharedFunctionInfo> shared_info =
882 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); 1019 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
883 shared_info->set_script(*script_handle); 1020 shared_info->set_script(*script_handle);
884 } 1021 }
885 1022
886 1023
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 } 1122 }
986 1123
987 RelocInfoWriter reloc_info_writer_; 1124 RelocInfoWriter reloc_info_writer_;
988 byte* buffer_; 1125 byte* buffer_;
989 int buffer_size_; 1126 int buffer_size_;
990 1127
991 static const int kBufferGap = RelocInfoWriter::kMaxSize; 1128 static const int kBufferGap = RelocInfoWriter::kMaxSize;
992 static const int kMaximalBufferSize = 512*MB; 1129 static const int kMaximalBufferSize = 512*MB;
993 }; 1130 };
994 1131
995 // Patch positions in code (changes relocation info section) and possibly 1132
996 // returns new instance of code. 1133 static void AddRestarterRInfo(Handle<Code> code, int patch_pc,
997 static Handle<Code> PatchPositionsInCode(Handle<Code> code, 1134 int source_position) {
1135 RelocInfoBuffer buffer_writer(code->relocation_size(),
1136 code->instruction_start());
1137
1138 {
1139 AssertNoAllocation no_allocations_please;
1140 for (RelocIterator it(*code); !it.done(); it.next()) {
1141 buffer_writer.Write(it.rinfo());
1142 }
1143 byte* pc = code->instruction_start() + patch_pc;
1144 intptr_t position_value = source_position;
1145 RelocInfo additional_info(pc, RelocInfo::POSITION, position_value);
1146 buffer_writer.Write(&additional_info);
1147 }
1148
1149 Vector<byte> buffer = buffer_writer.GetResult();
1150 Handle<ByteArray> array = Factory::NewByteArray(buffer.length(), TENURED);
1151 code->set_relocation_info(*array);
1152
1153 memcpy(code->relocation_start(), buffer.start(), buffer.length());
1154 }
1155
1156
1157
1158 // Patch positions in code (changes relocation info section).
1159 static void PatchPositionsInCode(Handle<Code> code,
998 Handle<JSArray> position_change_array) { 1160 Handle<JSArray> position_change_array) {
999 1161
1000 RelocInfoBuffer buffer_writer(code->relocation_size(), 1162 RelocInfoBuffer buffer_writer(code->relocation_size(),
1001 code->instruction_start()); 1163 code->instruction_start());
1002 1164
1003 { 1165 {
1004 AssertNoAllocation no_allocations_please; 1166 AssertNoAllocation no_allocations_please;
1005 for (RelocIterator it(*code); !it.done(); it.next()) { 1167 for (RelocIterator it(*code); !it.done(); it.next()) {
1006 RelocInfo* rinfo = it.rinfo(); 1168 RelocInfo* rinfo = it.rinfo();
1007 if (RelocInfo::IsPosition(rinfo->rmode())) { 1169 if (RelocInfo::IsPosition(rinfo->rmode())) {
1008 int position = static_cast<int>(rinfo->data()); 1170 int position = static_cast<int>(rinfo->data());
1009 int new_position = TranslatePosition(position, 1171 int new_position = TranslatePosition(position,
1010 position_change_array); 1172 position_change_array);
1011 if (position != new_position) { 1173 if (position != new_position) {
1012 RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position); 1174 RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position);
1013 buffer_writer.Write(&info_copy); 1175 buffer_writer.Write(&info_copy);
1014 continue; 1176 continue;
1015 } 1177 }
1016 } 1178 }
1017 buffer_writer.Write(it.rinfo()); 1179 buffer_writer.Write(it.rinfo());
1018 } 1180 }
1019 } 1181 }
1020 1182
1021 Vector<byte> buffer = buffer_writer.GetResult(); 1183 Vector<byte> buffer = buffer_writer.GetResult();
1022 1184
1023 if (buffer.length() == code->relocation_size()) { 1185 if (buffer.length() != code->relocation_size()) {
1024 // Simply patch relocation area of code. 1186 // Relocation info section now has different size.
1025 memcpy(code->relocation_start(), buffer.start(), buffer.length()); 1187 Handle<ByteArray> array = Factory::NewByteArray(buffer.length(), TENURED);
1026 return code; 1188 code->set_relocation_info(*array);
1027 } else {
1028 // Relocation info section now has different size. We cannot simply
1029 // rewrite it inside code object. Instead we have to create a new
1030 // code object.
1031 Handle<Code> result(Factory::CopyCode(code, buffer));
1032 return result;
1033 } 1189 }
1190 memcpy(code->relocation_start(), buffer.start(), buffer.length());
1034 } 1191 }
1035 1192
1036 1193
1037 Object* LiveEdit::PatchFunctionPositions( 1194 Object* LiveEdit::PatchFunctionPositions(
1038 Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) { 1195 Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
1039 1196
1040 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { 1197 if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
1041 return Top::ThrowIllegalOperation(); 1198 return Top::ThrowIllegalOperation();
1042 } 1199 }
1043 1200
1044 SharedInfoWrapper shared_info_wrapper(shared_info_array); 1201 SharedInfoWrapper shared_info_wrapper(shared_info_array);
1045 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo(); 1202 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
1046 1203
1047 int old_function_start = info->start_position(); 1204 int old_function_start = info->start_position();
1048 int new_function_start = TranslatePosition(old_function_start, 1205 int new_function_start = TranslatePosition(old_function_start,
1049 position_change_array); 1206 position_change_array);
1050 info->set_start_position(new_function_start); 1207 info->set_start_position(new_function_start);
1051 info->set_end_position(TranslatePosition(info->end_position(), 1208 info->set_end_position(TranslatePosition(info->end_position(),
1052 position_change_array)); 1209 position_change_array));
1053 1210
1054 info->set_function_token_position( 1211 info->set_function_token_position(
1055 TranslatePosition(info->function_token_position(), 1212 TranslatePosition(info->function_token_position(),
1056 position_change_array)); 1213 position_change_array));
1057 1214
1058 if (IsJSFunctionCode(info->code())) { 1215 if (IsJSFunctionCode(info->code())) {
1059 // Patch relocation info section of the code. 1216 // Patch relocation info section of the code.
1060 Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()), 1217 PatchPositionsInCode(Handle<Code>(info->code()), position_change_array);
1061 position_change_array);
1062 if (*patched_code != info->code()) {
1063 // Replace all references to the code across the heap. In particular,
1064 // some stubs may refer to this code and this code may be being executed
1065 // on stack (it is safe to substitute the code object on stack, because
1066 // we only change the structure of rinfo and leave instructions
1067 // untouched).
1068 ReplaceCodeObject(info->code(), *patched_code);
1069 }
1070 } 1218 }
1071 1219
1072 return Heap::undefined_value(); 1220 return Heap::undefined_value();
1073 } 1221 }
1074 1222
1075 1223
1076 static Handle<Script> CreateScriptCopy(Handle<Script> original) { 1224 static Handle<Script> CreateScriptCopy(Handle<Script> original) {
1077 Handle<String> original_source(String::cast(original->source())); 1225 Handle<String> original_source(String::cast(original->source()));
1078 1226
1079 Handle<Script> copy = Factory::NewScript(original_source); 1227 Handle<Script> copy = Factory::NewScript(original_source);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) { 1279 for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
1132 if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) { 1280 if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
1133 if (it.rinfo()->target_object() == *orig_shared) { 1281 if (it.rinfo()->target_object() == *orig_shared) {
1134 it.rinfo()->set_target_object(*subst_shared); 1282 it.rinfo()->set_target_object(*subst_shared);
1135 } 1283 }
1136 } 1284 }
1137 } 1285 }
1138 } 1286 }
1139 1287
1140 1288
1141 // Check an activation against list of functions. If there is a function 1289 // Check an activation against the list of functions. If there is a function
1142 // that matches, its status in result array is changed to status argument value. 1290 // that matches its index is returned. Otherwise returns -1.
1143 static bool CheckActivation(Handle<JSArray> shared_info_array, 1291 static int CheckActivation(Handle<JSArray> shared_info_array,
1144 Handle<JSArray> result, StackFrame* frame, 1292 StackFrame* frame) {
1145 LiveEdit::FunctionPatchabilityStatus status) {
1146 if (!frame->is_java_script()) { 1293 if (!frame->is_java_script()) {
1147 return false; 1294 return -1;
1148 } 1295 }
1149 int len = Smi::cast(shared_info_array->length())->value(); 1296 int len = Smi::cast(shared_info_array->length())->value();
1150 for (int i = 0; i < len; i++) { 1297 for (int i = 0; i < len; i++) {
1151 JSValue* wrapper = JSValue::cast(shared_info_array->GetElement(i)); 1298 JSValue* wrapper = JSValue::cast(shared_info_array->GetElement(i));
1299 if (!wrapper->value()->IsSharedFunctionInfo()) {
1300 continue;
1301 }
1152 Handle<SharedFunctionInfo> shared( 1302 Handle<SharedFunctionInfo> shared(
1153 SharedFunctionInfo::cast(wrapper->value())); 1303 SharedFunctionInfo::cast(wrapper->value()));
1154 1304
1155 if (frame->code() == shared->code()) { 1305 if (frame->code() == shared->code()) {
1156 SetElement(result, i, Handle<Smi>(Smi::FromInt(status))); 1306 return i;
1157 return true;
1158 } 1307 }
1159 } 1308 }
1160 return false; 1309 return -1;
1161 } 1310 }
1162 1311
1163 1312
1164 // Iterates over handler chain and removes all elements that are inside 1313 // Iterates over handler chain and removes all elements that are inside
1165 // frames being dropped. 1314 // frames being dropped.
1166 static bool FixTryCatchHandler(StackFrame* top_frame, 1315 static bool FixTryCatchHandler(StackFrame* top_frame,
1167 StackFrame* bottom_frame) { 1316 StackFrame* bottom_frame) {
1168 Address* pointer_address = 1317 Address* pointer_address =
1169 &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address)); 1318 &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address));
1170 1319
1171 while (*pointer_address < top_frame->sp()) { 1320 while (*pointer_address < top_frame->sp()) {
1172 pointer_address = &Memory::Address_at(*pointer_address); 1321 pointer_address = &Memory::Address_at(*pointer_address);
1173 } 1322 }
1174 Address* above_frame_address = pointer_address; 1323 Address* above_frame_address = pointer_address;
1175 while (*pointer_address < bottom_frame->fp()) { 1324 while (*pointer_address < bottom_frame->fp()) {
1176 pointer_address = &Memory::Address_at(*pointer_address); 1325 pointer_address = &Memory::Address_at(*pointer_address);
1177 } 1326 }
1178 bool change = *above_frame_address != *pointer_address; 1327 bool change = *above_frame_address != *pointer_address;
1179 *above_frame_address = *pointer_address; 1328 *above_frame_address = *pointer_address;
1180 return change; 1329 return change;
1181 } 1330 }
1182 1331
1183 1332
1184 // Removes specified range of frames from stack. There may be 1 or more 1333 // If function was in some nested scope (e.g. 'with'), reset it back to
1185 // frames in range. Anyway the bottom frame is restarted rather than dropped, 1334 // function scope.
1186 // and therefore has to be a JavaScript frame. 1335 static void ResetFrameScope(JavaScriptFrame* js_frame) {
1187 // Returns error message or NULL. 1336 Context* original_context = Context::cast(js_frame->context());
1188 static const char* DropFrames(Vector<StackFrame*> frames, 1337 Context* context = original_context;
1189 int top_frame_index, 1338 while (!context->is_function_context()) {
1190 int bottom_js_frame_index, 1339 context = context->previous();
1191 Debug::FrameDropMode* mode) { 1340 ASSERT(context->IsContext());
1192 if (Debug::kFrameDropperFrameSize < 0) {
1193 return "Stack manipulations are not supported in this architecture.";
1194 } 1341 }
1342 if (original_context != context) {
1343 js_frame->SetContext(context);
1344 }
1345 }
1346
1347
1348 // The header of stack modification data that is stored in byte array.
1349 // This header is followed by 3 StackFrame objects.
1350 struct StackModificationPlanHeader {
1351 Address unused_stack_top;
1352 Address unused_stack_bottom;
1353 Debug::FrameDropMode frame_drop_mode;
1354 };
1355
1356
1357 // Plans the stack manipulations. The input defines a range of frames
1358 // with the bottom frames being a JavaScriptFrame. Returns a successfully
1359 // created plan or an error description.
1360 static Handle<JSArray> PrepareDropFrames(Vector<StackFrame*> frames,
1361 int top_frame_index,
1362 int bottom_js_frame_index,
1363 int target_function_index) {
1364 if (Debug::kRestartedFrameHeight < 0) {
1365 return StackManipulationInfo::CreateError(
1366 "Stack manipulations are not supported in this architecture",
1367 target_function_index);
1368 }
1369
1370 Debug::FrameDropMode mode;
1195 1371
1196 StackFrame* pre_top_frame = frames[top_frame_index - 1]; 1372 StackFrame* pre_top_frame = frames[top_frame_index - 1];
1197 StackFrame* top_frame = frames[top_frame_index]; 1373 StackFrame* top_frame = frames[top_frame_index];
1198 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; 1374 StackFrame* bottom_js_frame = frames[bottom_js_frame_index];
1199 1375
1200 ASSERT(bottom_js_frame->is_java_script()); 1376 ASSERT(bottom_js_frame->is_java_script());
1201 1377
1202 // Check the nature of the top frame. 1378 // Check the nature of the top frame.
1203 if (pre_top_frame->code()->is_inline_cache_stub() && 1379 if (pre_top_frame->code()->is_inline_cache_stub() &&
1204 pre_top_frame->code()->ic_state() == DEBUG_BREAK) { 1380 pre_top_frame->code()->ic_state() == DEBUG_BREAK) {
1205 // OK, we can drop inline cache calls. 1381 // OK, we can drop inline cache calls.
1206 *mode = Debug::FRAME_DROPPED_IN_IC_CALL; 1382 mode = Debug::FRAME_DROPPED_IN_IC_CALL;
1207 } else if (pre_top_frame->code() == Debug::debug_break_slot()) { 1383 } else if (pre_top_frame->code() == Debug::debug_break_slot()) {
1208 // OK, we can drop debug break slot. 1384 // OK, we can drop debug break slot.
1209 *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; 1385 mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
1210 } else if (pre_top_frame->code() == 1386 } else if (Debug::GetRestartedFrameFp() != 0) {
1211 Builtins::builtin(Builtins::FrameDropper_LiveEdit)) { 1387 // The top frame must be restarted.
1212 // OK, we can drop our own code. 1388 // OK, we can drop our own code.
1213 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; 1389 mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
1214 } else if (pre_top_frame->code()->kind() == Code::STUB && 1390 } else if (pre_top_frame->code()->kind() == Code::STUB &&
1215 pre_top_frame->code()->major_key()) { 1391 pre_top_frame->code()->major_key()) {
1216 // Entry from our unit tests, it's fine, we support this case. 1392 // Entry from our unit tests, it's fine, we support this case.
1217 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; 1393 mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
1218 } else { 1394 } else {
1219 return "Unknown structure of stack above changing function"; 1395 return StackManipulationInfo::CreateError(
1396 "Unknown structure of stack above JavaScript frames",
1397 target_function_index);
1220 } 1398 }
1221 1399
1222 Address unused_stack_top = top_frame->sp(); 1400 Address unused_stack_top = top_frame->sp();
1223 Address unused_stack_bottom = bottom_js_frame->fp() 1401 Address unused_stack_bottom = bottom_js_frame->fp()
1224 - Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame. 1402 - Debug::kRestartedFrameHeight * kPointerSize // Size of the new frame.
1225 + kPointerSize; // Bigger address end is exclusive. 1403 + kPointerSize; // Bigger address end is exclusive.
1226 1404
1227 if (unused_stack_top > unused_stack_bottom) { 1405 if (unused_stack_top > unused_stack_bottom) {
1228 return "Not enough space for frame dropper frame"; 1406 return StackManipulationInfo::CreateError(
1407 "Not enough space in stack to do stack manipulations",
1408 target_function_index);
1409 }
1410 StackModificationPlanHeader plan;
1411 plan.unused_stack_top = unused_stack_top;
1412 plan.unused_stack_bottom = unused_stack_bottom;
1413 plan.frame_drop_mode = mode;
1414
1415 StackFrame* three_frames[] = { pre_top_frame, top_frame, bottom_js_frame };
1416
1417 int data_size = sizeof(plan);
1418 for (int i = 0; i < 3; i++) {
1419 data_size += GetStackFrameObjectSize(three_frames[i]);
1229 } 1420 }
1230 1421
1231 // Committing now. After this point we should return only NULL value. 1422 Handle<ByteArray> array = Factory::NewByteArray(data_size);
1423 {
1424 AssertNoAllocation no_allocations_please;
1425 byte* dst = array->GetDataStartAddress();
1426 memcpy(dst, &plan, sizeof(plan));
1427 dst += sizeof(plan);
1428 for (int i = 0; i < 3; i++) {
1429 int size = GetStackFrameObjectSize(three_frames[i]);
1430 memcpy(dst, three_frames[i], size);
1431 dst += size;
1432 }
1433 }
1434 return StackManipulationInfo::CreateSuccess(target_function_index, array);
1435 }
1232 1436
1437 // Actually modifies the active stack. Within the range of frames,
1438 // restarts the function in a bottom one and zeroes out all other.
1439 static void DoDropFrames(StackFrame* pre_top_frame, StackFrame* top_frame,
1440 JavaScriptFrame* bottom_js_frame,
1441 Address unused_stack_top, Address unused_stack_bottom,
1442 SharedFunctionInfo* expected_function) {
1233 FixTryCatchHandler(pre_top_frame, bottom_js_frame); 1443 FixTryCatchHandler(pre_top_frame, bottom_js_frame);
1234 // Make sure FixTryCatchHandler is idempotent. 1444 // Make sure FixTryCatchHandler is idempotent.
1235 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); 1445 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
1236 1446
1237 Handle<Code> code(Builtins::builtin(Builtins::FrameDropper_LiveEdit)); 1447 ResetFrameScope(bottom_js_frame);
1238 top_frame->set_pc(code->entry()); 1448
1449 SharedFunctionInfo* bottom_function =
1450 JSFunction::cast(bottom_js_frame->function())->shared();
1451
1452 ASSERT_EQ(bottom_function, expected_function);
1453
1454 Code* bottom_frame_code = bottom_function->code();
1455
1456 top_frame->set_pc(LiveEdit::GetRestarterPatchEntryPoint(bottom_frame_code));
1239 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); 1457 pre_top_frame->SetCallerFp(bottom_js_frame->fp());
1240 1458
1241 Debug::SetUpFrameDropperFrame(bottom_js_frame, code);
1242
1243 for (Address a = unused_stack_top; 1459 for (Address a = unused_stack_top;
1244 a < unused_stack_bottom; 1460 a < unused_stack_bottom;
1245 a += kPointerSize) { 1461 a += kPointerSize) {
1246 Memory::Object_at(a) = Smi::FromInt(0); 1462 Memory::Object_at(a) = Smi::FromInt(0);
1247 } 1463 }
1464 }
1248 1465
1249 return NULL;
1250 }
1251 1466
1252 1467
1253 static bool IsDropableFrame(StackFrame* frame) { 1468 static bool IsDropableFrame(StackFrame* frame) {
1254 return !frame->is_exit(); 1469 return !frame->is_exit();
1255 } 1470 }
1256 1471
1257 // Fills result array with statuses of functions. Modifies the stack 1472 // Iterates over the stack and decides whether it contains any of listed
1258 // removing all listed function if possible and if do_drop is true. 1473 // functions' activations or not. If it does contain, return the plan on
1259 static const char* DropActivationsInActiveThread( 1474 // how the stack could be modified or failure description.
1260 Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) { 1475 static Handle<JSArray> PrepareActiveStackModification(
1476 Handle<JSArray> shared_info_array) {
1261 1477
1262 ZoneScope scope(DELETE_ON_EXIT); 1478 ZoneScope scope(DELETE_ON_EXIT);
1263 Vector<StackFrame*> frames = CreateStackMap(); 1479 Vector<StackFrame*> frames = CreateStackMap();
1264 1480
1265 int array_len = Smi::cast(shared_info_array->length())->value();
1266
1267 int top_frame_index = -1; 1481 int top_frame_index = -1;
1268 int frame_index = 0; 1482 int frame_index = 0;
1269 for (; frame_index < frames.length(); frame_index++) { 1483 for (; frame_index < frames.length(); frame_index++) {
1270 StackFrame* frame = frames[frame_index]; 1484 StackFrame* frame = frames[frame_index];
1271 if (frame->id() == Debug::break_frame_id()) { 1485 if (frame->id() == Debug::break_frame_id()) {
1272 top_frame_index = frame_index; 1486 top_frame_index = frame_index;
1273 break; 1487 break;
1274 } 1488 }
1275 if (CheckActivation(shared_info_array, result, frame, 1489 int problem_function_index = CheckActivation(shared_info_array, frame);
1276 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { 1490 if (problem_function_index != -1) {
1277 // We are still above break_frame. It is not a target frame, 1491 return StackManipulationInfo::CreateError(
1278 // it is a problem. 1492 "Debugger mark-up on stack is not found",
1279 return "Debugger mark-up on stack is not found"; 1493 problem_function_index);
1280 } 1494 }
1281 } 1495 }
1282 1496
1283 if (top_frame_index == -1) { 1497 if (top_frame_index == -1) {
1284 // We haven't found break frame, but no function is blocking us anyway. 1498 // We haven't found break frame, but no function is blocking us anyway.
1285 return NULL; 1499 return StackManipulationInfo::CreateEmpty();
1286 } 1500 }
1287 1501
1288 bool target_frame_found = false; 1502 int target_function_index = -1;
1289 int bottom_js_frame_index = top_frame_index; 1503 int bottom_js_frame_index = top_frame_index;
1290 bool c_code_found = false; 1504 bool c_code_found = false;
1291 1505
1292 for (; frame_index < frames.length(); frame_index++) { 1506 for (; frame_index < frames.length(); frame_index++) {
1293 StackFrame* frame = frames[frame_index]; 1507 StackFrame* frame = frames[frame_index];
1294 if (!IsDropableFrame(frame)) { 1508 if (!IsDropableFrame(frame)) {
1295 c_code_found = true; 1509 c_code_found = true;
1296 break; 1510 break;
1297 } 1511 }
1298 if (CheckActivation(shared_info_array, result, frame, 1512 int problem_function_index = CheckActivation(shared_info_array, frame);
1299 LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 1513 if (problem_function_index != -1) {
1300 target_frame_found = true; 1514 target_function_index = problem_function_index;
1301 bottom_js_frame_index = frame_index; 1515 bottom_js_frame_index = frame_index;
1302 } 1516 }
1303 } 1517 }
1304 1518
1305 if (c_code_found) { 1519 if (c_code_found) {
1306 // There is a C frames on stack. Check that there are no target frames 1520 // There is a C frames on stack. Check that there are no target frames
1307 // below them. 1521 // below them.
1308 for (; frame_index < frames.length(); frame_index++) { 1522 for (; frame_index < frames.length(); frame_index++) {
1309 StackFrame* frame = frames[frame_index]; 1523 StackFrame* frame = frames[frame_index];
1310 if (frame->is_java_script()) { 1524 if (frame->is_java_script()) {
1311 if (CheckActivation(shared_info_array, result, frame, 1525 int problem_function_index = CheckActivation(shared_info_array, frame);
1312 LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { 1526 if (problem_function_index != -1) {
1313 // Cannot drop frame under C frames. 1527 return StackManipulationInfo::CreateError(
1314 return NULL; 1528 "Cannot drop frame under C frames",
1529 problem_function_index);
1315 } 1530 }
1316 } 1531 }
1317 } 1532 }
1318 } 1533 }
1319 1534
1320 if (!do_drop) { 1535 if (target_function_index == -1) {
1321 // We are in check-only mode. 1536 return StackManipulationInfo::CreateEmpty();
1322 return NULL;
1323 } 1537 }
1324 1538
1325 if (!target_frame_found) { 1539 return PrepareDropFrames(frames, top_frame_index, bottom_js_frame_index,
1326 // Nothing to drop. 1540 target_function_index);
1327 return NULL; 1541 }
1542
1543
1544 // Unpacks stack manipulation data and operates stack manipulation procedure.
1545 static void PerformActiveStackModification(
1546 ByteArray* stack_manipulation_data,
1547 SharedFunctionInfo* expected_function) {
1548 StackModificationPlanHeader* plan =
1549 reinterpret_cast<StackModificationPlanHeader*>(
1550 stack_manipulation_data->GetDataStartAddress());
1551
1552 StackFrame* pre_top_frame;
1553 StackFrame* top_frame;
1554 StackFrame* bottom_frame;
1555 {
1556 byte* pos = reinterpret_cast<byte*>(plan);
1557 pos += sizeof(StackModificationPlanHeader);
1558 pre_top_frame = reinterpret_cast<StackFrame*>(pos);
1559 pos += GetStackFrameObjectSize(pre_top_frame);
1560 top_frame = reinterpret_cast<StackFrame*>(pos);
1561 pos += GetStackFrameObjectSize(top_frame);
1562 bottom_frame = reinterpret_cast<StackFrame*>(pos);
1328 } 1563 }
1564 JavaScriptFrame* bottom_js_frame = JavaScriptFrame::cast(bottom_frame);
1329 1565
1330 Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED;
1331 const char* error_message = DropFrames(frames, top_frame_index,
1332 bottom_js_frame_index, &drop_mode);
1333 1566
1334 if (error_message != NULL) { 1567 DoDropFrames(pre_top_frame, top_frame, bottom_js_frame,
1335 return error_message; 1568 plan->unused_stack_top, plan->unused_stack_bottom,
1336 } 1569 expected_function);
1337 1570
1338 // Adjust break_frame after some frames has been dropped. 1571 Debug::FramesHaveBeenDropped(bottom_js_frame, plan->frame_drop_mode);
1339 StackFrame::Id new_id = StackFrame::NO_ID; 1572 ASSERT(LiveEdit::IsAtFrameResetPatch(bottom_js_frame));
1340 for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
1341 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
1342 new_id = frames[i]->id();
1343 break;
1344 }
1345 }
1346 Debug::FramesHaveBeenDropped(new_id, drop_mode);
1347
1348 // Replace "blocked on active" with "replaced on active" status.
1349 for (int i = 0; i < array_len; i++) {
1350 if (result->GetElement(i) ==
1351 Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1352 result->SetElement(i, Smi::FromInt(
1353 LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
1354 }
1355 }
1356 return NULL;
1357 } 1573 }
1358 1574
1359 1575
1360 class InactiveThreadActivationsChecker : public ThreadVisitor { 1576 class InactiveThreadActivationsChecker : public ThreadVisitor {
1361 public: 1577 public:
1362 InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array, 1578 explicit InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array)
1363 Handle<JSArray> result) 1579 : shared_info_array_(shared_info_array), blocked_function_index_(-1) {
1364 : shared_info_array_(shared_info_array), result_(result),
1365 has_blocked_functions_(false) {
1366 } 1580 }
1367 void VisitThread(ThreadLocalTop* top) { 1581 void VisitThread(ThreadLocalTop* top) {
1368 for (StackFrameIterator it(top); !it.done(); it.Advance()) { 1582 for (StackFrameIterator it(top); !it.done(); it.Advance()) {
1369 has_blocked_functions_ |= CheckActivation( 1583 if (blocked_function_index_ == -1) {
1370 shared_info_array_, result_, it.frame(), 1584 blocked_function_index_ = CheckActivation(shared_info_array_,
1371 LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK); 1585 it.frame());
1586 }
1372 } 1587 }
1373 } 1588 }
1374 bool HasBlockedFunctions() { 1589 int GetBlockedFunctionIndex() {
1375 return has_blocked_functions_; 1590 return blocked_function_index_;
1376 } 1591 }
1377 1592
1378 private: 1593 private:
1379 Handle<JSArray> shared_info_array_; 1594 Handle<JSArray> shared_info_array_;
1380 Handle<JSArray> result_; 1595 int blocked_function_index_;
1381 bool has_blocked_functions_;
1382 }; 1596 };
1383 1597
1384 1598
1385 Handle<JSArray> LiveEdit::CheckAndDropActivations( 1599 Handle<JSArray> LiveEdit::CheckActivations(Handle<JSArray> shared_info_array) {
1386 Handle<JSArray> shared_info_array, bool do_drop) { 1600 // First check inactive threads. Fail if some functions are blocked there.
1387 int len = Smi::cast(shared_info_array->length())->value(); 1601 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array);
1602 ThreadManager::IterateArchivedThreads(&inactive_threads_checker);
1388 1603
1389 Handle<JSArray> result = Factory::NewJSArray(len); 1604 if (inactive_threads_checker.GetBlockedFunctionIndex() != -1) {
1390 1605 return StackManipulationInfo::CreateError(
1391 // Fill the default values. 1606 "Cannot patch function that is activated in inactive thread",
1392 for (int i = 0; i < len; i++) { 1607 inactive_threads_checker.GetBlockedFunctionIndex());
1393 SetElement(result, i,
1394 Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
1395 } 1608 }
1396 1609
1397 1610 return PrepareActiveStackModification(shared_info_array);
1398 // First check inactive threads. Fail if some functions are blocked there.
1399 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
1400 result);
1401 ThreadManager::IterateArchivedThreads(&inactive_threads_checker);
1402 if (inactive_threads_checker.HasBlockedFunctions()) {
1403 return result;
1404 }
1405
1406 // Try to drop activations from the current stack.
1407 const char* error_message =
1408 DropActivationsInActiveThread(shared_info_array, result, do_drop);
1409 if (error_message != NULL) {
1410 // Add error message as an array extra element.
1411 Vector<const char> vector_message(error_message, StrLength(error_message));
1412 Handle<String> str = Factory::NewStringFromAscii(vector_message);
1413 SetElement(result, len, str);
1414 }
1415 return result;
1416 } 1611 }
1417 1612
1418 1613
1419 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { 1614 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
1420 if (active_function_info_listener != NULL) { 1615 if (active_function_info_listener != NULL) {
1421 active_function_info_listener->FunctionStarted(fun); 1616 active_function_info_listener->FunctionStarted(fun);
1422 } 1617 }
1423 } 1618 }
1424 1619
1425 1620
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1471 1666
1472 bool LiveEditFunctionTracker::IsActive() { 1667 bool LiveEditFunctionTracker::IsActive() {
1473 return false; 1668 return false;
1474 } 1669 }
1475 1670
1476 #endif // ENABLE_DEBUGGER_SUPPORT 1671 #endif // ENABLE_DEBUGGER_SUPPORT
1477 1672
1478 1673
1479 1674
1480 } } // namespace v8::internal 1675 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698