| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 | 28 |
| 29 #include "v8.h" | 29 #include "v8.h" |
| 30 | 30 |
| 31 #include "liveedit.h" | 31 #include "liveedit.h" |
| 32 | 32 |
| 33 #include "compiler.h" | 33 #include "compiler.h" |
| 34 #include "compilation-cache.h" |
| 34 #include "debug.h" | 35 #include "debug.h" |
| 36 #include "deoptimizer.h" |
| 35 #include "global-handles.h" | 37 #include "global-handles.h" |
| 36 #include "memory.h" | 38 #include "memory.h" |
| 37 #include "oprofile-agent.h" | 39 #include "oprofile-agent.h" |
| 38 #include "parser.h" | 40 #include "parser.h" |
| 39 #include "scopeinfo.h" | 41 #include "scopeinfo.h" |
| 40 #include "scopes.h" | 42 #include "scopes.h" |
| 41 | 43 |
| 42 namespace v8 { | 44 namespace v8 { |
| 43 namespace internal { | 45 namespace internal { |
| 44 | 46 |
| (...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 info.SetInitialProperties(fun->name(), fun->start_position(), | 605 info.SetInitialProperties(fun->name(), fun->start_position(), |
| 604 fun->end_position(), fun->num_parameters(), | 606 fun->end_position(), fun->num_parameters(), |
| 605 current_parent_index_); | 607 current_parent_index_); |
| 606 current_parent_index_ = len_; | 608 current_parent_index_ = len_; |
| 607 SetElement(result_, len_, info.GetJSArray()); | 609 SetElement(result_, len_, info.GetJSArray()); |
| 608 len_++; | 610 len_++; |
| 609 } | 611 } |
| 610 | 612 |
| 611 void FunctionDone() { | 613 void FunctionDone() { |
| 612 HandleScope scope; | 614 HandleScope scope; |
| 613 Object* element = | 615 FunctionInfoWrapper info = |
| 614 result_->GetElementNoExceptionThrown(current_parent_index_); | 616 FunctionInfoWrapper::cast( |
| 615 FunctionInfoWrapper info = FunctionInfoWrapper::cast(element); | 617 result_->GetElementNoExceptionThrown(current_parent_index_)); |
| 616 current_parent_index_ = info.GetParentIndex(); | 618 current_parent_index_ = info.GetParentIndex(); |
| 617 } | 619 } |
| 618 | 620 |
| 619 // Saves only function code, because for a script function we | 621 // Saves only function code, because for a script function we |
| 620 // may never create a SharedFunctionInfo object. | 622 // may never create a SharedFunctionInfo object. |
| 621 void FunctionCode(Handle<Code> function_code) { | 623 void FunctionCode(Handle<Code> function_code) { |
| 622 Object* element = | 624 FunctionInfoWrapper info = |
| 623 result_->GetElementNoExceptionThrown(current_parent_index_); | 625 FunctionInfoWrapper::cast( |
| 624 FunctionInfoWrapper info = FunctionInfoWrapper::cast(element); | 626 result_->GetElementNoExceptionThrown(current_parent_index_)); |
| 625 info.SetFunctionCode(function_code, Handle<Object>(HEAP->null_value())); | 627 info.SetFunctionCode(function_code, Handle<Object>(HEAP->null_value())); |
| 626 } | 628 } |
| 627 | 629 |
| 628 // Saves full information about a function: its code, its scope info | 630 // Saves full information about a function: its code, its scope info |
| 629 // and a SharedFunctionInfo object. | 631 // and a SharedFunctionInfo object. |
| 630 void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) { | 632 void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) { |
| 631 if (!shared->IsSharedFunctionInfo()) { | 633 if (!shared->IsSharedFunctionInfo()) { |
| 632 return; | 634 return; |
| 633 } | 635 } |
| 634 Object* element = | 636 FunctionInfoWrapper info = |
| 635 result_->GetElementNoExceptionThrown(current_parent_index_); | 637 FunctionInfoWrapper::cast( |
| 636 FunctionInfoWrapper info = FunctionInfoWrapper::cast(element); | 638 result_->GetElementNoExceptionThrown(current_parent_index_)); |
| 637 info.SetFunctionCode(Handle<Code>(shared->code()), | 639 info.SetFunctionCode(Handle<Code>(shared->code()), |
| 638 Handle<Object>(shared->scope_info())); | 640 Handle<Object>(shared->scope_info())); |
| 639 info.SetSharedFunctionInfo(shared); | 641 info.SetSharedFunctionInfo(shared); |
| 640 | 642 |
| 641 Handle<Object> scope_info_list(SerializeFunctionScope(scope)); | 643 Handle<Object> scope_info_list(SerializeFunctionScope(scope)); |
| 642 info.SetOuterScopeInfo(scope_info_list); | 644 info.SetOuterScopeInfo(scope_info_list); |
| 643 } | 645 } |
| 644 | 646 |
| 645 Handle<JSArray> GetResult() { return result_; } | 647 Handle<JSArray> GetResult() { return result_; } |
| 646 | 648 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 } | 827 } |
| 826 | 828 |
| 827 | 829 |
| 828 // Check whether the code is natural function code (not a lazy-compile stub | 830 // Check whether the code is natural function code (not a lazy-compile stub |
| 829 // code). | 831 // code). |
| 830 static bool IsJSFunctionCode(Code* code) { | 832 static bool IsJSFunctionCode(Code* code) { |
| 831 return code->kind() == Code::FUNCTION; | 833 return code->kind() == Code::FUNCTION; |
| 832 } | 834 } |
| 833 | 835 |
| 834 | 836 |
| 837 // Returns true if an instance of candidate were inlined into function's code. |
| 838 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { |
| 839 AssertNoAllocation no_gc; |
| 840 |
| 841 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false; |
| 842 |
| 843 DeoptimizationInputData* data = |
| 844 DeoptimizationInputData::cast(function->code()->deoptimization_data()); |
| 845 |
| 846 if (data == HEAP->empty_fixed_array()) return false; |
| 847 |
| 848 FixedArray* literals = data->LiteralArray(); |
| 849 |
| 850 int inlined_count = data->InlinedFunctionCount()->value(); |
| 851 for (int i = 0; i < inlined_count; ++i) { |
| 852 JSFunction* inlined = JSFunction::cast(literals->get(i)); |
| 853 if (inlined->shared() == candidate) return true; |
| 854 } |
| 855 |
| 856 return false; |
| 857 } |
| 858 |
| 859 |
| 860 class DependentFunctionsDeoptimizingVisitor : public OptimizedFunctionVisitor { |
| 861 public: |
| 862 explicit DependentFunctionsDeoptimizingVisitor( |
| 863 SharedFunctionInfo* function_info) |
| 864 : function_info_(function_info) {} |
| 865 |
| 866 virtual void EnterContext(Context* context) { |
| 867 } |
| 868 |
| 869 virtual void VisitFunction(JSFunction* function) { |
| 870 if (function->shared() == function_info_ || |
| 871 IsInlined(function, function_info_)) { |
| 872 Deoptimizer::DeoptimizeFunction(function); |
| 873 } |
| 874 } |
| 875 |
| 876 virtual void LeaveContext(Context* context) { |
| 877 } |
| 878 |
| 879 private: |
| 880 SharedFunctionInfo* function_info_; |
| 881 }; |
| 882 |
| 883 |
| 884 static void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) { |
| 885 AssertNoAllocation no_allocation; |
| 886 |
| 887 DependentFunctionsDeoptimizingVisitor visitor(function_info); |
| 888 Deoptimizer::VisitAllOptimizedFunctions(&visitor); |
| 889 } |
| 890 |
| 891 |
| 835 MaybeObject* LiveEdit::ReplaceFunctionCode( | 892 MaybeObject* LiveEdit::ReplaceFunctionCode( |
| 836 Handle<JSArray> new_compile_info_array, | 893 Handle<JSArray> new_compile_info_array, |
| 837 Handle<JSArray> shared_info_array) { | 894 Handle<JSArray> shared_info_array) { |
| 838 HandleScope scope; | 895 HandleScope scope; |
| 839 | 896 |
| 840 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { | 897 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 841 return Isolate::Current()->ThrowIllegalOperation(); | 898 return Isolate::Current()->ThrowIllegalOperation(); |
| 842 } | 899 } |
| 843 | 900 |
| 844 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); | 901 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 862 debug_info->set_original_code(*new_original_code); | 919 debug_info->set_original_code(*new_original_code); |
| 863 } | 920 } |
| 864 | 921 |
| 865 shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); | 922 shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); |
| 866 shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); | 923 shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); |
| 867 | 924 |
| 868 shared_info->set_construct_stub( | 925 shared_info->set_construct_stub( |
| 869 Isolate::Current()->builtins()->builtin( | 926 Isolate::Current()->builtins()->builtin( |
| 870 Builtins::JSConstructStubGeneric)); | 927 Builtins::JSConstructStubGeneric)); |
| 871 | 928 |
| 929 DeoptimizeDependentFunctions(*shared_info); |
| 930 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 931 |
| 872 return HEAP->undefined_value(); | 932 return HEAP->undefined_value(); |
| 873 } | 933 } |
| 874 | 934 |
| 875 | 935 |
| 876 // TODO(635): Eval caches its scripts (same text -- same compiled info). | 936 MaybeObject* LiveEdit::FunctionSourceUpdated( |
| 877 // Make sure we clear such caches. | 937 Handle<JSArray> shared_info_array) { |
| 938 HandleScope scope; |
| 939 |
| 940 if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
| 941 return Isolate::Current()->ThrowIllegalOperation(); |
| 942 } |
| 943 |
| 944 SharedInfoWrapper shared_info_wrapper(shared_info_array); |
| 945 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); |
| 946 |
| 947 DeoptimizeDependentFunctions(*shared_info); |
| 948 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 949 |
| 950 return HEAP->undefined_value(); |
| 951 } |
| 952 |
| 953 |
| 878 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, | 954 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, |
| 879 Handle<Object> script_handle) { | 955 Handle<Object> script_handle) { |
| 880 Handle<SharedFunctionInfo> shared_info = | 956 Handle<SharedFunctionInfo> shared_info = |
| 881 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); | 957 Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); |
| 882 shared_info->set_script(*script_handle); | 958 shared_info->set_script(*script_handle); |
| 959 |
| 960 Isolate::Current()->compilation_cache()->Remove(shared_info); |
| 883 } | 961 } |
| 884 | 962 |
| 885 | 963 |
| 886 // For a script text change (defined as position_change_array), translates | 964 // For a script text change (defined as position_change_array), translates |
| 887 // position in unchanged text to position in changed text. | 965 // position in unchanged text to position in changed text. |
| 888 // Text change is a set of non-overlapping regions in text, that have changed | 966 // Text change is a set of non-overlapping regions in text, that have changed |
| 889 // their contents and length. It is specified as array of groups of 3 numbers: | 967 // their contents and length. It is specified as array of groups of 3 numbers: |
| 890 // (change_begin, change_end, change_end_new_position). | 968 // (change_begin, change_end, change_end_new_position). |
| 891 // Each group describes a change in text; groups are sorted by change_begin. | 969 // Each group describes a change in text; groups are sorted by change_begin. |
| 892 // Only position in text beyond any changes may be successfully translated. | 970 // Only position in text beyond any changes may be successfully translated. |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 it.rinfo()->set_target_object(*subst_shared); | 1212 it.rinfo()->set_target_object(*subst_shared); |
| 1135 } | 1213 } |
| 1136 } | 1214 } |
| 1137 } | 1215 } |
| 1138 } | 1216 } |
| 1139 | 1217 |
| 1140 | 1218 |
| 1141 // Check an activation against list of functions. If there is a function | 1219 // Check an activation against list of functions. If there is a function |
| 1142 // that matches, its status in result array is changed to status argument value. | 1220 // that matches, its status in result array is changed to status argument value. |
| 1143 static bool CheckActivation(Handle<JSArray> shared_info_array, | 1221 static bool CheckActivation(Handle<JSArray> shared_info_array, |
| 1144 Handle<JSArray> result, StackFrame* frame, | 1222 Handle<JSArray> result, |
| 1223 StackFrame* frame, |
| 1145 LiveEdit::FunctionPatchabilityStatus status) { | 1224 LiveEdit::FunctionPatchabilityStatus status) { |
| 1146 if (!frame->is_java_script()) { | 1225 if (!frame->is_java_script()) return false; |
| 1147 return false; | 1226 |
| 1148 } | 1227 Handle<JSFunction> function( |
| 1228 JSFunction::cast(JavaScriptFrame::cast(frame)->function())); |
| 1229 |
| 1149 int len = Smi::cast(shared_info_array->length())->value(); | 1230 int len = Smi::cast(shared_info_array->length())->value(); |
| 1150 for (int i = 0; i < len; i++) { | 1231 for (int i = 0; i < len; i++) { |
| 1151 JSValue* wrapper = | 1232 JSValue* wrapper = |
| 1152 JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i)); | 1233 JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i)); |
| 1153 Handle<SharedFunctionInfo> shared( | 1234 Handle<SharedFunctionInfo> shared( |
| 1154 SharedFunctionInfo::cast(wrapper->value())); | 1235 SharedFunctionInfo::cast(wrapper->value())); |
| 1155 | 1236 |
| 1156 if (frame->LookupCode(Isolate::Current()) == shared->code()) { | 1237 if (function->shared() == *shared || IsInlined(*function, *shared)) { |
| 1157 SetElement(result, i, Handle<Smi>(Smi::FromInt(status))); | 1238 SetElement(result, i, Handle<Smi>(Smi::FromInt(status))); |
| 1158 return true; | 1239 return true; |
| 1159 } | 1240 } |
| 1160 } | 1241 } |
| 1161 return false; | 1242 return false; |
| 1162 } | 1243 } |
| 1163 | 1244 |
| 1164 | 1245 |
| 1165 // Iterates over handler chain and removes all elements that are inside | 1246 // Iterates over handler chain and removes all elements that are inside |
| 1166 // frames being dropped. | 1247 // frames being dropped. |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 | 1570 |
| 1490 bool LiveEditFunctionTracker::IsActive() { | 1571 bool LiveEditFunctionTracker::IsActive() { |
| 1491 return false; | 1572 return false; |
| 1492 } | 1573 } |
| 1493 | 1574 |
| 1494 #endif // ENABLE_DEBUGGER_SUPPORT | 1575 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1495 | 1576 |
| 1496 | 1577 |
| 1497 | 1578 |
| 1498 } } // namespace v8::internal | 1579 } } // namespace v8::internal |
| OLD | NEW |