OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 static void PatchLiterals(FunctionInfoWrapper* compile_info_wrapper, |
| 1032 Handle<SharedFunctionInfo> shared_info, |
| 1033 Isolate* isolate) { |
| 1034 int new_literal_count = compile_info_wrapper->GetLiteralCount(); |
| 1035 if (new_literal_count > 0) { |
| 1036 new_literal_count += JSFunction::kLiteralsPrefixSize; |
| 1037 } |
| 1038 int old_literal_count = shared_info->num_literals(); |
| 1039 |
| 1040 if (old_literal_count == new_literal_count) { |
| 1041 // If literal count didn't change, simply go over all functions |
| 1042 // and clear literal arrays. |
| 1043 ClearValuesVisitor visitor; |
| 1044 IterateJSFunctions(*shared_info, &visitor); |
| 1045 } else { |
| 1046 // When literal count changes, we have to create new array instances. |
| 1047 // Since we cannot create instances when iterating heap, we should first |
| 1048 // collect all functions and fix their literal arrays. |
| 1049 Handle<FixedArray> function_instances = |
| 1050 CollectJSFunctions(shared_info, isolate); |
| 1051 for (int i = 0; i < function_instances->length(); i++) { |
| 1052 Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i))); |
| 1053 Handle<FixedArray> old_literals(fun->literals()); |
| 1054 Handle<FixedArray> new_literals = |
| 1055 isolate->factory()->NewFixedArray(new_literal_count); |
| 1056 if (new_literal_count > 0) { |
| 1057 Handle<Context> native_context; |
| 1058 if (old_literals->length() > |
| 1059 JSFunction::kLiteralNativeContextIndex) { |
| 1060 native_context = Handle<Context>( |
| 1061 JSFunction::NativeContextFromLiterals(fun->literals())); |
| 1062 } else { |
| 1063 native_context = Handle<Context>(fun->context()->native_context()); |
| 1064 } |
| 1065 new_literals->set(JSFunction::kLiteralNativeContextIndex, |
| 1066 *native_context); |
| 1067 } |
| 1068 fun->set_literals(*new_literals); |
| 1069 } |
| 1070 |
| 1071 shared_info->set_num_literals(new_literal_count); |
| 1072 } |
| 1073 } |
| 1074 |
| 1075 private: |
| 1076 // Iterates all function instances in the HEAP that refers to the |
| 1077 // provided shared_info. |
| 1078 template<typename Visitor> |
| 1079 static void IterateJSFunctions(SharedFunctionInfo* shared_info, |
| 1080 Visitor* visitor) { |
| 1081 AssertNoAllocation no_allocations_please; |
| 1082 |
| 1083 HeapIterator iterator; |
| 1084 for (HeapObject* obj = iterator.next(); obj != NULL; |
| 1085 obj = iterator.next()) { |
| 1086 if (obj->IsJSFunction()) { |
| 1087 JSFunction* function = JSFunction::cast(obj); |
| 1088 if (function->shared() == shared_info) { |
| 1089 visitor->visit(function); |
| 1090 } |
| 1091 } |
| 1092 } |
| 1093 } |
| 1094 |
| 1095 // Finds all instances of JSFunction that refers to the provided shared_info |
| 1096 // and returns array with them. |
| 1097 static Handle<FixedArray> CollectJSFunctions( |
| 1098 Handle<SharedFunctionInfo> shared_info, Isolate* isolate) { |
| 1099 CountVisitor count_visitor; |
| 1100 count_visitor.count = 0; |
| 1101 IterateJSFunctions(*shared_info, &count_visitor); |
| 1102 int size = count_visitor.count; |
| 1103 |
| 1104 Handle<FixedArray> result = isolate->factory()->NewFixedArray(size); |
| 1105 if (size > 0) { |
| 1106 CollectVisitor collect_visitor(result); |
| 1107 IterateJSFunctions(*shared_info, &collect_visitor); |
| 1108 } |
| 1109 return result; |
| 1110 } |
| 1111 |
| 1112 class ClearValuesVisitor { |
| 1113 public: |
| 1114 void visit(JSFunction* fun) { |
| 1115 FixedArray* literals = fun->literals(); |
| 1116 int len = literals->length(); |
| 1117 for (int j = JSFunction::kLiteralsPrefixSize; j < len; j++) { |
| 1118 literals->set_undefined(j); |
| 1119 } |
| 1120 } |
| 1121 }; |
| 1122 |
| 1123 class CountVisitor { |
| 1124 public: |
| 1125 void visit(JSFunction* fun) { |
| 1126 count++; |
| 1127 } |
| 1128 int count; |
| 1129 }; |
| 1130 |
| 1131 class CollectVisitor { |
| 1132 public: |
| 1133 explicit CollectVisitor(Handle<FixedArray> output) |
| 1134 : m_output(output), m_pos(0) {} |
| 1135 |
| 1136 void visit(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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |