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

Side by Side Diff: src/liveedit.cc

Issue 11191039: Issue 2368: LiveEdit crashes when new object/array literal is added (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: follow code review Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/mjsunit/debug-liveedit-literals.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 696
697 // Represents some function compilation details. This structure will be used 697 // Represents some function compilation details. This structure will be used
698 // from JavaScript. It contains Code object, which is kept wrapped 698 // from JavaScript. It contains Code object, which is kept wrapped
699 // into a BlindReference for sanitizing reasons. 699 // into a BlindReference for sanitizing reasons.
700 class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> { 700 class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
701 public: 701 public:
702 explicit FunctionInfoWrapper(Handle<JSArray> array) 702 explicit FunctionInfoWrapper(Handle<JSArray> array)
703 : JSArrayBasedStruct<FunctionInfoWrapper>(array) { 703 : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
704 } 704 }
705 void SetInitialProperties(Handle<String> name, int start_position, 705 void SetInitialProperties(Handle<String> name, int start_position,
706 int end_position, int param_num, int parent_index) { 706 int end_position, int param_num,
707 int literal_count, int parent_index) {
707 HandleScope scope; 708 HandleScope scope;
708 this->SetField(kFunctionNameOffset_, name); 709 this->SetField(kFunctionNameOffset_, name);
709 this->SetSmiValueField(kStartPositionOffset_, start_position); 710 this->SetSmiValueField(kStartPositionOffset_, start_position);
710 this->SetSmiValueField(kEndPositionOffset_, end_position); 711 this->SetSmiValueField(kEndPositionOffset_, end_position);
711 this->SetSmiValueField(kParamNumOffset_, param_num); 712 this->SetSmiValueField(kParamNumOffset_, param_num);
713 this->SetSmiValueField(kLiteralNumOffset_, literal_count);
712 this->SetSmiValueField(kParentIndexOffset_, parent_index); 714 this->SetSmiValueField(kParentIndexOffset_, parent_index);
713 } 715 }
714 void SetFunctionCode(Handle<Code> function_code, 716 void SetFunctionCode(Handle<Code> function_code,
715 Handle<Object> code_scope_info) { 717 Handle<Object> code_scope_info) {
716 Handle<JSValue> code_wrapper = WrapInJSValue(function_code); 718 Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
717 this->SetField(kCodeOffset_, code_wrapper); 719 this->SetField(kCodeOffset_, code_wrapper);
718 720
719 Handle<JSValue> scope_wrapper = WrapInJSValue(code_scope_info); 721 Handle<JSValue> scope_wrapper = WrapInJSValue(code_scope_info);
720 this->SetField(kCodeScopeInfoOffset_, scope_wrapper); 722 this->SetField(kCodeScopeInfoOffset_, scope_wrapper);
721 } 723 }
722 void SetOuterScopeInfo(Handle<Object> scope_info_array) { 724 void SetOuterScopeInfo(Handle<Object> scope_info_array) {
723 this->SetField(kOuterScopeInfoOffset_, scope_info_array); 725 this->SetField(kOuterScopeInfoOffset_, scope_info_array);
724 } 726 }
725 void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) { 727 void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) {
726 Handle<JSValue> info_holder = WrapInJSValue(info); 728 Handle<JSValue> info_holder = WrapInJSValue(info);
727 this->SetField(kSharedFunctionInfoOffset_, info_holder); 729 this->SetField(kSharedFunctionInfoOffset_, info_holder);
728 } 730 }
731 int GetLiteralCount() {
732 return this->GetSmiValueField(kLiteralNumOffset_);
733 }
729 int GetParentIndex() { 734 int GetParentIndex() {
730 return this->GetSmiValueField(kParentIndexOffset_); 735 return this->GetSmiValueField(kParentIndexOffset_);
731 } 736 }
732 Handle<Code> GetFunctionCode() { 737 Handle<Code> GetFunctionCode() {
733 Object* element = this->GetField(kCodeOffset_); 738 Object* element = this->GetField(kCodeOffset_);
734 CHECK(element->IsJSValue()); 739 CHECK(element->IsJSValue());
735 Handle<JSValue> value_wrapper(JSValue::cast(element)); 740 Handle<JSValue> value_wrapper(JSValue::cast(element));
736 Handle<Object> raw_result = UnwrapJSValue(value_wrapper); 741 Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
737 CHECK(raw_result->IsCode()); 742 CHECK(raw_result->IsCode());
738 return Handle<Code>::cast(raw_result); 743 return Handle<Code>::cast(raw_result);
(...skipping 13 matching lines...) Expand all
752 private: 757 private:
753 static const int kFunctionNameOffset_ = 0; 758 static const int kFunctionNameOffset_ = 0;
754 static const int kStartPositionOffset_ = 1; 759 static const int kStartPositionOffset_ = 1;
755 static const int kEndPositionOffset_ = 2; 760 static const int kEndPositionOffset_ = 2;
756 static const int kParamNumOffset_ = 3; 761 static const int kParamNumOffset_ = 3;
757 static const int kCodeOffset_ = 4; 762 static const int kCodeOffset_ = 4;
758 static const int kCodeScopeInfoOffset_ = 5; 763 static const int kCodeScopeInfoOffset_ = 5;
759 static const int kOuterScopeInfoOffset_ = 6; 764 static const int kOuterScopeInfoOffset_ = 6;
760 static const int kParentIndexOffset_ = 7; 765 static const int kParentIndexOffset_ = 7;
761 static const int kSharedFunctionInfoOffset_ = 8; 766 static const int kSharedFunctionInfoOffset_ = 8;
762 static const int kSize_ = 9; 767 static const int kLiteralNumOffset_ = 9;
768 static const int kSize_ = 10;
763 769
764 friend class JSArrayBasedStruct<FunctionInfoWrapper>; 770 friend class JSArrayBasedStruct<FunctionInfoWrapper>;
765 }; 771 };
766 772
767 773
768 // Wraps SharedFunctionInfo along with some of its fields for passing it 774 // Wraps SharedFunctionInfo along with some of its fields for passing it
769 // back to JavaScript. SharedFunctionInfo object itself is additionally 775 // back to JavaScript. SharedFunctionInfo object itself is additionally
770 // wrapped into BlindReference for sanitizing reasons. 776 // wrapped into BlindReference for sanitizing reasons.
771 class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> { 777 class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
772 public: 778 public:
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 current_parent_index_ = -1; 818 current_parent_index_ = -1;
813 len_ = 0; 819 len_ = 0;
814 result_ = FACTORY->NewJSArray(10); 820 result_ = FACTORY->NewJSArray(10);
815 } 821 }
816 822
817 void FunctionStarted(FunctionLiteral* fun) { 823 void FunctionStarted(FunctionLiteral* fun) {
818 HandleScope scope; 824 HandleScope scope;
819 FunctionInfoWrapper info = FunctionInfoWrapper::Create(); 825 FunctionInfoWrapper info = FunctionInfoWrapper::Create();
820 info.SetInitialProperties(fun->name(), fun->start_position(), 826 info.SetInitialProperties(fun->name(), fun->start_position(),
821 fun->end_position(), fun->parameter_count(), 827 fun->end_position(), fun->parameter_count(),
828 fun->materialized_literal_count(),
822 current_parent_index_); 829 current_parent_index_);
823 current_parent_index_ = len_; 830 current_parent_index_ = len_;
824 SetElementNonStrict(result_, len_, info.GetJSArray()); 831 SetElementNonStrict(result_, len_, info.GetJSArray());
825 len_++; 832 len_++;
826 } 833 }
827 834
828 void FunctionDone() { 835 void FunctionDone() {
829 HandleScope scope; 836 HandleScope scope;
830 FunctionInfoWrapper info = 837 FunctionInfoWrapper info =
831 FunctionInfoWrapper::cast( 838 FunctionInfoWrapper::cast(
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 1014
1008 // Now iterate over all pointers of all objects, including code_target 1015 // Now iterate over all pointers of all objects, including code_target
1009 // implicit pointers. 1016 // implicit pointers.
1010 HeapIterator iterator; 1017 HeapIterator iterator;
1011 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { 1018 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1012 obj->Iterate(&visitor); 1019 obj->Iterate(&visitor);
1013 } 1020 }
1014 } 1021 }
1015 1022
1016 1023
1024 // Patch function literals.
1025 // Name 'literals' is a misnomer. Rather it's a cache for complex object
1026 // boilerplates and for a native context. We must clean cached values.
1027 // Additionally we may need to allocate a new array if number of literals
1028 // changed.
1029 class LiteralFixer {
1030 public:
1031
1032 static void PatchLiterals(FunctionInfoWrapper* compile_info_wrapper,
1033 Handle<SharedFunctionInfo> shared_info,
1034 Isolate* isolate) {
1035 int new_literal_count = compile_info_wrapper->GetLiteralCount();
1036 if (new_literal_count > 0) {
1037 new_literal_count += JSFunction::kLiteralsPrefixSize;
1038 }
1039 int old_literal_count = shared_info->num_literals();
1040
1041 if (old_literal_count == new_literal_count) {
1042 // If literal count didn't change, simply go over all functions
1043 // and clear literal arrays.
1044 ClearValuesProcessor processor;
1045 IterateJSFunctions(*shared_info, &processor);
Yang 2012/11/12 14:40:57 We usually call this kind of callback *Visitor, as
1046 } else {
1047 // When literal count changes, we have to create new array instances.
1048 // Since we cannot create instances when iterating heap, we should first
1049 // collect all functions and fix their literal arrays.
1050 Handle<FixedArray> function_instances =
1051 CollectJSFunctions(shared_info, isolate);
1052 for (int i = 0; i < function_instances->length(); i++) {
1053 Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i)));
1054 Handle<FixedArray> old_literals(fun->literals());
1055 Handle<FixedArray> new_literals =
1056 isolate->factory()->NewFixedArray(new_literal_count);
1057 if (new_literal_count > 0) {
1058 Handle<Context> native_context;
1059 if (old_literals->length() >
1060 JSFunction::kLiteralNativeContextIndex) {
1061 native_context = Handle<Context>(
1062 JSFunction::NativeContextFromLiterals(fun->literals()));
1063 } else {
1064 native_context = Handle<Context>(fun->context()->native_context());
1065 }
1066 new_literals->set(JSFunction::kLiteralNativeContextIndex,
1067 *native_context);
1068 }
1069 fun->set_literals(*new_literals);
1070 }
1071
1072 shared_info->set_num_literals(new_literal_count);
1073 }
1074 }
1075
1076 private:
1077 // Iterates all function instances in the HEAP that refers to the
1078 // provided shared_info.
1079 template<typename PROCESSOR>
Yang 2012/11/12 14:40:57 I think we usually use lowercase for typename. Als
1080 static void IterateJSFunctions(SharedFunctionInfo* shared_info,
1081 PROCESSOR* processor) {
1082 AssertNoAllocation no_allocations_please;
1083
1084 HeapIterator iterator;
1085 for (HeapObject* obj = iterator.next(); obj != NULL;
1086 obj = iterator.next()) {
1087 if (obj->IsJSFunction()) {
1088 JSFunction* function = JSFunction::cast(obj);
1089 if (function->shared() == shared_info) {
1090 processor->process(function);
1091 }
1092 }
1093 }
1094 }
1095
1096 // Finds all instances of JSFunction that refers to the provided shared_info
1097 // and returns array with them.
1098 static Handle<FixedArray> CollectJSFunctions(
1099 Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
1100 CountProcessor count_processor;
1101 count_processor.count = 0;
1102 IterateJSFunctions(*shared_info, &count_processor);
1103 int size = count_processor.count;
1104
1105 Handle<FixedArray> result = isolate->factory()->NewFixedArray(size);
1106 if (size > 0) {
1107 CollectProcessor collect_processor(result);
1108 IterateJSFunctions(*shared_info, &collect_processor);
1109 }
1110 return result;
1111 }
1112
1113 class ClearValuesProcessor {
1114 public:
1115 void process(JSFunction* fun) {
1116 FixedArray* literals = fun->literals();
1117 int len = literals->length();
1118 for (int j = JSFunction::kLiteralsPrefixSize; j < len; j++) {
1119 literals->set_undefined(j);
1120 }
1121 }
1122 };
1123
1124 class CountProcessor {
1125 public:
1126 void process(JSFunction* fun) {
1127 count++;
1128 }
1129 int count;
1130 };
1131
1132 class CollectProcessor {
1133 public:
1134 CollectProcessor(Handle<FixedArray> output) : m_output(output), m_pos(0) {}
1135
1136 void process(JSFunction* fun) {
1137 m_output->set(m_pos, fun);
1138 m_pos++;
1139 }
1140 private:
1141 Handle<FixedArray> m_output;
1142 int m_pos;
1143 };
1144 };
1145
1146
1017 // Check whether the code is natural function code (not a lazy-compile stub 1147 // Check whether the code is natural function code (not a lazy-compile stub
1018 // code). 1148 // code).
1019 static bool IsJSFunctionCode(Code* code) { 1149 static bool IsJSFunctionCode(Code* code) {
1020 return code->kind() == Code::FUNCTION; 1150 return code->kind() == Code::FUNCTION;
1021 } 1151 }
1022 1152
1023 1153
1024 // Returns true if an instance of candidate were inlined into function's code. 1154 // Returns true if an instance of candidate were inlined into function's code.
1025 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { 1155 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) {
1026 AssertNoAllocation no_gc; 1156 AssertNoAllocation no_gc;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 1203
1074 DependentFunctionsDeoptimizingVisitor visitor(function_info); 1204 DependentFunctionsDeoptimizingVisitor visitor(function_info);
1075 Deoptimizer::VisitAllOptimizedFunctions(&visitor); 1205 Deoptimizer::VisitAllOptimizedFunctions(&visitor);
1076 } 1206 }
1077 1207
1078 1208
1079 MaybeObject* LiveEdit::ReplaceFunctionCode( 1209 MaybeObject* LiveEdit::ReplaceFunctionCode(
1080 Handle<JSArray> new_compile_info_array, 1210 Handle<JSArray> new_compile_info_array,
1081 Handle<JSArray> shared_info_array) { 1211 Handle<JSArray> shared_info_array) {
1082 HandleScope scope; 1212 HandleScope scope;
1213 Isolate* isolate = Isolate::Current();
1083 1214
1084 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { 1215 if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
1085 return Isolate::Current()->ThrowIllegalOperation(); 1216 return isolate->ThrowIllegalOperation();
1086 } 1217 }
1087 1218
1088 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); 1219 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
1089 SharedInfoWrapper shared_info_wrapper(shared_info_array); 1220 SharedInfoWrapper shared_info_wrapper(shared_info_array);
1090 1221
1091 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); 1222 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
1092 1223
1093 HEAP->EnsureHeapIsIterable(); 1224 HEAP->EnsureHeapIsIterable();
1094 1225
1095 if (IsJSFunctionCode(shared_info->code())) { 1226 if (IsJSFunctionCode(shared_info->code())) {
(...skipping 10 matching lines...) Expand all
1106 Handle<Code> new_original_code = 1237 Handle<Code> new_original_code =
1107 FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode()); 1238 FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode());
1108 debug_info->set_original_code(*new_original_code); 1239 debug_info->set_original_code(*new_original_code);
1109 } 1240 }
1110 1241
1111 int start_position = compile_info_wrapper.GetStartPosition(); 1242 int start_position = compile_info_wrapper.GetStartPosition();
1112 int end_position = compile_info_wrapper.GetEndPosition(); 1243 int end_position = compile_info_wrapper.GetEndPosition();
1113 shared_info->set_start_position(start_position); 1244 shared_info->set_start_position(start_position);
1114 shared_info->set_end_position(end_position); 1245 shared_info->set_end_position(end_position);
1115 1246
1247 LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info, isolate);
1248
1116 shared_info->set_construct_stub( 1249 shared_info->set_construct_stub(
1117 Isolate::Current()->builtins()->builtin( 1250 Isolate::Current()->builtins()->builtin(
1118 Builtins::kJSConstructStubGeneric)); 1251 Builtins::kJSConstructStubGeneric));
1119 1252
1120 DeoptimizeDependentFunctions(*shared_info); 1253 DeoptimizeDependentFunctions(*shared_info);
1121 Isolate::Current()->compilation_cache()->Remove(shared_info); 1254 Isolate::Current()->compilation_cache()->Remove(shared_info);
1122 1255
1123 return HEAP->undefined_value(); 1256 return HEAP->undefined_value();
1124 } 1257 }
1125 1258
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 2056
1924 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 2057 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
1925 return false; 2058 return false;
1926 } 2059 }
1927 2060
1928 #endif // ENABLE_DEBUGGER_SUPPORT 2061 #endif // ENABLE_DEBUGGER_SUPPORT
1929 2062
1930 2063
1931 2064
1932 } } // namespace v8::internal 2065 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/debug-liveedit-literals.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698