Chromium Code Reviews| 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 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 } | 214 } |
| 215 | 215 |
| 216 for (var i = 0; i < replace_code_list.length; i++) { | 216 for (var i = 0; i < replace_code_list.length; i++) { |
| 217 PatchFunctionCode(replace_code_list[i], change_log); | 217 PatchFunctionCode(replace_code_list[i], change_log); |
| 218 } | 218 } |
| 219 | 219 |
| 220 var position_patch_report = new Array(); | 220 var position_patch_report = new Array(); |
| 221 change_log.push( {position_patched: position_patch_report} ); | 221 change_log.push( {position_patched: position_patch_report} ); |
| 222 | 222 |
| 223 for (var i = 0; i < update_positions_list.length; i++) { | 223 for (var i = 0; i < update_positions_list.length; i++) { |
| 224 // TODO(LiveEdit): take into account wether it's source_changed or | 224 // TODO(LiveEdit): take into account wether it's source_changed or |
|
aandrey
2013/09/20 12:35:21
wether -> whether
Peter.Rybin
2013/09/20 13:16:51
Done.
| |
| 225 // unchanged and whether positions changed at all. | 225 // unchanged and whether positions changed at all. |
| 226 PatchPositions(update_positions_list[i], diff_array, | 226 PatchPositions(update_positions_list[i], diff_array, |
| 227 position_patch_report); | 227 position_patch_report); |
| 228 | 228 |
| 229 if (update_positions_list[i].live_shared_function_infos) { | 229 if (update_positions_list[i].live_shared_function_infos) { |
| 230 update_positions_list[i].live_shared_function_infos. | 230 update_positions_list[i].live_shared_function_infos. |
| 231 forEach(function (info) { | 231 forEach(function (info) { |
| 232 %LiveEditFunctionSourceUpdated(info.raw_array); | 232 %LiveEditFunctionSourceUpdated(info.raw_array); |
| 233 }); | 233 }); |
| 234 } | 234 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 if (k != i) { | 281 if (k != i) { |
| 282 var temp_info = compile_info[k]; | 282 var temp_info = compile_info[k]; |
| 283 var temp_index = old_index_map[k]; | 283 var temp_index = old_index_map[k]; |
| 284 compile_info[k] = compile_info[i]; | 284 compile_info[k] = compile_info[i]; |
| 285 old_index_map[k] = old_index_map[i]; | 285 old_index_map[k] = old_index_map[i]; |
| 286 compile_info[i] = temp_info; | 286 compile_info[i] = temp_info; |
| 287 old_index_map[i] = temp_index; | 287 old_index_map[i] = temp_index; |
| 288 } | 288 } |
| 289 } | 289 } |
| 290 | 290 |
| 291 // After sorting update outer_inder field using old_index_map. Also | 291 // After sorting update outer_inder field using old_index_map. Also |
|
aandrey
2013/09/20 12:35:21
outer_inder -> outer_index
Peter.Rybin
2013/09/20 13:16:51
Done.
| |
| 292 // set next_sibling_index field. | 292 // set next_sibling_index field. |
| 293 var current_index = 0; | 293 var current_index = 0; |
| 294 | 294 |
| 295 // The recursive function, that goes over all children of a particular | 295 // The recursive function, that goes over all children of a particular |
| 296 // node (i.e. function info). | 296 // node (i.e. function info). |
| 297 function ResetIndexes(new_parent_index, old_parent_index) { | 297 function ResetIndexes(new_parent_index, old_parent_index) { |
| 298 var previous_sibling = -1; | 298 var previous_sibling = -1; |
| 299 while (current_index < compile_info.length && | 299 while (current_index < compile_info.length && |
| 300 compile_info[current_index].outer_index == old_parent_index) { | 300 compile_info[current_index].outer_index == old_parent_index) { |
| 301 var saved_index = current_index; | 301 var saved_index = current_index; |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 685 } | 685 } |
| 686 | 686 |
| 687 function ProcessUnchangedChild(node) { | 687 function ProcessUnchangedChild(node) { |
| 688 node.new_start_pos = chunk_it.TranslatePos(node.info.start_position); | 688 node.new_start_pos = chunk_it.TranslatePos(node.info.start_position); |
| 689 node.new_end_pos = chunk_it.TranslatePos(node.info.end_position); | 689 node.new_end_pos = chunk_it.TranslatePos(node.info.end_position); |
| 690 } | 690 } |
| 691 | 691 |
| 692 ProcessInternals(code_info_tree); | 692 ProcessInternals(code_info_tree); |
| 693 } | 693 } |
| 694 | 694 |
| 695 // For ecah old function (if it is not damaged) tries to find a corresponding | 695 // For ecah old function (if it is not damaged) tries to find a corresponding |
|
Yang
2013/09/20 12:17:34
For each
Peter.Rybin
2013/09/20 13:16:51
Done.
| |
| 696 // function in new script. Typically it should succeed (non-damaged functions | 696 // function in new script. Typically it should succeed (non-damaged functions |
| 697 // by definition may only have changes inside their bodies). However there are | 697 // by definition may only have changes inside their bodies). However there are |
| 698 // reasons for corresponence not to be found; function with unmodified text | 698 // reasons for corresponence not to be found; function with unmodified text |
|
Yang
2013/09/20 12:17:34
correspondence
Peter.Rybin
2013/09/20 13:16:51
Done.
| |
| 699 // in new script may become enclosed into other function; the innocent change | 699 // in new script may become enclosed into other function; the innocent change |
| 700 // inside function body may in fact be something like "} function B() {" that | 700 // inside function body may in fact be something like "} function B() {" that |
| 701 // splits a function into 2 functions. | 701 // splits a function into 2 functions. |
| 702 function FindCorrespondingFunctions(old_code_tree, new_code_tree) { | 702 function FindCorrespondingFunctions(old_code_tree, new_code_tree) { |
| 703 | 703 |
| 704 // A recursive function that tries to find a correspondence for all | 704 // A recursive function that tries to find a correspondence for all |
| 705 // child functions and for their inner functions. | 705 // child functions and for their inner functions. |
| 706 function ProcessChildren(old_node, new_node) { | 706 function ProcessNode(old_node, new_node) { |
| 707 var scope_change_description = | |
| 708 IsFunctionContextLocalsChanged(old_node.info, new_node.info); | |
| 709 if (scope_change_description) { | |
| 710 old_node.status = FunctionStatus.CHANGED; | |
| 711 } | |
| 712 | |
| 707 var old_children = old_node.children; | 713 var old_children = old_node.children; |
| 708 var new_children = new_node.children; | 714 var new_children = new_node.children; |
| 709 | 715 |
| 710 var unmatched_new_nodes_list = []; | 716 var unmatched_new_nodes_list = []; |
| 711 var textually_unmatched_new_nodes_list = []; | 717 var textually_unmatched_new_nodes_list = []; |
| 712 | 718 |
| 713 var old_index = 0; | 719 var old_index = 0; |
| 714 var new_index = 0; | 720 var new_index = 0; |
| 715 while (old_index < old_children.length) { | 721 while (old_index < old_children.length) { |
| 716 if (old_children[old_index].status == FunctionStatus.DAMAGED) { | 722 if (old_children[old_index].status == FunctionStatus.DAMAGED) { |
| 717 old_index++; | 723 old_index++; |
| 718 } else if (new_index < new_children.length) { | 724 } else if (new_index < new_children.length) { |
| 719 if (new_children[new_index].info.start_position < | 725 if (new_children[new_index].info.start_position < |
| 720 old_children[old_index].new_start_pos) { | 726 old_children[old_index].new_start_pos) { |
| 721 unmatched_new_nodes_list.push(new_children[new_index]); | 727 unmatched_new_nodes_list.push(new_children[new_index]); |
| 722 textually_unmatched_new_nodes_list.push(new_children[new_index]); | 728 textually_unmatched_new_nodes_list.push(new_children[new_index]); |
| 723 new_index++; | 729 new_index++; |
| 724 } else if (new_children[new_index].info.start_position == | 730 } else if (new_children[new_index].info.start_position == |
| 725 old_children[old_index].new_start_pos) { | 731 old_children[old_index].new_start_pos) { |
| 726 if (new_children[new_index].info.end_position == | 732 if (new_children[new_index].info.end_position == |
| 727 old_children[old_index].new_end_pos) { | 733 old_children[old_index].new_end_pos) { |
| 728 old_children[old_index].corresponding_node = | 734 old_children[old_index].corresponding_node = |
| 729 new_children[new_index]; | 735 new_children[new_index]; |
| 730 old_children[old_index].textual_corresponding_node = | 736 old_children[old_index].textual_corresponding_node = |
| 731 new_children[new_index]; | 737 new_children[new_index]; |
| 732 if (old_children[old_index].status != FunctionStatus.UNCHANGED) { | 738 if (scope_change_description) { |
| 733 ProcessChildren(old_children[old_index], | 739 old_children[old_index].status = FunctionStatus.DAMAGED; |
| 740 old_children[old_index].status_explanation = | |
| 741 "Enclosing function is now incompatible. " + | |
| 742 scope_change_description; | |
| 743 old_children[old_index].corresponding_node = void 0; | |
| 744 } else if (old_children[old_index].status != | |
| 745 FunctionStatus.UNCHANGED) { | |
| 746 ProcessNode(old_children[old_index], | |
| 734 new_children[new_index]); | 747 new_children[new_index]); |
| 735 if (old_children[old_index].status == FunctionStatus.DAMAGED) { | 748 if (old_children[old_index].status == FunctionStatus.DAMAGED) { |
| 736 unmatched_new_nodes_list.push( | 749 unmatched_new_nodes_list.push( |
| 737 old_children[old_index].corresponding_node); | 750 old_children[old_index].corresponding_node); |
| 738 old_children[old_index].corresponding_node = void 0; | 751 old_children[old_index].corresponding_node = void 0; |
| 739 old_node.status = FunctionStatus.CHANGED; | 752 old_node.status = FunctionStatus.CHANGED; |
| 740 } | 753 } |
| 741 } | 754 } |
| 742 } else { | 755 } else { |
| 743 old_children[old_index].status = FunctionStatus.DAMAGED; | 756 old_children[old_index].status = FunctionStatus.DAMAGED; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 765 } | 778 } |
| 766 } | 779 } |
| 767 | 780 |
| 768 while (new_index < new_children.length) { | 781 while (new_index < new_children.length) { |
| 769 unmatched_new_nodes_list.push(new_children[new_index]); | 782 unmatched_new_nodes_list.push(new_children[new_index]); |
| 770 textually_unmatched_new_nodes_list.push(new_children[new_index]); | 783 textually_unmatched_new_nodes_list.push(new_children[new_index]); |
| 771 new_index++; | 784 new_index++; |
| 772 } | 785 } |
| 773 | 786 |
| 774 if (old_node.status == FunctionStatus.CHANGED) { | 787 if (old_node.status == FunctionStatus.CHANGED) { |
| 775 var why_wrong_expectations = | 788 if (old_node.info.param_num != new_node.info.param_num) { |
| 776 WhyFunctionExpectationsDiffer(old_node.info, new_node.info); | |
| 777 if (why_wrong_expectations) { | |
| 778 old_node.status = FunctionStatus.DAMAGED; | 789 old_node.status = FunctionStatus.DAMAGED; |
| 779 old_node.status_explanation = why_wrong_expectations; | 790 old_node.status_explanation = "Changed parameter number: " + |
| 791 old_node.info.param_num + " and " + new_node.info.param_num; | |
| 780 } | 792 } |
| 781 } | 793 } |
| 782 old_node.unmatched_new_nodes = unmatched_new_nodes_list; | 794 old_node.unmatched_new_nodes = unmatched_new_nodes_list; |
| 783 old_node.textually_unmatched_new_nodes = | 795 old_node.textually_unmatched_new_nodes = |
| 784 textually_unmatched_new_nodes_list; | 796 textually_unmatched_new_nodes_list; |
| 785 } | 797 } |
| 786 | 798 |
| 787 ProcessChildren(old_code_tree, new_code_tree); | 799 ProcessNode(old_code_tree, new_code_tree); |
| 788 | 800 |
| 789 old_code_tree.corresponding_node = new_code_tree; | 801 old_code_tree.corresponding_node = new_code_tree; |
| 790 old_code_tree.textual_corresponding_node = new_code_tree; | 802 old_code_tree.textual_corresponding_node = new_code_tree; |
| 791 | 803 |
| 792 Assert(old_code_tree.status != FunctionStatus.DAMAGED, | 804 Assert(old_code_tree.status != FunctionStatus.DAMAGED, |
| 793 "Script became damaged"); | 805 "Script became damaged"); |
| 794 } | 806 } |
| 795 | 807 |
| 796 function FindLiveSharedInfos(old_code_tree, script) { | 808 function FindLiveSharedInfos(old_code_tree, script) { |
| 797 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script); | 809 var shared_raw_list = %LiveEditFindSharedFunctionInfosForScript(script); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 } | 861 } |
| 850 | 862 |
| 851 function SharedInfoWrapper(raw_array) { | 863 function SharedInfoWrapper(raw_array) { |
| 852 this.function_name = raw_array[0]; | 864 this.function_name = raw_array[0]; |
| 853 this.start_position = raw_array[1]; | 865 this.start_position = raw_array[1]; |
| 854 this.end_position = raw_array[2]; | 866 this.end_position = raw_array[2]; |
| 855 this.info = raw_array[3]; | 867 this.info = raw_array[3]; |
| 856 this.raw_array = raw_array; | 868 this.raw_array = raw_array; |
| 857 } | 869 } |
| 858 | 870 |
| 859 // Changes positions (including all statments) in function. | 871 // Changes positions (including all statments) in function. |
|
aandrey
2013/09/20 12:35:21
statments -> statements
Peter.Rybin
2013/09/20 13:16:51
Done.
| |
| 860 function PatchPositions(old_info_node, diff_array, report_array) { | 872 function PatchPositions(old_info_node, diff_array, report_array) { |
| 861 if (old_info_node.live_shared_function_infos) { | 873 if (old_info_node.live_shared_function_infos) { |
| 862 old_info_node.live_shared_function_infos.forEach(function (info) { | 874 old_info_node.live_shared_function_infos.forEach(function (info) { |
| 863 %LiveEditPatchFunctionPositions(info.raw_array, | 875 %LiveEditPatchFunctionPositions(info.raw_array, |
| 864 diff_array); | 876 diff_array); |
| 865 }); | 877 }); |
| 866 | 878 |
| 867 report_array.push( { name: old_info_node.info.function_name } ); | 879 report_array.push( { name: old_info_node.info.function_name } ); |
| 868 } else { | 880 } else { |
| 869 // TODO(LiveEdit): function is not compiled yet or is already collected. | 881 // TODO(LiveEdit): function is not compiled yet or is already collected. |
| 870 report_array.push( | 882 report_array.push( |
| 871 { name: old_info_node.info.function_name, info_not_found: true } ); | 883 { name: old_info_node.info.function_name, info_not_found: true } ); |
| 872 } | 884 } |
| 873 } | 885 } |
| 874 | 886 |
| 875 // Adds a suffix to script name to mark that it is old version. | 887 // Adds a suffix to script name to mark that it is old version. |
| 876 function CreateNameForOldScript(script) { | 888 function CreateNameForOldScript(script) { |
| 877 // TODO(635): try better than this; support several changes. | 889 // TODO(635): try better than this; support several changes. |
| 878 return script.name + " (old)"; | 890 return script.name + " (old)"; |
| 879 } | 891 } |
| 880 | 892 |
| 881 // Compares a function interface old and new version, whether it | 893 // Compares a function scope heap structure, old and new version, whether it |
| 882 // changed or not. Returns explanation if they differ. | 894 // changed or not. Returns explanation if they differ. |
| 883 function WhyFunctionExpectationsDiffer(function_info1, function_info2) { | 895 function IsFunctionContextLocalsChanged(function_info1, function_info2) { |
| 884 // Check that function has the same number of parameters (there may exist | |
| 885 // an adapter, that won't survive function parameter number change). | |
| 886 if (function_info1.param_num != function_info2.param_num) { | |
| 887 return "Changed parameter number: " + function_info1.param_num + | |
| 888 " and " + function_info2.param_num; | |
| 889 } | |
| 890 var scope_info1 = function_info1.scope_info; | 896 var scope_info1 = function_info1.scope_info; |
| 891 var scope_info2 = function_info2.scope_info; | 897 var scope_info2 = function_info2.scope_info; |
| 892 | 898 |
| 893 var scope_info1_text; | 899 var scope_info1_text; |
| 894 var scope_info2_text; | 900 var scope_info2_text; |
| 895 | 901 |
| 896 if (scope_info1) { | 902 if (scope_info1) { |
| 897 scope_info1_text = scope_info1.toString(); | 903 scope_info1_text = scope_info1.toString(); |
| 898 } else { | 904 } else { |
| 899 scope_info1_text = ""; | 905 scope_info1_text = ""; |
| 900 } | 906 } |
| 901 if (scope_info2) { | 907 if (scope_info2) { |
| 902 scope_info2_text = scope_info2.toString(); | 908 scope_info2_text = scope_info2.toString(); |
| 903 } else { | 909 } else { |
| 904 scope_info2_text = ""; | 910 scope_info2_text = ""; |
| 905 } | 911 } |
| 906 | 912 |
| 907 if (scope_info1_text != scope_info2_text) { | 913 if (scope_info1_text != scope_info2_text) { |
| 908 return "Incompatible variable maps: [" + scope_info1_text + | 914 return "Variable map changed: [" + scope_info1_text + |
| 909 "] and [" + scope_info2_text + "]"; | 915 "] => [" + scope_info2_text + "]"; |
| 910 } | 916 } |
| 911 // No differences. Return undefined. | 917 // No differences. Return undefined. |
| 912 return; | 918 return; |
| 913 } | 919 } |
| 914 | 920 |
| 915 // Minifier forward declaration. | 921 // Minifier forward declaration. |
| 916 var FunctionPatchabilityStatus; | 922 var FunctionPatchabilityStatus; |
| 917 | 923 |
| 918 // For array of wrapped shared function infos checks that none of them | 924 // For array of wrapped shared function infos checks that none of them |
| 919 // have activations on stack (of any thread). Throws a Failure exception | 925 // have activations on stack (of any thread). Throws a Failure exception |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1128 // Function is public. | 1134 // Function is public. |
| 1129 this.RestartFrame = RestartFrame; | 1135 this.RestartFrame = RestartFrame; |
| 1130 | 1136 |
| 1131 // Functions are public for tests. | 1137 // Functions are public for tests. |
| 1132 this.TestApi = { | 1138 this.TestApi = { |
| 1133 PosTranslator: PosTranslator, | 1139 PosTranslator: PosTranslator, |
| 1134 CompareStrings: CompareStrings, | 1140 CompareStrings: CompareStrings, |
| 1135 ApplySingleChunkPatch: ApplySingleChunkPatch | 1141 ApplySingleChunkPatch: ApplySingleChunkPatch |
| 1136 }; | 1142 }; |
| 1137 }; | 1143 }; |
| OLD | NEW |