Fully compiles source string as a script. Returns Array of FunctionCompileInfo -- a descriptions of all functions of the script. Elements of array are ordered by start positions of functions (from top to bottom) in the source. Fields outer_index and next_sibling_index help to navigate the nesting structure of functions.  All functions get compiled linked to script provided as parameter script. TODO(LiveEdit): consider not using actual scripts as script, because we have to manually erase all links right after compile.
function GatherCompileInfo(source, script) {
    // Get function info, elements are partially sorted (it is a tree of
    // nested functions serialized as parent followed by serialized children.
    var raw_compile_info = %LiveEditGatherCompileInfo(script, source);

    // Sort function infos by start position field.
    var compile_info = new GlobalArray();
    var old_index_map = new GlobalArray();
    for (var i = 0; i < raw_compile_info.length; i++) {
      var info = new FunctionCompileInfo(raw_compile_info[i]);
      // Remove all links to the actual script. Breakpoints system and
      // LiveEdit itself believe that any function in heap that points to a
      // particular script is a regular function.
      // For some functions we will restore this link later.
      %LiveEditFunctionSetScript(info.shared_function_info, UNDEFINED);
      compile_info.push(info);
      old_index_map.push(i);
    }

    for (var i = 0; i < compile_info.length; i++) {
      var k = i;
      for (var j = i + 1; j < compile_info.length; j++) {
        if (compile_info[k].start_position > compile_info[j].start_position) {
          k = j;
        }
      }
      if (k != i) {
        var temp_info = compile_info[k];
        var temp_index = old_index_map[k];
        compile_info[k] = compile_info[i];
        old_index_map[k] = old_index_map[i];
        compile_info[i] = temp_info;
        old_index_map[i] = temp_index;
      }
    }

    // After sorting update outer_index field using old_index_map. Also
    // set next_sibling_index field.
    var current_index = 0;

    // The recursive function, that goes over all children of a particular
    // node (i.e. function info).
    function ResetIndexes(new_parent_index, old_parent_index) {
      var previous_sibling = -1;
      while (current_index < compile_info.length &&
          compile_info[current_index].outer_index == old_parent_index) {
        var saved_index = current_index;
        compile_info[saved_index].outer_index = new_parent_index;
        if (previous_sibling != -1) {
          compile_info[previous_sibling].next_sibling_index = saved_index;
        }
        previous_sibling = saved_index;
        current_index++;
        ResetIndexes(saved_index, old_index_map[saved_index]);
      }
      if (previous_sibling != -1) {
        compile_info[previous_sibling].next_sibling_index = -1;
      }
    }

    ResetIndexes(-1, -1);
    Assert(current_index == compile_info.length);

    return compile_info;
  }