liveedit.cc revision b0fe1620dcb4135ac3ab2d66ff93072373911299
1402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Copyright 2010 the V8 project authors. All rights reserved.
2402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Redistribution and use in source and binary forms, with or without
3402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// modification, are permitted provided that the following conditions are
4402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// met:
5402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//
6402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//     * Redistributions of source code must retain the above copyright
7402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       notice, this list of conditions and the following disclaimer.
8402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//     * Redistributions in binary form must reproduce the above
9402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       copyright notice, this list of conditions and the following
10402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       disclaimer in the documentation and/or other materials provided
11402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       with the distribution.
12402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//     * Neither the name of Google Inc. nor the names of its
13402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       contributors may be used to endorse or promote products derived
14402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       from this software without specific prior written permission.
15402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//
16402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
28402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
29402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "v8.h"
30402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
31402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "liveedit.h"
32f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
33402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "compiler.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "compilation-cache.h"
35402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "debug.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h"
37f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "global-handles.h"
386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "memory.h"
39f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "oprofile-agent.h"
40f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "parser.h"
41f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "scopeinfo.h"
42f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "scopes.h"
43402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
44402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace v8 {
45402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace internal {
46402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
47402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// A simple implementation of dynamic programming algorithm. It solves
526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the problem of finding the difference of 2 arrays. It uses a table of results
536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// of subproblems. Each cell contains a number together with 2-bit flag
546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that helps building the chunk list.
556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass Differencer {
566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit Differencer(Comparator::Input* input)
586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : input_(input), len1_(input->getLength1()), len2_(input->getLength2()) {
596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = NewArray<int>(len1_ * len2_);
606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~Differencer() {
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Initialize() {
666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int array_size = len1_ * len2_;
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < array_size; i++) {
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      buffer_[i] = kEmptyCellValue;
696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Makes sure that result for the full problem is calculated and stored
736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in the table together with flags showing a path through subproblems.
746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void FillTable() {
756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CompareUpToTail(0, 0);
766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SaveResult(Comparator::Output* chunk_writer) {
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ResultWriter writer(chunk_writer);
806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1 = 0;
826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2 = 0;
836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    while (true) {
846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (pos1 < len1_) {
856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (pos2 < len2_) {
866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Direction dir = get_direction(pos1, pos2);
876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          switch (dir) {
886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case EQ:
896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.eq();
906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos1++;
916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos2++;
926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP1:
946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.skip1(1);
956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos1++;
966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP2:
986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP_ANY:
996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.skip2(1);
1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos2++;
1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            default:
1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              UNREACHABLE();
1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          writer.skip1(len1_ - pos1);
1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (len2_ != pos2) {
1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          writer.skip2(len2_ - pos2);
1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        break;
1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    writer.close();
1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comparator::Input* input_;
1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int* buffer_;
1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len1_;
1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len2_;
1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  enum Direction {
1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    EQ = 0,
1276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP1,
1286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP2,
1296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP_ANY,
1306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    MAX_DIRECTION_FLAG_VALUE = SKIP_ANY
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Computes result for a subtask and optionally caches it in the buffer table.
1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All results values are shifted to make space for flags in the lower bits.
1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int CompareUpToTail(int pos1, int pos2) {
1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (pos1 < len1_) {
1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (pos2 < len2_) {
1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int cached_res = get_value4(pos1, pos2);
1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (cached_res == kEmptyCellValue) {
1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Direction dir;
1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          int res;
1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (input_->equals(pos1, pos2)) {
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            res = CompareUpToTail(pos1 + 1, pos2 + 1);
1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            dir = EQ;
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else {
1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int res1 = CompareUpToTail(pos1 + 1, pos2) +
1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                (1 << kDirectionSizeBits);
1496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int res2 = CompareUpToTail(pos1, pos2 + 1) +
1506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                (1 << kDirectionSizeBits);
1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (res1 == res2) {
1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res1;
1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP_ANY;
1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else if (res1 < res2) {
1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res1;
1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP1;
1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res2;
1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP2;
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          set_value4_and_dir(pos1, pos2, res, dir);
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          cached_res = res;
1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return cached_res;
1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return (len1_ - pos1) << kDirectionSizeBits;
1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return (len2_ - pos2) << kDirectionSizeBits;
1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline int& get_cell(int i1, int i2) {
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return buffer_[i1 + i2 * len1_];
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Each cell keeps a value plus direction. Value is multiplied by 4.
1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void set_value4_and_dir(int i1, int i2, int value4, Direction dir) {
1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT((value4 & kDirectionMask) == 0);
1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    get_cell(i1, i2) = value4 | dir;
1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int get_value4(int i1, int i2) {
1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return get_cell(i1, i2) & (kMaxUInt32 ^ kDirectionMask);
1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Direction get_direction(int i1, int i2) {
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return static_cast<Direction>(get_cell(i1, i2) & kDirectionMask);
1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kDirectionSizeBits = 2;
1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kDirectionMask = (1 << kDirectionSizeBits) - 1;
1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEmptyCellValue = -1 << kDirectionSizeBits;
1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This method only holds static assert statement (unfortunately you cannot
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // place one in class scope).
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void StaticAssertHolder() {
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    STATIC_ASSERT(MAX_DIRECTION_FLAG_VALUE < (1 << kDirectionSizeBits));
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  class ResultWriter {
2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   public:
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    explicit ResultWriter(Comparator::Output* chunk_writer)
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        : chunk_writer_(chunk_writer), pos1_(0), pos2_(0),
2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          pos1_begin_(-1), pos2_begin_(-1), has_open_chunk_(false) {
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void eq() {
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FlushChunk();
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos1_++;
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos2_++;
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void skip1(int len1) {
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StartChunk();
2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos1_ += len1;
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void skip2(int len2) {
2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StartChunk();
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos2_ += len2;
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void close() {
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FlushChunk();
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   private:
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Comparator::Output* chunk_writer_;
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1_;
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2_;
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1_begin_;
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2_begin_;
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool has_open_chunk_;
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void StartChunk() {
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!has_open_chunk_) {
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        pos1_begin_ = pos1_;
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        pos2_begin_ = pos2_;
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_open_chunk_ = true;
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void FlushChunk() {
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (has_open_chunk_) {
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        chunk_writer_->AddChunk(pos1_begin_, pos2_begin_,
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                pos1_ - pos1_begin_, pos2_ - pos2_begin_);
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_open_chunk_ = false;
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Comparator::CalculateDifference(Comparator::Input* input,
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Comparator::Output* result_writer) {
2536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Differencer differencer(input);
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.Initialize();
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.FillTable();
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.SaveResult(result_writer);
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CompareSubstrings(Handle<String> s1, int pos1,
2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              Handle<String> s2, int pos2, int len) {
2626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static StringInputBuffer buf1;
2636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static StringInputBuffer buf2;
2646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf1.Reset(*s1);
2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf1.Seek(pos1);
2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf2.Reset(*s2);
2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf2.Seek(pos2);
2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(buf1.has_more() && buf2.has_more());
2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buf1.GetNext() != buf2.GetNext()) {
2716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps raw n-elements line_ends array as a list of n+1 lines. The last line
2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// never has terminating new line character.
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineEndsWrapper {
2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit LineEndsWrapper(Handle<String> string)
2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : ends_array_(CalculateLineEnds(string, false)),
2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        string_len_(string->length()) {
2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int length() {
2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return ends_array_->length() + 1;
2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Returns start for any line including start of the imaginary line after
2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the last line.
2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineStart(int index) {
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == 0) {
2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return 0;
2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetLineEnd(index - 1);
2966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineEnd(int index) {
2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == ends_array_->length()) {
3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // End of the last line is always an end of the whole string.
3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If the string ends with a new line character, the last line is an
3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // empty string after this character.
3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return string_len_;
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetPosAfterNewLine(index);
3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<FixedArray> ends_array_;
3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int string_len_;
3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetPosAfterNewLine(int index) {
3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(ends_array_->get(index))->value() + 1;
3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents 2 strings as 2 arrays of lines.
3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineArrayCompareInput : public Comparator::Input {
3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : s1_(s1), s2_(s2), line_ends1_(line_ends1), line_ends2_(line_ends2) {
3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int getLength1() {
3276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return line_ends1_.length();
3286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int getLength2() {
3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return line_ends2_.length();
3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool equals(int index1, int index2) {
3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start1 = line_ends1_.GetLineStart(index1);
3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start2 = line_ends2_.GetLineStart(index2);
3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end1 = line_ends1_.GetLineEnd(index1);
3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end2 = line_ends2_.GetLineEnd(index2);
3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len1 = line_end1 - line_start1;
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len2 = line_end2 - line_start2;
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (len1 != len2) {
3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return CompareSubstrings(s1_, line_start1, s2_, line_start2, len1);
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s1_;
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s2_;
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Stores compare result in JSArray. Each chunk is stored as 3 array elements:
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (pos1_begin, pos1_end, pos2_end).
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineArrayCompareOutput : public Comparator::Output {
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareOutput(LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : array_(Factory::NewJSArray(10)), current_size_(0),
3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        line_ends1_(line_ends1), line_ends2_(line_ends2) {
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos1 = line_ends1_.GetLineStart(line_pos1);
3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos2 = line_ends2_.GetLineStart(line_pos2);
3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, current_size_, Handle<Object>(Smi::FromInt(char_pos1)));
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, current_size_ + 1,
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Handle<Object>(Smi::FromInt(char_pos1 + char_len1)));
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, current_size_ + 2,
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Handle<Object>(Smi::FromInt(char_pos2 + char_len2)));
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_size_ += 3;
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetResult() {
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array_;
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> array_;
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int current_size_;
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CompareStringsLinewise(Handle<String> s1,
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                 Handle<String> s2) {
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1(s1);
3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2(s2);
3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareOutput output(line_ends1, line_ends2);
3956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comparator::CalculateDifference(&input, &output);
3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return output.GetResult();
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void CompileScriptForTracker(Handle<Script> script) {
4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): support extensions.
4046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  PostponeInterruptsScope postpone;
4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Build AST.
407f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompilationInfo info(script);
408f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  info.MarkAsGlobal();
4093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (ParserApi::Parse(&info)) {
410f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // Compile the code.
411f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    LiveEditFunctionTracker tracker(info.function());
412f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    if (Compiler::MakeCodeForLiveEdit(&info)) {
413f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      ASSERT(!info.code().is_null());
414f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      tracker.RecordRootFunctionInfo(info.code());
415f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    } else {
416f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      Top::StackOverflow();
417f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
4186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
421f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Unwraps JSValue object, returning its field "value"
4236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Handle<Object>(jsValue->value());
4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
427f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps any object into a OpaqueReference, that will hide the object
4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript.
4306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<JSValue> WrapInJSValue(Object* object) {
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> constructor = Top::opaque_reference_function();
4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSValue> result =
4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<JSValue>::cast(Factory::NewJSObject(constructor));
4346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  result->set_value(object);
4356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
438f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Simple helper class that creates more or less typed structures over
4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// JSArray object. This is an adhoc method of passing structures from C++
4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// to JavaScript.
4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename S>
4436ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass JSArrayBasedStruct {
4446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S Create() {
4466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> array = Factory::NewJSArray(S::kSize_);
4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array);
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S cast(Object* object) {
4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    JSArray* array = JSArray::cast(object);
4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> array_handle(array);
4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array_handle);
4536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
4556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetJSArray() {
4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array_;
4586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
459f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
4606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected:
4616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetField(int field_position, Handle<Object> value) {
4626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, field_position, value);
4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSmiValueField(int field_position, int value) {
4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value)));
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* GetField(int field_position) {
4685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return array_->GetElementNoExceptionThrown(field_position);
4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetSmiValueField(int field_position) {
4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* res = GetField(field_position);
4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(res)->value();
4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
474f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> array_;
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents some function compilation details. This structure will be used
4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript. It contains Code object, which is kept wrapped
4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// into a BlindReference for sanitizing reasons.
4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit FunctionInfoWrapper(Handle<JSArray> array)
4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetInitialProperties(Handle<String> name, int start_position,
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            int end_position, int param_num, int parent_index) {
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParamNumOffset_, param_num);
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParentIndexOffset_, parent_index);
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
497756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetFunctionCode(Handle<Code> function_code,
498756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Handle<Object> code_scope_info) {
499756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<JSValue> code_wrapper = WrapInJSValue(*function_code);
500756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeOffset_, code_wrapper);
501756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
502756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<JSValue> scope_wrapper = WrapInJSValue(*code_scope_info);
503756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeScopeInfoOffset_, scope_wrapper);
5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
505756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetOuterScopeInfo(Handle<Object> scope_info_array) {
506756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kOuterScopeInfoOffset_, scope_info_array);
5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) {
5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> info_holder = WrapInJSValue(*info);
5106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedFunctionInfoOffset_, info_holder);
5116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetParentIndex() {
5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kParentIndexOffset_);
5146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> GetFunctionCode() {
5166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        JSValue::cast(this->GetField(kCodeOffset_))));
5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<Code>::cast(raw_result);
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
520756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Handle<Object> GetCodeScopeInfo() {
521756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
522756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        JSValue::cast(this->GetField(kCodeScopeInfoOffset_))));
523756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return raw_result;
524756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
5256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetStartPosition() {
5266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kStartPositionOffset_);
5276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetEndPosition() {
5296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kEndPositionOffset_);
5306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kParamNumOffset_ = 3;
5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kCodeOffset_ = 4;
538756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kCodeScopeInfoOffset_ = 5;
539756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kOuterScopeInfoOffset_ = 6;
540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kParentIndexOffset_ = 7;
541756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSharedFunctionInfoOffset_ = 8;
542756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSize_ = 9;
5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<FunctionInfoWrapper>;
5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps SharedFunctionInfo along with some of its fields for passing it
5496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// back to JavaScript. SharedFunctionInfo object itself is additionally
5506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// wrapped into BlindReference for sanitizing reasons.
5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static bool IsInstance(Handle<JSArray> array) {
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array->length() == Smi::FromInt(kSize_) &&
5555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        array->GetElementNoExceptionThrown(kSharedInfoOffset_)->IsJSValue();
5566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit SharedInfoWrapper(Handle<JSArray> array)
5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<SharedInfoWrapper>(array) {
5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetProperties(Handle<String> name, int start_position, int end_position,
5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     Handle<SharedFunctionInfo> info) {
5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> info_holder = WrapInJSValue(*info);
5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedInfoOffset_, info_holder);
5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> GetInfo() {
5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* element = this->GetField(kSharedInfoOffset_);
5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> value_wrapper(JSValue::cast(element));
5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<SharedFunctionInfo>::cast(raw_result);
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSharedInfoOffset_ = 3;
5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSize_ = 4;
5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<SharedInfoWrapper>;
5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
588f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuclass FunctionInfoListener {
590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu public:
5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener() {
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = -1;
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_ = 0;
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    result_ = Factory::NewJSArray(10);
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionStarted(FunctionLiteral* fun) {
5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FunctionInfoWrapper info = FunctionInfoWrapper::Create();
6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info.SetInitialProperties(fun->name(), fun->start_position(),
6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              fun->end_position(), fun->num_parameters(),
6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              current_parent_index_);
6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = len_;
6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(result_, len_, info.GetJSArray());
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_++;
606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionDone() {
6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = info.GetParentIndex();
614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
615402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
61659151504615d929945dc59db37bf1166937748c6Steve Block  // Saves only function code, because for a script function we
61759151504615d929945dc59db37bf1166937748c6Steve Block  // may never create a SharedFunctionInfo object.
61859151504615d929945dc59db37bf1166937748c6Steve Block  void FunctionCode(Handle<Code> function_code) {
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
62259151504615d929945dc59db37bf1166937748c6Steve Block    info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value()));
62359151504615d929945dc59db37bf1166937748c6Steve Block  }
62459151504615d929945dc59db37bf1166937748c6Steve Block
62559151504615d929945dc59db37bf1166937748c6Steve Block  // Saves full information about a function: its code, its scope info
62659151504615d929945dc59db37bf1166937748c6Steve Block  // and a SharedFunctionInfo object.
62759151504615d929945dc59db37bf1166937748c6Steve Block  void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) {
62859151504615d929945dc59db37bf1166937748c6Steve Block    if (!shared->IsSharedFunctionInfo()) {
62959151504615d929945dc59db37bf1166937748c6Steve Block      return;
63059151504615d929945dc59db37bf1166937748c6Steve Block    }
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
63459151504615d929945dc59db37bf1166937748c6Steve Block    info.SetFunctionCode(Handle<Code>(shared->code()),
63559151504615d929945dc59db37bf1166937748c6Steve Block        Handle<Object>(shared->scope_info()));
63659151504615d929945dc59db37bf1166937748c6Steve Block    info.SetSharedFunctionInfo(shared);
63759151504615d929945dc59db37bf1166937748c6Steve Block
63859151504615d929945dc59db37bf1166937748c6Steve Block    Handle<Object> scope_info_list(SerializeFunctionScope(scope));
63959151504615d929945dc59db37bf1166937748c6Steve Block    info.SetOuterScopeInfo(scope_info_list);
64059151504615d929945dc59db37bf1166937748c6Steve Block  }
64159151504615d929945dc59db37bf1166937748c6Steve Block
64259151504615d929945dc59db37bf1166937748c6Steve Block  Handle<JSArray> GetResult() { return result_; }
64359151504615d929945dc59db37bf1166937748c6Steve Block
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* SerializeFunctionScope(Scope* scope) {
6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope handle_scope;
6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> scope_info_list = Factory::NewJSArray(10);
6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int scope_info_length = 0;
6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Saves some description of scope. It stores name and indexes of
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // variables in the whole scope chain. Null-named slots delimit
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // scopes of this chain.
6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Scope* outer_scope = scope->outer_scope();
6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (outer_scope == NULL) {
6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return Heap::undefined_value();
6576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    do {
6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ZoneList<Variable*> list(10);
6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      outer_scope->CollectUsedVariables(&list);
6616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int j = 0;
6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 0; i < list.length(); i++) {
6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Variable* var1 = list[i];
6640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        Slot* slot = var1->AsSlot();
6656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (slot != NULL && slot->type() == Slot::CONTEXT) {
6666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (j != i) {
6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            list[j] = var1;
6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          j++;
6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Sort it.
6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int k = 1; k < j; k++) {
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int l = k;
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        for (int m = k + 1; m < j; m++) {
6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          if (list[l]->AsSlot()->index() > list[m]->AsSlot()->index()) {
6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            l = m;
6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        list[k] = list[l];
6826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 0; i < j; i++) {
6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SetElement(scope_info_list, scope_info_length, list[i]->name());
6856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
6866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SetElement(scope_info_list, scope_info_length,
6870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                   Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())));
6886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
6896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      SetElement(scope_info_list, scope_info_length,
6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 Handle<Object>(Heap::null_value()));
6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      scope_info_length++;
6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      outer_scope = outer_scope->outer_scope();
6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } while (outer_scope != NULL);
6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return *scope_info_list;
698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
7016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len_;
7026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int current_parent_index_;
703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu};
704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
705f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic FunctionInfoListener* active_function_info_listener = NULL;
707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
7086ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockJSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> source) {
7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompilationZoneScope zone_scope(DELETE_ON_EXIT);
7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener listener;
7136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> original_source = Handle<Object>(script->source());
7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*source);
7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  active_function_info_listener = &listener;
7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileScriptForTracker(script);
7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  active_function_info_listener = NULL;
7186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*original_source);
7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *(listener.GetResult());
7216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(array->length())->value();
7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info(
7295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        SharedFunctionInfo::cast(array->GetElementNoExceptionThrown(i)));
7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<String> name_handle(String::cast(info->name()));
7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info_wrapper.SetProperties(name_handle, info->start_position(),
7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               info->end_position(), info);
73480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetElement(array, i, info_wrapper.GetJSArray());
7356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
7376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor that collects all references to a particular code object,
7406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// including "CODE_TARGET" references in other code objects.
7416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It works in context of ZoneScope.
7426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ReferenceCollectorVisitor : public ObjectVisitor {
7436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit ReferenceCollectorVisitor(Code* original)
745791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    : original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) {
7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitPointers(Object** start, Object** end) {
7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (Object** p = start; p < end; p++) {
7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (*p == original_) {
7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        rvalues_.Add(p);
7526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
7536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
756791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeEntry(Address entry) {
757791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (Code::GetObjectFromEntryAddress(entry) == original_) {
758791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      code_entries_.Add(entry);
759791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
760791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
761791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
762791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeTarget(RelocInfo* rinfo) {
7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
7656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      reloc_infos_.Add(*rinfo);
7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitDebugTarget(RelocInfo* rinfo) {
7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitCodeTarget(rinfo);
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Post-visiting method that iterates over all collected references and
7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // modifies them.
7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Replace(Code* substitution) {
7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < rvalues_.length(); i++) {
7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      *(rvalues_[i]) = substitution;
7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
779791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Address substitution_entry = substitution->instruction_start();
7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < reloc_infos_.length(); i++) {
781791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      reloc_infos_[i].set_target_address(substitution_entry);
782791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
783791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    for (int i = 0; i < code_entries_.length(); i++) {
784791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Address entry = code_entries_[i];
785791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Memory::Address_at(entry) = substitution_entry;
7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Code* original_;
7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<Object**> rvalues_;
7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<RelocInfo> reloc_infos_;
793791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ZoneList<Address> code_entries_;
7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Finds all references to original and replaces them with substitution.
7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReplaceCodeObject(Code* original, Code* substitution) {
7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!Heap::InNewSpace(substitution));
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  AssertNoAllocation no_allocations_please;
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // A zone scope for ReferenceCollectorVisitor.
8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneScope scope(DELETE_ON_EXIT);
8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ReferenceCollectorVisitor visitor(original);
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Iterate over all roots. Stack frames may have pointer into original code,
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // so temporary replace the pointers with offset numbers
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in prologue/epilogue.
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Heap::IterateStrongRoots(&visitor, VISIT_ALL);
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Now iterate over all pointers of all objects, including code_target
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // implicit pointers.
8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HeapIterator iterator;
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    obj->Iterate(&visitor);
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  visitor.Replace(substitution);
8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check whether the code is natural function code (not a lazy-compile stub
8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// code).
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsJSFunctionCode(Code* code) {
8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return code->kind() == Code::FUNCTION;
8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Returns true if an instance of candidate were inlined into function's code.
834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) {
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_gc;
836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* data =
840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      DeoptimizationInputData::cast(function->code()->deoptimization_data());
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (data == Heap::empty_fixed_array()) return false;
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  FixedArray* literals = data->LiteralArray();
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int inlined_count = data->InlinedFunctionCount()->value();
847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < inlined_count; ++i) {
848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* inlined = JSFunction::cast(literals->get(i));
849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (inlined->shared() == candidate) return true;
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass DependentFunctionsDeoptimizingVisitor : public OptimizedFunctionVisitor {
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit DependentFunctionsDeoptimizingVisitor(
859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* function_info)
860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : function_info_(function_info) {}
861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void EnterContext(Context* context) {
863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void VisitFunction(JSFunction* function) {
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->shared() == function_info_ ||
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        IsInlined(function, function_info_)) {
868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Deoptimizer::DeoptimizeFunction(function);
869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void LeaveContext(Context* context) {
873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedFunctionInfo* function_info_;
877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) {
881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DependentFunctionsDeoptimizingVisitor visitor(function_info);
884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Deoptimizer::VisitAllOptimizedFunctions(&visitor);
885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8885913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::ReplaceFunctionCode(
8895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Handle<JSArray> new_compile_info_array,
8905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Handle<JSArray> shared_info_array) {
8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Top::ThrowIllegalOperation();
8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(shared_info->code())) {
9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ReplaceCodeObject(shared_info->code(),
9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      *(compile_info_wrapper.GetFunctionCode()));
905756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> code_scope_info =  compile_info_wrapper.GetCodeScopeInfo();
906756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (code_scope_info->IsFixedArray()) {
907756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info));
908756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (shared_info->debug_info()->IsDebugInfo()) {
9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> new_original_code =
9146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Factory::CopyCode(compile_info_wrapper.GetFunctionCode());
9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    debug_info->set_original_code(*new_original_code);
9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_start_position(compile_info_wrapper.GetStartPosition());
9196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
9206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_construct_stub(
9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Builtins::builtin(Builtins::JSConstructStubGeneric));
9236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizeDependentFunctions(*shared_info);
925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompilationCache::Remove(shared_info);
926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return Heap::undefined_value();
928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochMaybeObject* LiveEdit::FunctionSourceUpdated(
932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSArray> shared_info_array) {
933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HandleScope scope;
934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return Top::ThrowIllegalOperation();
937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedInfoWrapper shared_info_wrapper(shared_info_array);
940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizeDependentFunctions(*shared_info);
943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompilationCache::Remove(shared_info);
944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Heap::undefined_value();
9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9496ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
9506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 Handle<Object> script_handle) {
9516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info =
9526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
9536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_script(*script_handle);
954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompilationCache::Remove(shared_info);
9566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// For a script text change (defined as position_change_array), translates
9606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// position in unchanged text to position in changed text.
9616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Text change is a set of non-overlapping regions in text, that have changed
9626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// their contents and length. It is specified as array of groups of 3 numbers:
9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (change_begin, change_end, change_end_new_position).
9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Each group describes a change in text; groups are sorted by change_begin.
9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Only position in text beyond any changes may be successfully translated.
9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// If a positions is inside some region that changed, result is currently
9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// undefined.
9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic int TranslatePosition(int original_position,
9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             Handle<JSArray> position_change_array) {
9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int position_diff = 0;
9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(position_change_array->length())->value();
9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): binary search may be used here
9736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i += 3) {
9745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* element = position_change_array->GetElementNoExceptionThrown(i);
9755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_start = Smi::cast(element)->value();
9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (original_position < chunk_start) {
9776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
9786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    element = position_change_array->GetElementNoExceptionThrown(i + 1);
9805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_end = Smi::cast(element)->value();
9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Position mustn't be inside a chunk.
9826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(original_position >= chunk_end);
9835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    element = position_change_array->GetElementNoExceptionThrown(i + 2);
9845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_changed_end = Smi::cast(element)->value();
9856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    position_diff = chunk_changed_end - chunk_end;
9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return original_position + position_diff;
9896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Auto-growing buffer for writing relocation info code section. This buffer
9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// is a simplified version of buffer from Assembler. Unlike Assembler, this
9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// class is platform-independent and it works without dealing with instructions.
9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// As specified by RelocInfo format, the buffer is filled in reversed order:
9966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from upper to lower addresses.
9976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It uses NewArray/DeleteArray for memory management.
9986ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass RelocInfoBuffer {
9996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
10006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer(int buffer_initial_capicity, byte* pc) {
10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = buffer_initial_capicity + kBufferGap;
10026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = NewArray<byte>(buffer_size_);
10036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc);
10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~RelocInfoBuffer() {
10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // As specified by RelocInfo format, the buffer is filled in reversed order:
10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // from upper to lower addresses.
10126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Write(const RelocInfo* rinfo) {
10136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) {
10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Grow();
10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Write(rinfo);
10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> GetResult() {
10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Return the bytes from pos up to end of buffer.
10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int result_size =
10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer_.pos());
10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Vector<byte>(reloc_info_writer_.pos(), result_size);
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Grow() {
10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Compute new buffer size.
10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int new_buffer_size;
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_size_ < 2 * KB) {
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 4 * KB;
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 2 * buffer_size_;
10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Some internal data structures overflow for very large buffers,
10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // they must ensure that kMaximalBufferSize is not too large.
10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (new_buffer_size > kMaximalBufferSize) {
10386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer");
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Setup new buffer.
10426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    byte* new_buffer = NewArray<byte>(new_buffer_size);
10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Copy the data.
10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int curently_used_size =
10466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>(buffer_ + buffer_size_ - reloc_info_writer_.pos());
10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memmove(new_buffer + new_buffer_size - curently_used_size,
10486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            reloc_info_writer_.pos(), curently_used_size);
10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(
10516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        new_buffer + new_buffer_size - curently_used_size,
10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        reloc_info_writer_.last_pc());
10536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
10556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = new_buffer;
10566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = new_buffer_size;
10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoWriter reloc_info_writer_;
10606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  byte* buffer_;
10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int buffer_size_;
10626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kBufferGap = RelocInfoWriter::kMaxSize;
10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kMaximalBufferSize = 512*MB;
10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Patch positions in code (changes relocation info section) and possibly
10686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// returns new instance of code.
10696ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Code> PatchPositionsInCode(Handle<Code> code,
10706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> position_change_array) {
10716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer buffer_writer(code->relocation_size(),
10736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                code->instruction_start());
10746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    AssertNoAllocation no_allocations_please;
10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (RelocIterator it(*code); !it.done(); it.next()) {
10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      RelocInfo* rinfo = it.rinfo();
10796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (RelocInfo::IsPosition(rinfo->rmode())) {
10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int position = static_cast<int>(rinfo->data());
10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int new_position = TranslatePosition(position,
10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (position != new_position) {
10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position);
10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          buffer_writer.Write(&info_copy);
10866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          continue;
10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      buffer_writer.Write(it.rinfo());
10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> buffer = buffer_writer.GetResult();
10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (buffer.length() == code->relocation_size()) {
10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Simply patch relocation area of code.
10976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memcpy(code->relocation_start(), buffer.start(), buffer.length());
10986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return code;
10996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Relocation info section now has different size. We cannot simply
11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // rewrite it inside code object. Instead we have to create a new
11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // code object.
11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> result(Factory::CopyCode(code, buffer));
11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11095913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::PatchFunctionPositions(
11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
11136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Top::ThrowIllegalOperation();
11146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int old_function_start = info->start_position();
11206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int new_function_start = TranslatePosition(old_function_start,
11216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_start_position(new_function_start);
11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_end_position(TranslatePosition(info->end_position(),
11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           position_change_array));
11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_function_token_position(
11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      TranslatePosition(info->function_token_position(),
11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      position_change_array));
11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(info->code())) {
11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Patch relocation info section of the code.
11326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()),
11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                     position_change_array);
11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (*patched_code != info->code()) {
11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Replace all references to the code across the heap. In particular,
11366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // some stubs may refer to this code and this code may be being executed
11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // on stack (it is safe to substitute the code object on stack, because
11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // we only change the structure of rinfo and leave instructions
11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // untouched).
11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReplaceCodeObject(info->code(), *patched_code);
11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Heap::undefined_value();
11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Script> CreateScriptCopy(Handle<Script> original) {
11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> original_source(String::cast(original->source()));
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Script> copy = Factory::NewScript(original_source);
11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_name(original->name());
11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_line_offset(original->line_offset());
11556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_column_offset(original->column_offset());
11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_data(original->data());
11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_type(original->type());
11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_context_data(original->context_data());
11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_compilation_type(original->compilation_type());
11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_shared(original->eval_from_shared());
11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_instructions_offset(
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      original->eval_from_instructions_offset());
11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return copy;
11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11686ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LiveEdit::ChangeScriptSource(Handle<Script> original_script,
11696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> new_source,
11706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<Object> old_script_name) {
11716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> old_script_object;
11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (old_script_name->IsString()) {
11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Script> old_script = CreateScriptCopy(original_script);
11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script->set_name(String::cast(*old_script_name));
11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script_object = old_script;
11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING);
11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script_object = Handle<Object>(Heap::null_value());
11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  original_script->set_source(*new_source);
11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Drop line ends so that they will be recalculated.
11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  original_script->set_line_ends(Heap::undefined_value());
11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *old_script_object;
11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::ReplaceRefToNestedFunction(
11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> parent_function_wrapper,
11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> orig_function_wrapper,
11946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> subst_function_wrapper) {
11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> parent_shared =
11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(parent_function_wrapper));
11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> orig_shared =
11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(orig_function_wrapper));
12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> subst_shared =
12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(subst_function_wrapper));
12026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
12046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
12056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (it.rinfo()->target_object() == *orig_shared) {
12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        it.rinfo()->set_target_object(*subst_shared);
12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check an activation against list of functions. If there is a function
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that matches, its status in result array is changed to status argument value.
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CheckActivation(Handle<JSArray> shared_info_array,
1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Handle<JSArray> result,
1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            StackFrame* frame,
12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FunctionPatchabilityStatus status) {
1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!frame->is_java_script()) return false;
1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<JSFunction> function(
1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JSFunction::cast(JavaScriptFrame::cast(frame)->function()));
1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
12265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSValue* wrapper =
12275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i));
12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> shared(
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SharedFunctionInfo::cast(wrapper->value()));
12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->shared() == *shared || IsInlined(*function, *shared)) {
12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      SetElement(result, i, Handle<Smi>(Smi::FromInt(status)));
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Iterates over handler chain and removes all elements that are inside
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames being dropped.
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool FixTryCatchHandler(StackFrame* top_frame,
12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               StackFrame* bottom_frame) {
12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* pointer_address =
12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address));
12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < top_frame->sp()) {
12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* above_frame_address = pointer_address;
12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < bottom_frame->fp()) {
12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool change = *above_frame_address != *pointer_address;
12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  *above_frame_address = *pointer_address;
12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return change;
12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Removes specified range of frames from stack. There may be 1 or more
12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames in range. Anyway the bottom frame is restarted rather than dropped,
12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// and therefore has to be a JavaScript frame.
12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Returns error message or NULL.
12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropFrames(Vector<StackFrame*> frames,
12656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              int top_frame_index,
12668defd9ff6930b4e24729971a61cf7469daf119beSteve Block                              int bottom_js_frame_index,
1267bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Debug::FrameDropMode* mode,
1268bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Object*** restarter_frame_function_pointer) {
1269756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (!Debug::kFrameDropperSupported) {
12708defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return "Stack manipulations are not supported in this architecture.";
12718defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
12728defd9ff6930b4e24729971a61cf7469daf119beSteve Block
12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* pre_top_frame = frames[top_frame_index - 1];
12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* top_frame = frames[top_frame_index];
12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* bottom_js_frame = frames[bottom_js_frame_index];
12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(bottom_js_frame->is_java_script());
12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the nature of the top frame.
12806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (pre_top_frame->code()->is_inline_cache_stub() &&
12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pre_top_frame->code()->ic_state() == DEBUG_BREAK) {
12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop inline cache calls.
12838defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
12848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  } else if (pre_top_frame->code() == Debug::debug_break_slot()) {
12858defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // OK, we can drop debug break slot.
12868defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (pre_top_frame->code() ==
12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Builtins::builtin(Builtins::FrameDropper_LiveEdit)) {
12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop our own code.
12908defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (pre_top_frame->code()->kind() == Code::STUB &&
12926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pre_top_frame->code()->major_key()) {
12938defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Entry from our unit tests, it's fine, we support this case.
12948defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
12956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Unknown structure of stack above changing function";
12976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_top = top_frame->sp();
13006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_bottom = bottom_js_frame->fp()
13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      - Debug::kFrameDropperFrameSize * kPointerSize  // Size of the new frame.
13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      + kPointerSize;  // Bigger address end is exclusive.
13036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (unused_stack_top > unused_stack_bottom) {
13056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Not enough space for frame dropper frame";
13066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Committing now. After this point we should return only NULL value.
13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FixTryCatchHandler(pre_top_frame, bottom_js_frame);
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Make sure FixTryCatchHandler is idempotent.
13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> code(Builtins::builtin(Builtins::FrameDropper_LiveEdit));
13156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  top_frame->set_pc(code->entry());
13166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  pre_top_frame->SetCallerFp(bottom_js_frame->fp());
13176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1318bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  *restarter_frame_function_pointer =
1319bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      Debug::SetUpFrameDropperFrame(bottom_js_frame, code);
1320bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1321bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((**restarter_frame_function_pointer)->IsJSFunction());
13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (Address a = unused_stack_top;
13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a < unused_stack_bottom;
13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a += kPointerSize) {
13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Memory::Object_at(a) = Smi::FromInt(0);
13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13336ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDropableFrame(StackFrame* frame) {
13346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return !frame->is_exit();
13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Fills result array with statuses of functions. Modifies the stack
13386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// removing all listed function if possible and if do_drop is true.
13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropActivationsInActiveThread(
13406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
13416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneScope scope(DELETE_ON_EXIT);
13436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<StackFrame*> frames = CreateStackMap();
13446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(shared_info_array->length())->value();
13466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int top_frame_index = -1;
13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_index = 0;
13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frame->id() == Debug::break_frame_id()) {
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      top_frame_index = frame_index;
13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
13546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We are still above break_frame. It is not a target frame,
13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // it is a problem.
13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return "Debugger mark-up on stack is not found";
13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_frame_index == -1) {
13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We haven't found break frame, but no function is blocking us anyway.
13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool target_frame_found = false;
13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int bottom_js_frame_index = top_frame_index;
13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool c_code_found = false;
13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!IsDropableFrame(frame)) {
13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      c_code_found = true;
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      target_frame_found = true;
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      bottom_js_frame_index = frame_index;
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (c_code_found) {
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // There is a C frames on stack. Check that there are no target frames
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // below them.
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (; frame_index < frames.length(); frame_index++) {
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StackFrame* frame = frames[frame_index];
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (frame->is_java_script()) {
13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (CheckActivation(shared_info_array, result, frame,
13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // Cannot drop frame under C frames.
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          return NULL;
13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!do_drop) {
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We are in check-only mode.
14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!target_frame_found) {
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Nothing to drop.
14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14108defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED;
1411bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object** restarter_frame_function_pointer = NULL;
14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message = DropFrames(frames, top_frame_index,
1413bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         bottom_js_frame_index, &drop_mode,
1414bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         &restarter_frame_function_pointer);
14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return error_message;
14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Adjust break_frame after some frames has been dropped.
14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame::Id new_id = StackFrame::NO_ID;
14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_id = frames[i]->id();
14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1428bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Debug::FramesHaveBeenDropped(new_id, drop_mode,
1429bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                               restarter_frame_function_pointer);
14306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Replace "blocked on active" with "replaced on active" status.
14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i++) {
14336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (result->GetElement(i) ==
14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
143580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Handle<Object> replaced(
143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
143780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      SetElement(result, i, replaced);
14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass InactiveThreadActivationsChecker : public ThreadVisitor {
14456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   Handle<JSArray> result)
14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : shared_info_array_(shared_info_array), result_(result),
14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_blocked_functions_(false) {
14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitThread(ThreadLocalTop* top) {
14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      has_blocked_functions_ |= CheckActivation(
14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          shared_info_array_, result_, it.frame(),
14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool HasBlockedFunctions() {
14596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return has_blocked_functions_;
14606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
14636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> shared_info_array_;
14646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool has_blocked_functions_;
14666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
14676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CheckAndDropActivations(
14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, bool do_drop) {
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result = Factory::NewJSArray(len);
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fill the default values.
14766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(result, i,
14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First check inactive threads. Fail if some functions are blocked there.
14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                            result);
14857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ThreadManager::IterateArchivedThreads(&inactive_threads_checker);
14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (inactive_threads_checker.HasBlockedFunctions()) {
14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Try to drop activations from the current stack.
14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message =
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      DropActivationsInActiveThread(shared_info_array, result, do_drop);
14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Add error message as an array extra element.
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Vector<const char> vector_message(error_message, StrLength(error_message));
14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<String> str = Factory::NewStringFromAscii(vector_message);
14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(result, len, str);
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
1504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (active_function_info_listener != NULL) {
1505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    active_function_info_listener->FunctionStarted(fun);
1506402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::~LiveEditFunctionTracker() {
1511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (active_function_info_listener != NULL) {
1512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    active_function_info_listener->FunctionDone();
1513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
15156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
1519402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (active_function_info_listener != NULL) {
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    active_function_info_listener->FunctionInfo(info, lit->scope());
1521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1522402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  active_function_info_listener->FunctionCode(code);
1527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescubool LiveEditFunctionTracker::IsActive() {
1531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return active_function_info_listener != NULL;
1532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else  // ENABLE_DEBUGGER_SUPPORT
15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// This ifdef-else-endif section provides working or stub implementation of
15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// LiveEditFunctionTracker.
15396ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15436ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::~LiveEditFunctionTracker() {
15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool LiveEditFunctionTracker::IsActive() {
15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // ENABLE_DEBUGGER_SUPPORT
15616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} }  // namespace v8::internal
1565