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

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: style Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 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 // Finds all instances of JSFunction that refers to the provided shared_info.
1025 // Return their number and optionally writes them into output array.
1026 static int FindJSFunctions(Handle<SharedFunctionInfo> shared_info,
1027 Handle<FixedArray> output) {
1028 int pos = 0;
1029
1030 AssertNoAllocation no_allocations_please;
1031
1032 SharedFunctionInfo* shared_info_raw = *shared_info;
1033 HeapIterator iterator;
1034 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
1035 if (obj->IsJSFunction()) {
1036 JSFunction* function = JSFunction::cast(obj);
1037 if (function->shared() == shared_info_raw) {
1038 if (!output.is_null()) {
1039 output->set(pos, function);
1040 }
1041 pos++;
1042 }
1043 }
1044 }
1045 return pos;
1046 }
1047
1048
1049 // Finds all instances of JSFunction that refers to the provided shared_info
1050 // and returns array with them.
1051 static Handle<FixedArray> CollectJSFunctions(
1052 Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
1053 int size = FindJSFunctions(shared_info, Handle<FixedArray>::null());
1054 Handle<FixedArray> result = isolate->factory()->NewFixedArray(size);
1055 if (size > 0) {
1056 FindJSFunctions(shared_info, result);
Yang 2012/10/23 16:10:31 Running twice over the heap seems really inefficie
Peter Rybin 2012/11/11 03:28:47 In fact I only copy how Runtime_DebugReferencedBy
1057 }
1058 return result;
1059 }
1060
1061
1017 // Check whether the code is natural function code (not a lazy-compile stub 1062 // Check whether the code is natural function code (not a lazy-compile stub
1018 // code). 1063 // code).
1019 static bool IsJSFunctionCode(Code* code) { 1064 static bool IsJSFunctionCode(Code* code) {
1020 return code->kind() == Code::FUNCTION; 1065 return code->kind() == Code::FUNCTION;
1021 } 1066 }
1022 1067
1023 1068
1024 // Returns true if an instance of candidate were inlined into function's code. 1069 // Returns true if an instance of candidate were inlined into function's code.
1025 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { 1070 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) {
1026 AssertNoAllocation no_gc; 1071 AssertNoAllocation no_gc;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1073 1118
1074 DependentFunctionsDeoptimizingVisitor visitor(function_info); 1119 DependentFunctionsDeoptimizingVisitor visitor(function_info);
1075 Deoptimizer::VisitAllOptimizedFunctions(&visitor); 1120 Deoptimizer::VisitAllOptimizedFunctions(&visitor);
1076 } 1121 }
1077 1122
1078 1123
1079 MaybeObject* LiveEdit::ReplaceFunctionCode( 1124 MaybeObject* LiveEdit::ReplaceFunctionCode(
1080 Handle<JSArray> new_compile_info_array, 1125 Handle<JSArray> new_compile_info_array,
1081 Handle<JSArray> shared_info_array) { 1126 Handle<JSArray> shared_info_array) {
1082 HandleScope scope; 1127 HandleScope scope;
1128 Isolate* isolate = Isolate::Current();
1083 1129
1084 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { 1130 if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
1085 return Isolate::Current()->ThrowIllegalOperation(); 1131 return isolate->ThrowIllegalOperation();
1086 } 1132 }
1087 1133
1088 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); 1134 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
1089 SharedInfoWrapper shared_info_wrapper(shared_info_array); 1135 SharedInfoWrapper shared_info_wrapper(shared_info_array);
1090 1136
1091 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); 1137 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
1092 1138
1093 HEAP->EnsureHeapIsIterable(); 1139 HEAP->EnsureHeapIsIterable();
1094 1140
1095 if (IsJSFunctionCode(shared_info->code())) { 1141 if (IsJSFunctionCode(shared_info->code())) {
(...skipping 10 matching lines...) Expand all
1106 Handle<Code> new_original_code = 1152 Handle<Code> new_original_code =
1107 FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode()); 1153 FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode());
1108 debug_info->set_original_code(*new_original_code); 1154 debug_info->set_original_code(*new_original_code);
1109 } 1155 }
1110 1156
1111 int start_position = compile_info_wrapper.GetStartPosition(); 1157 int start_position = compile_info_wrapper.GetStartPosition();
1112 int end_position = compile_info_wrapper.GetEndPosition(); 1158 int end_position = compile_info_wrapper.GetEndPosition();
1113 shared_info->set_start_position(start_position); 1159 shared_info->set_start_position(start_position);
1114 shared_info->set_end_position(end_position); 1160 shared_info->set_end_position(end_position);
1115 1161
1162 // Patch function literals.
1163 // TODO(prybin): is the following legit?
1164 // Name 'literals' is a misnomer. Rather it's a cache for complex object
1165 // boilerplates and for a native context. We must clean cached values or
1166 // adjust array size.
Yang 2012/10/23 16:10:31 Wouldn't adjusting array size imply cleaning cache
Peter Rybin 2012/11/11 03:28:47 Done.
1167 {
1168 int new_literal_count = compile_info_wrapper.GetLiteralCount();
1169 if (new_literal_count > 0) {
1170 new_literal_count += JSFunction::kLiteralsPrefixSize;
1171 }
1172 shared_info->set_num_literals(new_literal_count);
1173
1174 Handle<FixedArray> function_instances =
1175 CollectJSFunctions(shared_info, isolate);
1176 for (int i = 0; i < function_instances->length(); i++) {
Yang 2012/10/23 16:10:31 Instead of looping over function instances that yo
Peter Rybin 2012/11/11 03:28:47 I have to update literal array, and possibly creat
1177 Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i)));
1178 Handle<FixedArray> old_literals(fun->literals());
1179 if (old_literals->length() == new_literal_count) {
1180 for (int j = JSFunction::kLiteralsPrefixSize;
1181 j < new_literal_count; j++) {
1182 old_literals->set(j, isolate->heap()->undefined_value());
Yang 2012/10/23 16:10:31 I guess you could use FixedArray->set_undefined he
Peter Rybin 2012/11/11 03:28:47 Done.
1183 }
1184 } else {
1185 Handle<FixedArray> new_literals =
1186 isolate->factory()->NewFixedArray(new_literal_count);
1187 if (new_literal_count > 0) {
1188 Handle<Context> native_context;
1189 if (old_literals->length() >
1190 JSFunction::kLiteralNativeContextIndex) {
1191 native_context = Handle<Context>(
1192 JSFunction::NativeContextFromLiterals(fun->literals()));
1193 } else {
1194 native_context = Handle<Context>(fun->context()->native_context());
1195 }
1196 new_literals->set(JSFunction::kLiteralNativeContextIndex,
1197 *native_context);
1198 }
1199 fun->set_literals(*new_literals);
1200 }
Yang 2012/10/23 16:10:31 I assume that we are not dealing with optimized co
Peter Rybin 2012/11/11 03:28:47 May be it more safe to always create an accurate l
1201 }
1202 }
1203
1116 shared_info->set_construct_stub( 1204 shared_info->set_construct_stub(
1117 Isolate::Current()->builtins()->builtin( 1205 Isolate::Current()->builtins()->builtin(
1118 Builtins::kJSConstructStubGeneric)); 1206 Builtins::kJSConstructStubGeneric));
1119 1207
1120 DeoptimizeDependentFunctions(*shared_info); 1208 DeoptimizeDependentFunctions(*shared_info);
1121 Isolate::Current()->compilation_cache()->Remove(shared_info); 1209 Isolate::Current()->compilation_cache()->Remove(shared_info);
1122 1210
1123 return HEAP->undefined_value(); 1211 return HEAP->undefined_value();
1124 } 1212 }
1125 1213
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
1921 2009
1922 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { 2010 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
1923 return false; 2011 return false;
1924 } 2012 }
1925 2013
1926 #endif // ENABLE_DEBUGGER_SUPPORT 2014 #endif // ENABLE_DEBUGGER_SUPPORT
1927 2015
1928 2016
1929 2017
1930 } } // namespace v8::internal 2018 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/debug-liveedit-literals.js » ('j') | test/mjsunit/debug-liveedit-literals.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698