| 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 whether it's source_changed or | 
| 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_index field using old_index_map. Also | 
| 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 each old function (if it is not damaged) tries to find a corresponding | 
| 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 correspondence not to be found; function with unmodified text | 
| 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 statements) in function. | 
| 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 | 
|---|