liveedit.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
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"
38f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "parser.h"
39f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "scopeinfo.h"
40f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "scopes.h"
4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "v8memory.h"
42402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
43402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace v8 {
44402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace internal {
45402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
46402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid SetElementNonStrict(Handle<JSObject> object,
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         uint32_t index,
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         Handle<Object> value) {
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Ignore return value from SetElement. It can only be a failure if there
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // are element setters causing exceptions and the debugger context has none
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // of these.
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> no_failure;
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  no_failure = SetElement(object, index, value, kNonStrictMode);
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!no_failure.is_null());
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  USE(no_failure);
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// A simple implementation of dynamic programming algorithm. It solves
636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the problem of finding the difference of 2 arrays. It uses a table of results
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// of subproblems. Each cell contains a number together with 2-bit flag
656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that helps building the chunk list.
666ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass Differencer {
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit Differencer(Comparator::Input* input)
696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : input_(input), len1_(input->getLength1()), len2_(input->getLength2()) {
706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = NewArray<int>(len1_ * len2_);
716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~Differencer() {
736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Initialize() {
776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int array_size = len1_ * len2_;
786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < array_size; i++) {
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      buffer_[i] = kEmptyCellValue;
806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Makes sure that result for the full problem is calculated and stored
846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in the table together with flags showing a path through subproblems.
856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void FillTable() {
866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CompareUpToTail(0, 0);
876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SaveResult(Comparator::Output* chunk_writer) {
906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ResultWriter writer(chunk_writer);
916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1 = 0;
936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2 = 0;
946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    while (true) {
956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (pos1 < len1_) {
966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (pos2 < len2_) {
976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Direction dir = get_direction(pos1, pos2);
986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          switch (dir) {
996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case EQ:
1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.eq();
1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos1++;
1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos2++;
1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP1:
1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.skip1(1);
1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos1++;
1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP2:
1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP_ANY:
1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.skip2(1);
1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos2++;
1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            default:
1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              UNREACHABLE();
1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          writer.skip1(len1_ - pos1);
1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (len2_ != pos2) {
1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          writer.skip2(len2_ - pos2);
1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        break;
1256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
1276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    writer.close();
1286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comparator::Input* input_;
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int* buffer_;
1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len1_;
1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len2_;
1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  enum Direction {
1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    EQ = 0,
1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP1,
1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP2,
1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP_ANY,
1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    MAX_DIRECTION_FLAG_VALUE = SKIP_ANY
1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Computes result for a subtask and optionally caches it in the buffer table.
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All results values are shifted to make space for flags in the lower bits.
1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int CompareUpToTail(int pos1, int pos2) {
1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (pos1 < len1_) {
1496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (pos2 < len2_) {
1506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int cached_res = get_value4(pos1, pos2);
1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (cached_res == kEmptyCellValue) {
1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Direction dir;
1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          int res;
1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (input_->equals(pos1, pos2)) {
1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            res = CompareUpToTail(pos1 + 1, pos2 + 1);
1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            dir = EQ;
1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else {
1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int res1 = CompareUpToTail(pos1 + 1, pos2) +
1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                (1 << kDirectionSizeBits);
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int res2 = CompareUpToTail(pos1, pos2 + 1) +
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                (1 << kDirectionSizeBits);
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (res1 == res2) {
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res1;
1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP_ANY;
1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else if (res1 < res2) {
1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res1;
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP1;
1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res2;
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP2;
1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          set_value4_and_dir(pos1, pos2, res, dir);
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          cached_res = res;
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return cached_res;
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return (len1_ - pos1) << kDirectionSizeBits;
1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return (len2_ - pos2) << kDirectionSizeBits;
1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline int& get_cell(int i1, int i2) {
1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return buffer_[i1 + i2 * len1_];
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Each cell keeps a value plus direction. Value is multiplied by 4.
1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void set_value4_and_dir(int i1, int i2, int value4, Direction dir) {
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT((value4 & kDirectionMask) == 0);
1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    get_cell(i1, i2) = value4 | dir;
1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int get_value4(int i1, int i2) {
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return get_cell(i1, i2) & (kMaxUInt32 ^ kDirectionMask);
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Direction get_direction(int i1, int i2) {
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return static_cast<Direction>(get_cell(i1, i2) & kDirectionMask);
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kDirectionSizeBits = 2;
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kDirectionMask = (1 << kDirectionSizeBits) - 1;
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEmptyCellValue = -1 << kDirectionSizeBits;
2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This method only holds static assert statement (unfortunately you cannot
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // place one in class scope).
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void StaticAssertHolder() {
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    STATIC_ASSERT(MAX_DIRECTION_FLAG_VALUE < (1 << kDirectionSizeBits));
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  class ResultWriter {
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   public:
2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    explicit ResultWriter(Comparator::Output* chunk_writer)
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        : chunk_writer_(chunk_writer), pos1_(0), pos2_(0),
2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          pos1_begin_(-1), pos2_begin_(-1), has_open_chunk_(false) {
2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void eq() {
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FlushChunk();
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos1_++;
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos2_++;
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void skip1(int len1) {
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StartChunk();
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos1_ += len1;
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void skip2(int len2) {
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StartChunk();
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos2_ += len2;
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void close() {
2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FlushChunk();
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   private:
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Comparator::Output* chunk_writer_;
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1_;
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2_;
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1_begin_;
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2_begin_;
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool has_open_chunk_;
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void StartChunk() {
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!has_open_chunk_) {
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        pos1_begin_ = pos1_;
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        pos2_begin_ = pos2_;
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_open_chunk_ = true;
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void FlushChunk() {
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (has_open_chunk_) {
2536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        chunk_writer_->AddChunk(pos1_begin_, pos2_begin_,
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                pos1_ - pos1_begin_, pos2_ - pos2_begin_);
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_open_chunk_ = false;
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Comparator::CalculateDifference(Comparator::Input* input,
2636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Comparator::Output* result_writer) {
2646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Differencer differencer(input);
2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.Initialize();
2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.FillTable();
2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.SaveResult(result_writer);
2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
27144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic bool CompareSubstrings(Isolate* isolate, Handle<String> s1, int pos1,
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              Handle<String> s2, int pos2, int len) {
27344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  StringInputBuffer& buf1 = *isolate->liveedit_compare_substrings_buf1();
27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  StringInputBuffer& buf2 = *isolate->liveedit_compare_substrings_buf2();
2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf1.Reset(*s1);
2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf1.Seek(pos1);
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf2.Reset(*s2);
2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf2.Seek(pos2);
2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(buf1.has_more() && buf2.has_more());
2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buf1.GetNext() != buf2.GetNext()) {
2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
289b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A helper class that writes chunk numbers into JSArray.
290b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end).
291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass CompareOutputArrayWriter {
292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
293b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompareOutputArrayWriter()
29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : array_(FACTORY->NewJSArray(10)), current_size_(0) {}
295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
296b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<JSArray> GetResult() {
297b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return array_;
298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) {
30144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       current_size_,
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       Handle<Object>(Smi::FromInt(char_pos1)));
30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        current_size_ + 1,
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Handle<Object>(Smi::FromInt(char_pos1 + char_len1)));
30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        current_size_ + 2,
30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Handle<Object>(Smi::FromInt(char_pos2 + char_len2)));
310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    current_size_ += 3;
311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
312b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<JSArray> array_;
315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int current_size_;
316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Represents 2 strings as 2 arrays of tokens.
320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// TODO(LiveEdit): Currently it's actually an array of charactres.
321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch//     Make array of tokens instead.
322b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass TokensCompareInput : public Comparator::Input {
323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokensCompareInput(Handle<String> s1, int offset1, int len1,
325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       Handle<String> s2, int offset2, int len2)
326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : s1_(s1), offset1_(offset1), len1_(len1),
327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        s2_(s2), offset2_(offset2), len2_(len2) {
328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
329b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual int getLength1() {
330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return len1_;
331b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
332b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual int getLength2() {
333b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return len2_;
334b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
335b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bool equals(int index1, int index2) {
336b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return s1_->Get(offset1_ + index1) == s2_->Get(offset2_ + index2);
337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
338b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s1_;
341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset1_;
342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int len1_;
343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s2_;
344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset2_;
345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int len2_;
346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
347b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
348b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
349b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Stores compare result in JSArray. Converts substring positions
350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// to absolute positions.
351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass TokensCompareOutput : public Comparator::Output {
352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokensCompareOutput(CompareOutputArrayWriter* array_writer,
354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      int offset1, int offset2)
355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        : array_writer_(array_writer), offset1_(offset1), offset2_(offset2) {
356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void AddChunk(int pos1, int pos2, int len1, int len2) {
359b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    array_writer_->WriteChunk(pos1 + offset1_, pos2 + offset2_, len1, len2);
360b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
361b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
362b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
363b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompareOutputArrayWriter* array_writer_;
364b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset1_;
365b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset2_;
366b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
368b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps raw n-elements line_ends array as a list of n+1 lines. The last line
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// never has terminating new line character.
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineEndsWrapper {
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit LineEndsWrapper(Handle<String> string)
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : ends_array_(CalculateLineEnds(string, false)),
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        string_len_(string->length()) {
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int length() {
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return ends_array_->length() + 1;
3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Returns start for any line including start of the imaginary line after
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the last line.
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineStart(int index) {
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == 0) {
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return 0;
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetLineEnd(index - 1);
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineEnd(int index) {
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == ends_array_->length()) {
3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // End of the last line is always an end of the whole string.
3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If the string ends with a new line character, the last line is an
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // empty string after this character.
3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return string_len_;
3956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetPosAfterNewLine(index);
3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<FixedArray> ends_array_;
4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int string_len_;
4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetPosAfterNewLine(int index) {
4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(ends_array_->get(index))->value() + 1;
4066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
4086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents 2 strings as 2 arrays of lines.
4116ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineArrayCompareInput : public Comparator::Input {
4126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LineArrayCompareInput(Isolate* isolate, Handle<String> s1, Handle<String> s2,
4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
41544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : isolate_(isolate), s1_(s1), s2_(s2), line_ends1_(line_ends1),
41644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        line_ends2_(line_ends2) {
4176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int getLength1() {
4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return line_ends1_.length();
4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int getLength2() {
4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return line_ends2_.length();
4236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool equals(int index1, int index2) {
4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start1 = line_ends1_.GetLineStart(index1);
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start2 = line_ends2_.GetLineStart(index2);
4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end1 = line_ends1_.GetLineEnd(index1);
4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end2 = line_ends2_.GetLineEnd(index2);
4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len1 = line_end1 - line_start1;
4306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len2 = line_end2 - line_start2;
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (len1 != len2) {
4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return CompareSubstrings(isolate_, s1_, line_start1, s2_, line_start2,
43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             len1);
4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s1_;
4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s2_;
4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
4436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
4446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Stores compare result in JSArray. For each chunk tries to conduct
448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// a fine-grained nested diff token-wise.
449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass TokenizingLineArrayCompareOutput : public Comparator::Output {
4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
451b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1,
452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                   LineEndsWrapper line_ends2,
453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                   Handle<String> s1, Handle<String> s2)
454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2) {
4556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
4586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos1 = line_ends1_.GetLineStart(line_pos1);
4596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos2 = line_ends2_.GetLineStart(line_pos2);
4606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
4616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
4626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (char_len1 < CHUNK_LEN_LIMIT && char_len2 < CHUNK_LEN_LIMIT) {
464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      // Chunk is small enough to conduct a nested token-level diff.
465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      HandleScope subTaskScope;
466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      TokensCompareInput tokens_input(s1_, char_pos1, char_len1,
468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                      s2_, char_pos2, char_len2);
469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      TokensCompareOutput tokens_output(&array_writer_, char_pos1,
470b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                          char_pos2);
471b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
472b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Comparator::CalculateDifference(&tokens_input, &tokens_output);
473b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } else {
474b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2);
475b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetResult() {
479b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return array_writer_.GetResult();
4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
483b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  static const int CHUNK_LEN_LIMIT = 800;
484b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompareOutputArrayWriter array_writer_;
4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s1_;
489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s2_;
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochHandle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         Handle<String> s2) {
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1(s1);
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2(s2);
4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
49844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LineArrayCompareInput
49944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      input(Isolate::Current(), s1, s2, line_ends1, line_ends2);
500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
5016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comparator::CalculateDifference(&input, &output);
5036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return output.GetResult();
5056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
50844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void CompileScriptForTracker(Isolate* isolate, Handle<Script> script) {
5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): support extensions.
51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PostponeInterruptsScope postpone(isolate);
5116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Build AST.
513f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompilationInfo info(script);
514f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  info.MarkAsGlobal();
5153e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (ParserApi::Parse(&info)) {
516f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // Compile the code.
51744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LiveEditFunctionTracker tracker(info.isolate(), info.function());
518f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    if (Compiler::MakeCodeForLiveEdit(&info)) {
519f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      ASSERT(!info.code().is_null());
520f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      tracker.RecordRootFunctionInfo(info.code());
521f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    } else {
52244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      info.isolate()->StackOverflow();
523f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
5246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
527f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
5286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Unwraps JSValue object, returning its field "value"
5296ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
5306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Handle<Object>(jsValue->value());
5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
533f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps any object into a OpaqueReference, that will hide the object
5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript.
5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<JSValue> WrapInJSValue(Object* object) {
53744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSFunction> constructor =
53844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->opaque_reference_function();
5396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSValue> result =
54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Handle<JSValue>::cast(FACTORY->NewJSObject(constructor));
5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  result->set_value(object);
5426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
545f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Simple helper class that creates more or less typed structures over
5476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// JSArray object. This is an adhoc method of passing structures from C++
5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// to JavaScript.
5496ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename S>
5506ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass JSArrayBasedStruct {
5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S Create() {
55344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<JSArray> array = FACTORY->NewJSArray(S::kSize_);
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array);
5556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S cast(Object* object) {
5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    JSArray* array = JSArray::cast(object);
5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> array_handle(array);
5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array_handle);
5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetJSArray() {
5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array_;
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
566f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected:
5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetField(int field_position, Handle<Object> value) {
56944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_, field_position, value);
5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSmiValueField(int field_position, int value) {
57244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
57344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        field_position,
57444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Handle<Smi>(Smi::FromInt(value)));
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* GetField(int field_position) {
5775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return array_->GetElementNoExceptionThrown(field_position);
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetSmiValueField(int field_position) {
5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* res = GetField(field_position);
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(res)->value();
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
583f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> array_;
5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents some function compilation details. This structure will be used
5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript. It contains Code object, which is kept wrapped
5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// into a BlindReference for sanitizing reasons.
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit FunctionInfoWrapper(Handle<JSArray> array)
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetInitialProperties(Handle<String> name, int start_position,
5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            int end_position, int param_num, int parent_index) {
5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParamNumOffset_, param_num);
6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParentIndexOffset_, parent_index);
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
606756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetFunctionCode(Handle<Code> function_code,
607756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Handle<Object> code_scope_info) {
608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<JSValue> code_wrapper = WrapInJSValue(*function_code);
609756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeOffset_, code_wrapper);
610756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
611756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<JSValue> scope_wrapper = WrapInJSValue(*code_scope_info);
612756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeScopeInfoOffset_, scope_wrapper);
6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
614756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetOuterScopeInfo(Handle<Object> scope_info_array) {
615756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kOuterScopeInfoOffset_, scope_info_array);
6166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) {
6186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> info_holder = WrapInJSValue(*info);
6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedFunctionInfoOffset_, info_holder);
6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetParentIndex() {
6226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kParentIndexOffset_);
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> GetFunctionCode() {
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        JSValue::cast(this->GetField(kCodeOffset_))));
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<Code>::cast(raw_result);
6286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
629756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Handle<Object> GetCodeScopeInfo() {
630756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
631756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        JSValue::cast(this->GetField(kCodeScopeInfoOffset_))));
632756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return raw_result;
633756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
6346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetStartPosition() {
6356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kStartPositionOffset_);
6366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetEndPosition() {
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kEndPositionOffset_);
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kParamNumOffset_ = 3;
6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kCodeOffset_ = 4;
647756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kCodeScopeInfoOffset_ = 5;
648756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kOuterScopeInfoOffset_ = 6;
649756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kParentIndexOffset_ = 7;
650756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSharedFunctionInfoOffset_ = 8;
651756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSize_ = 9;
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<FunctionInfoWrapper>;
6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
656f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps SharedFunctionInfo along with some of its fields for passing it
6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// back to JavaScript. SharedFunctionInfo object itself is additionally
6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// wrapped into BlindReference for sanitizing reasons.
6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
6616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static bool IsInstance(Handle<JSArray> array) {
6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array->length() == Smi::FromInt(kSize_) &&
6645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        array->GetElementNoExceptionThrown(kSharedInfoOffset_)->IsJSValue();
6656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit SharedInfoWrapper(Handle<JSArray> array)
6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<SharedInfoWrapper>(array) {
6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetProperties(Handle<String> name, int start_position, int end_position,
6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     Handle<SharedFunctionInfo> info) {
6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> info_holder = WrapInJSValue(*info);
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedInfoOffset_, info_holder);
6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> GetInfo() {
6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* element = this->GetField(kSharedInfoOffset_);
6826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> value_wrapper(JSValue::cast(element));
6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<SharedFunctionInfo>::cast(raw_result);
6856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
6886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
6896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSharedInfoOffset_ = 3;
6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSize_ = 4;
6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<SharedInfoWrapper>;
6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
697f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuclass FunctionInfoListener {
699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu public:
7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener() {
7016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = -1;
7026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_ = 0;
70344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result_ = FACTORY->NewJSArray(10);
7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionStarted(FunctionLiteral* fun) {
7076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FunctionInfoWrapper info = FunctionInfoWrapper::Create();
7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info.SetInitialProperties(fun->name(), fun->start_position(),
7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              fun->end_position(), fun->num_parameters(),
7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              current_parent_index_);
7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = len_;
71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(result_, len_, info.GetJSArray());
7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_++;
715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
717402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionDone() {
7186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = info.GetParentIndex();
723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
724402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
72559151504615d929945dc59db37bf1166937748c6Steve Block  // Saves only function code, because for a script function we
72659151504615d929945dc59db37bf1166937748c6Steve Block  // may never create a SharedFunctionInfo object.
72759151504615d929945dc59db37bf1166937748c6Steve Block  void FunctionCode(Handle<Code> function_code) {
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    info.SetFunctionCode(function_code, Handle<Object>(HEAP->null_value()));
73259151504615d929945dc59db37bf1166937748c6Steve Block  }
73359151504615d929945dc59db37bf1166937748c6Steve Block
73459151504615d929945dc59db37bf1166937748c6Steve Block  // Saves full information about a function: its code, its scope info
73559151504615d929945dc59db37bf1166937748c6Steve Block  // and a SharedFunctionInfo object.
73659151504615d929945dc59db37bf1166937748c6Steve Block  void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) {
73759151504615d929945dc59db37bf1166937748c6Steve Block    if (!shared->IsSharedFunctionInfo()) {
73859151504615d929945dc59db37bf1166937748c6Steve Block      return;
73959151504615d929945dc59db37bf1166937748c6Steve Block    }
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
74359151504615d929945dc59db37bf1166937748c6Steve Block    info.SetFunctionCode(Handle<Code>(shared->code()),
74459151504615d929945dc59db37bf1166937748c6Steve Block        Handle<Object>(shared->scope_info()));
74559151504615d929945dc59db37bf1166937748c6Steve Block    info.SetSharedFunctionInfo(shared);
74659151504615d929945dc59db37bf1166937748c6Steve Block
74759151504615d929945dc59db37bf1166937748c6Steve Block    Handle<Object> scope_info_list(SerializeFunctionScope(scope));
74859151504615d929945dc59db37bf1166937748c6Steve Block    info.SetOuterScopeInfo(scope_info_list);
74959151504615d929945dc59db37bf1166937748c6Steve Block  }
75059151504615d929945dc59db37bf1166937748c6Steve Block
75159151504615d929945dc59db37bf1166937748c6Steve Block  Handle<JSArray> GetResult() { return result_; }
75259151504615d929945dc59db37bf1166937748c6Steve Block
7536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
7546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* SerializeFunctionScope(Scope* scope) {
7556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope handle_scope;
7566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<JSArray> scope_info_list = FACTORY->NewJSArray(10);
7586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int scope_info_length = 0;
7596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Saves some description of scope. It stores name and indexes of
7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // variables in the whole scope chain. Null-named slots delimit
7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // scopes of this chain.
7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Scope* outer_scope = scope->outer_scope();
7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (outer_scope == NULL) {
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return HEAP->undefined_value();
7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    do {
7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ZoneList<Variable*> list(10);
7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      outer_scope->CollectUsedVariables(&list);
7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int j = 0;
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 0; i < list.length(); i++) {
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Variable* var1 = list[i];
7730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        Slot* slot = var1->AsSlot();
7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (slot != NULL && slot->type() == Slot::CONTEXT) {
7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (j != i) {
7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            list[j] = var1;
7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          j++;
7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Sort it.
7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int k = 1; k < j; k++) {
7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int l = k;
7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        for (int m = k + 1; m < j; m++) {
7860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen          if (list[l]->AsSlot()->index() > list[m]->AsSlot()->index()) {
7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            l = m;
7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        list[k] = list[l];
7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 0; i < j; i++) {
79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        SetElementNonStrict(scope_info_list,
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            scope_info_length,
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            list[i]->name());
7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        SetElementNonStrict(
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block            scope_info_list,
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block            scope_info_length,
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index())));
8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SetElementNonStrict(scope_info_list,
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          scope_info_length,
80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Handle<Object>(HEAP->null_value()));
8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      scope_info_length++;
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      outer_scope = outer_scope->outer_scope();
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } while (outer_scope != NULL);
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return *scope_info_list;
812402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
813402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len_;
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int current_parent_index_;
817402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu};
818402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
819f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockJSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> source) {
82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompilationZoneScope zone_scope(DELETE_ON_EXIT);
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener listener;
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> original_source = Handle<Object>(script->source());
8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*source);
82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->set_active_function_info_listener(&listener);
82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CompileScriptForTracker(isolate, script);
83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->set_active_function_info_listener(NULL);
8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*original_source);
8326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *(listener.GetResult());
8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(array->length())->value();
8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info(
8425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        SharedFunctionInfo::cast(array->GetElementNoExceptionThrown(i)));
8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<String> name_handle(String::cast(info->name()));
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info_wrapper.SetProperties(name_handle, info->start_position(),
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               info->end_position(), info);
84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array, i, info_wrapper.GetJSArray());
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor that collects all references to a particular code object,
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// including "CODE_TARGET" references in other code objects.
8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It works in context of ZoneScope.
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ReferenceCollectorVisitor : public ObjectVisitor {
8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit ReferenceCollectorVisitor(Code* original)
858791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    : original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) {
8596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitPointers(Object** start, Object** end) {
8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (Object** p = start; p < end; p++) {
8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (*p == original_) {
8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        rvalues_.Add(p);
8656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
8666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
8676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
869791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeEntry(Address entry) {
870791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (Code::GetObjectFromEntryAddress(entry) == original_) {
871791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      code_entries_.Add(entry);
872791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
873791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
874791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
875791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeTarget(RelocInfo* rinfo) {
8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      reloc_infos_.Add(*rinfo);
8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
8806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitDebugTarget(RelocInfo* rinfo) {
8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitCodeTarget(rinfo);
8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Post-visiting method that iterates over all collected references and
8876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // modifies them.
8886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Replace(Code* substitution) {
8896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < rvalues_.length(); i++) {
8906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      *(rvalues_[i]) = substitution;
8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
892791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Address substitution_entry = substitution->instruction_start();
8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < reloc_infos_.length(); i++) {
894791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      reloc_infos_[i].set_target_address(substitution_entry);
895791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
896791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    for (int i = 0; i < code_entries_.length(); i++) {
897791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Address entry = code_entries_[i];
898791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Memory::Address_at(entry) = substitution_entry;
8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Code* original_;
9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<Object**> rvalues_;
9056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<RelocInfo> reloc_infos_;
906791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ZoneList<Address> code_entries_;
9076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
9086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Finds all references to original and replaces them with substitution.
9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReplaceCodeObject(Code* original, Code* substitution) {
91244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!HEAP->InNewSpace(substitution));
9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  AssertNoAllocation no_allocations_please;
9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // A zone scope for ReferenceCollectorVisitor.
9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneScope scope(DELETE_ON_EXIT);
9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ReferenceCollectorVisitor visitor(original);
9206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Iterate over all roots. Stack frames may have pointer into original code,
9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // so temporary replace the pointers with offset numbers
9236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in prologue/epilogue.
9246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HEAP->IterateStrongRoots(&visitor, VISIT_ALL);
9266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Now iterate over all pointers of all objects, including code_target
9296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // implicit pointers.
9306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HeapIterator iterator;
9316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
9326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    obj->Iterate(&visitor);
9336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  visitor.Replace(substitution);
9366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check whether the code is natural function code (not a lazy-compile stub
9406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// code).
9416ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsJSFunctionCode(Code* code) {
9426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return code->kind() == Code::FUNCTION;
9436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Returns true if an instance of candidate were inlined into function's code.
947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) {
948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_gc;
949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* data =
953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      DeoptimizationInputData::cast(function->code()->deoptimization_data());
954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
95544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (data == HEAP->empty_fixed_array()) return false;
956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  FixedArray* literals = data->LiteralArray();
958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int inlined_count = data->InlinedFunctionCount()->value();
960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < inlined_count; ++i) {
961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* inlined = JSFunction::cast(literals->get(i));
962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (inlined->shared() == candidate) return true;
963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass DependentFunctionsDeoptimizingVisitor : public OptimizedFunctionVisitor {
970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit DependentFunctionsDeoptimizingVisitor(
972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* function_info)
973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : function_info_(function_info) {}
974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void EnterContext(Context* context) {
976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void VisitFunction(JSFunction* function) {
979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->shared() == function_info_ ||
980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        IsInlined(function, function_info_)) {
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Deoptimizer::DeoptimizeFunction(function);
982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void LeaveContext(Context* context) {
986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedFunctionInfo* function_info_;
990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) {
994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DependentFunctionsDeoptimizingVisitor visitor(function_info);
997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Deoptimizer::VisitAllOptimizedFunctions(&visitor);
998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10015913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::ReplaceFunctionCode(
10025913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Handle<JSArray> new_compile_info_array,
10035913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Handle<JSArray> shared_info_array) {
10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->ThrowIllegalOperation();
10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
10126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(shared_info->code())) {
10166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ReplaceCodeObject(shared_info->code(),
10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      *(compile_info_wrapper.GetFunctionCode()));
1018756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> code_scope_info =  compile_info_wrapper.GetCodeScopeInfo();
1019756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (code_scope_info->IsFixedArray()) {
1020756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info));
1021756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (shared_info->debug_info()->IsDebugInfo()) {
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> new_original_code =
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode());
10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    debug_info->set_original_code(*new_original_code);
10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_start_position(compile_info_wrapper.GetStartPosition());
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_construct_stub(
103544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->builtins()->builtin(
103644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Builtins::kJSConstructStubGeneric));
10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizeDependentFunctions(*shared_info);
103944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->compilation_cache()->Remove(shared_info);
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
104144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->undefined_value();
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochMaybeObject* LiveEdit::FunctionSourceUpdated(
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSArray> shared_info_array) {
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HandleScope scope;
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->ThrowIllegalOperation();
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedInfoWrapper shared_info_wrapper(shared_info_array);
1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizeDependentFunctions(*shared_info);
105744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->compilation_cache()->Remove(shared_info);
1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->undefined_value();
10606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 Handle<Object> script_handle) {
10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info =
10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
10676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_script(*script_handle);
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
106944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->compilation_cache()->Remove(shared_info);
10706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// For a script text change (defined as position_change_array), translates
10746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// position in unchanged text to position in changed text.
10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Text change is a set of non-overlapping regions in text, that have changed
10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// their contents and length. It is specified as array of groups of 3 numbers:
10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (change_begin, change_end, change_end_new_position).
10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Each group describes a change in text; groups are sorted by change_begin.
10796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Only position in text beyond any changes may be successfully translated.
10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// If a positions is inside some region that changed, result is currently
10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// undefined.
10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic int TranslatePosition(int original_position,
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             Handle<JSArray> position_change_array) {
10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int position_diff = 0;
10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(position_change_array->length())->value();
10866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): binary search may be used here
10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i += 3) {
10885913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* element = position_change_array->GetElementNoExceptionThrown(i);
10895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_start = Smi::cast(element)->value();
10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (original_position < chunk_start) {
10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    element = position_change_array->GetElementNoExceptionThrown(i + 1);
10945913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_end = Smi::cast(element)->value();
10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Position mustn't be inside a chunk.
10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(original_position >= chunk_end);
10975913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    element = position_change_array->GetElementNoExceptionThrown(i + 2);
10985913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_changed_end = Smi::cast(element)->value();
10996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    position_diff = chunk_changed_end - chunk_end;
11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return original_position + position_diff;
11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Auto-growing buffer for writing relocation info code section. This buffer
11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// is a simplified version of buffer from Assembler. Unlike Assembler, this
11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// class is platform-independent and it works without dealing with instructions.
11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// As specified by RelocInfo format, the buffer is filled in reversed order:
11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from upper to lower addresses.
11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It uses NewArray/DeleteArray for memory management.
11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass RelocInfoBuffer {
11136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
11146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer(int buffer_initial_capicity, byte* pc) {
11156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = buffer_initial_capicity + kBufferGap;
11166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = NewArray<byte>(buffer_size_);
11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc);
11196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~RelocInfoBuffer() {
11216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // As specified by RelocInfo format, the buffer is filled in reversed order:
11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // from upper to lower addresses.
11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Write(const RelocInfo* rinfo) {
11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) {
11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Grow();
11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Write(rinfo);
11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> GetResult() {
11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Return the bytes from pos up to end of buffer.
11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int result_size =
11366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer_.pos());
11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Vector<byte>(reloc_info_writer_.pos(), result_size);
11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Grow() {
11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Compute new buffer size.
11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int new_buffer_size;
11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_size_ < 2 * KB) {
11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 4 * KB;
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 2 * buffer_size_;
11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Some internal data structures overflow for very large buffers,
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // they must ensure that kMaximalBufferSize is not too large.
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (new_buffer_size > kMaximalBufferSize) {
11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer");
11536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Setup new buffer.
11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    byte* new_buffer = NewArray<byte>(new_buffer_size);
11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Copy the data.
11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int curently_used_size =
11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>(buffer_ + buffer_size_ - reloc_info_writer_.pos());
11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memmove(new_buffer + new_buffer_size - curently_used_size,
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            reloc_info_writer_.pos(), curently_used_size);
11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(
11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        new_buffer + new_buffer_size - curently_used_size,
11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        reloc_info_writer_.last_pc());
11676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
11696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = new_buffer;
11706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = new_buffer_size;
11716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoWriter reloc_info_writer_;
11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  byte* buffer_;
11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int buffer_size_;
11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1177f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kBufferGap = RelocInfoWriter::kMaxSize;
11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kMaximalBufferSize = 512*MB;
11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Patch positions in code (changes relocation info section) and possibly
11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// returns new instance of code.
11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Code> PatchPositionsInCode(Handle<Code> code,
11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> position_change_array) {
11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer buffer_writer(code->relocation_size(),
11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                code->instruction_start());
11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    AssertNoAllocation no_allocations_please;
11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (RelocIterator it(*code); !it.done(); it.next()) {
11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      RelocInfo* rinfo = it.rinfo();
11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (RelocInfo::IsPosition(rinfo->rmode())) {
11946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int position = static_cast<int>(rinfo->data());
11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int new_position = TranslatePosition(position,
11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (position != new_position) {
11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position);
11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          buffer_writer.Write(&info_copy);
12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          continue;
12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
12026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      buffer_writer.Write(it.rinfo());
12046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> buffer = buffer_writer.GetResult();
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (buffer.length() == code->relocation_size()) {
12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Simply patch relocation area of code.
12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memcpy(code->relocation_start(), buffer.start(), buffer.length());
12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return code;
12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Relocation info section now has different size. We cannot simply
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // rewrite it inside code object. Instead we have to create a new
12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // code object.
121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> result(FACTORY->CopyCode(code, buffer));
12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
12196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12235913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::PatchFunctionPositions(
12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
122744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->ThrowIllegalOperation();
12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
12316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int old_function_start = info->start_position();
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int new_function_start = TranslatePosition(old_function_start,
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_start_position(new_function_start);
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_end_position(TranslatePosition(info->end_position(),
12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           position_change_array));
12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_function_token_position(
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      TranslatePosition(info->function_token_position(),
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      position_change_array));
12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(info->code())) {
12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Patch relocation info section of the code.
12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()),
12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                     position_change_array);
12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (*patched_code != info->code()) {
12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Replace all references to the code across the heap. In particular,
12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // some stubs may refer to this code and this code may be being executed
12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // on stack (it is safe to substitute the code object on stack, because
12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // we only change the structure of rinfo and leave instructions
12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // untouched).
12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReplaceCodeObject(info->code(), *patched_code);
12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
125844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->undefined_value();
12596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Script> CreateScriptCopy(Handle<Script> original) {
12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> original_source(String::cast(original->source()));
12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
126544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Script> copy = FACTORY->NewScript(original_source);
12666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_name(original->name());
12686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_line_offset(original->line_offset());
12696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_column_offset(original->column_offset());
12706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_data(original->data());
12716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_type(original->type());
12726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_context_data(original->context_data());
12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_compilation_type(original->compilation_type());
12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_shared(original->eval_from_shared());
12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_instructions_offset(
12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      original->eval_from_instructions_offset());
12776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return copy;
12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12826ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LiveEdit::ChangeScriptSource(Handle<Script> original_script,
12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> new_source,
12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<Object> old_script_name) {
12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> old_script_object;
12866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (old_script_name->IsString()) {
12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Script> old_script = CreateScriptCopy(original_script);
12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script->set_name(String::cast(*old_script_name));
12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script_object = old_script;
129044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate::Current()->debugger()->OnAfterCompile(
129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        old_script, Debugger::SEND_WHEN_DEBUGGING);
12926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    old_script_object = Handle<Object>(HEAP->null_value());
12946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  original_script->set_source(*new_source);
12976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Drop line ends so that they will be recalculated.
129944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  original_script->set_line_ends(HEAP->undefined_value());
13006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *old_script_object;
13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13066ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::ReplaceRefToNestedFunction(
13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> parent_function_wrapper,
13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> orig_function_wrapper,
13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> subst_function_wrapper) {
13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> parent_shared =
13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(parent_function_wrapper));
13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> orig_shared =
13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(orig_function_wrapper));
13156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> subst_shared =
13166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(subst_function_wrapper));
13176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
13196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
13206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (it.rinfo()->target_object() == *orig_shared) {
13216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        it.rinfo()->set_target_object(*subst_shared);
13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
13236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check an activation against list of functions. If there is a function
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that matches, its status in result array is changed to status argument value.
13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CheckActivation(Handle<JSArray> shared_info_array,
1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Handle<JSArray> result,
1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            StackFrame* frame,
13336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FunctionPatchabilityStatus status) {
1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!frame->is_java_script()) return false;
1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<JSFunction> function(
1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JSFunction::cast(JavaScriptFrame::cast(frame)->function()));
1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
13406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
13415913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSValue* wrapper =
13425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i));
13436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> shared(
13446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SharedFunctionInfo::cast(wrapper->value()));
13456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->shared() == *shared || IsInlined(*function, *shared)) {
134744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SetElementNonStrict(result, i, Handle<Smi>(Smi::FromInt(status)));
13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Iterates over handler chain and removes all elements that are inside
13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames being dropped.
13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool FixTryCatchHandler(StackFrame* top_frame,
13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               StackFrame* bottom_frame) {
13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* pointer_address =
136044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &Memory::Address_at(Isolate::Current()->get_address_from_id(
136144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Isolate::k_handler_address));
13626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < top_frame->sp()) {
13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* above_frame_address = pointer_address;
13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < bottom_frame->fp()) {
13686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool change = *above_frame_address != *pointer_address;
13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  *above_frame_address = *pointer_address;
13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return change;
13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Removes specified range of frames from stack. There may be 1 or more
13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames in range. Anyway the bottom frame is restarted rather than dropped,
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// and therefore has to be a JavaScript frame.
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Returns error message or NULL.
13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropFrames(Vector<StackFrame*> frames,
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              int top_frame_index,
13828defd9ff6930b4e24729971a61cf7469daf119beSteve Block                              int bottom_js_frame_index,
1383bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Debug::FrameDropMode* mode,
1384bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Object*** restarter_frame_function_pointer) {
1385756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (!Debug::kFrameDropperSupported) {
13868defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return "Stack manipulations are not supported in this architecture.";
13878defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
13888defd9ff6930b4e24729971a61cf7469daf119beSteve Block
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* pre_top_frame = frames[top_frame_index - 1];
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* top_frame = frames[top_frame_index];
13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* bottom_js_frame = frames[bottom_js_frame_index];
13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(bottom_js_frame->is_java_script());
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the nature of the top frame.
139644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* pre_top_frame_code = pre_top_frame->LookupCode(Isolate::Current());
139744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (pre_top_frame_code->is_inline_cache_stub() &&
139844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      pre_top_frame_code->ic_state() == DEBUG_BREAK) {
13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop inline cache calls.
14008defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
140144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (pre_top_frame_code ==
140244f0eee88ff00398ff7f715fab053374d808c90dSteve Block             Isolate::Current()->debug()->debug_break_slot()) {
14038defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // OK, we can drop debug break slot.
14048defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
140544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (pre_top_frame_code ==
140644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->builtins()->builtin(
140744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Builtins::kFrameDropper_LiveEdit)) {
14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop our own code.
14098defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
141044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (pre_top_frame_code->kind() == Code::STUB &&
141144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      pre_top_frame_code->major_key()) {
14128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Entry from our unit tests, it's fine, we support this case.
14138defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
14146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Unknown structure of stack above changing function";
14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_top = top_frame->sp();
14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_bottom = bottom_js_frame->fp()
14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      - Debug::kFrameDropperFrameSize * kPointerSize  // Size of the new frame.
14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      + kPointerSize;  // Bigger address end is exclusive.
14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (unused_stack_top > unused_stack_bottom) {
14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Not enough space for frame dropper frame";
14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Committing now. After this point we should return only NULL value.
14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FixTryCatchHandler(pre_top_frame, bottom_js_frame);
14306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Make sure FixTryCatchHandler is idempotent.
14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
143344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> code = Isolate::Current()->builtins()->FrameDropper_LiveEdit();
14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  top_frame->set_pc(code->entry());
14356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  pre_top_frame->SetCallerFp(bottom_js_frame->fp());
14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1437bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  *restarter_frame_function_pointer =
1438bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      Debug::SetUpFrameDropperFrame(bottom_js_frame, code);
1439bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1440bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((**restarter_frame_function_pointer)->IsJSFunction());
14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (Address a = unused_stack_top;
14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a < unused_stack_bottom;
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a += kPointerSize) {
14456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Memory::Object_at(a) = Smi::FromInt(0);
14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDropableFrame(StackFrame* frame) {
14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return !frame->is_exit();
14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Fills result array with statuses of functions. Modifies the stack
14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// removing all listed function if possible and if do_drop is true.
14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropActivationsInActiveThread(
14596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
146044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Debug* debug = Isolate::Current()->debug();
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneScope scope(DELETE_ON_EXIT);
14626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<StackFrame*> frames = CreateStackMap();
14636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(shared_info_array->length())->value();
14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int top_frame_index = -1;
14676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_index = 0;
14686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
147044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (frame->id() == debug->break_frame_id()) {
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      top_frame_index = frame_index;
14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
14766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We are still above break_frame. It is not a target frame,
14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // it is a problem.
14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return "Debugger mark-up on stack is not found";
14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_frame_index == -1) {
14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We haven't found break frame, but no function is blocking us anyway.
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool target_frame_found = false;
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int bottom_js_frame_index = top_frame_index;
14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool c_code_found = false;
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!IsDropableFrame(frame)) {
14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      c_code_found = true;
14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      target_frame_found = true;
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      bottom_js_frame_index = frame_index;
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (c_code_found) {
15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // There is a C frames on stack. Check that there are no target frames
15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // below them.
15076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (; frame_index < frames.length(); frame_index++) {
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StackFrame* frame = frames[frame_index];
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (frame->is_java_script()) {
15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (CheckActivation(shared_info_array, result, frame,
15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // Cannot drop frame under C frames.
15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          return NULL;
15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
15156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!do_drop) {
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We are in check-only mode.
15216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
15226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!target_frame_found) {
15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Nothing to drop.
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15298defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED;
1530bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object** restarter_frame_function_pointer = NULL;
15316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message = DropFrames(frames, top_frame_index,
1532bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         bottom_js_frame_index, &drop_mode,
1533bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         &restarter_frame_function_pointer);
15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return error_message;
15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Adjust break_frame after some frames has been dropped.
15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame::Id new_id = StackFrame::NO_ID;
15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_id = frames[i]->id();
15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
154744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  debug->FramesHaveBeenDropped(new_id, drop_mode,
1548bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                               restarter_frame_function_pointer);
15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Replace "blocked on active" with "replaced on active" status.
15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i++) {
15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (result->GetElement(i) ==
15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
155480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Handle<Object> replaced(
155580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
155644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SetElementNonStrict(result, i, replaced);
15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass InactiveThreadActivationsChecker : public ThreadVisitor {
15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
15656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   Handle<JSArray> result)
15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : shared_info_array_(shared_info_array), result_(result),
15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_blocked_functions_(false) {
15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitThread(ThreadLocalTop* top) {
15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
15726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      has_blocked_functions_ |= CheckActivation(
15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          shared_info_array_, result_, it.frame(),
15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
15756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool HasBlockedFunctions() {
15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return has_blocked_functions_;
15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
15826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> shared_info_array_;
15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool has_blocked_functions_;
15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15886ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CheckAndDropActivations(
15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, bool do_drop) {
15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
159244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSArray> result = FACTORY->NewJSArray(len);
15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fill the default values.
15956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
159644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(
159744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        result,
159844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        i,
159944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First check inactive threads. Fail if some functions are blocked there.
16046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
16056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                            result);
160644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->thread_manager()->IterateArchivedThreads(
160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &inactive_threads_checker);
16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (inactive_threads_checker.HasBlockedFunctions()) {
16096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
16106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Try to drop activations from the current stack.
16136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message =
16146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      DropActivationsInActiveThread(shared_info_array, result, do_drop);
16156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
16166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Add error message as an array extra element.
16176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Vector<const char> vector_message(error_message, StrLength(error_message));
161844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<String> str = FACTORY->NewStringFromAscii(vector_message);
161944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(result, len, str);
16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
16226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
162544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockLiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
162644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 FunctionLiteral* fun)
162744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate) {
162844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate_->active_function_info_listener() != NULL) {
162944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate_->active_function_info_listener()->FunctionStarted(fun);
1630402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1631402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
16326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1634402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::~LiveEditFunctionTracker() {
163544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate_->active_function_info_listener() != NULL) {
163644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate_->active_function_info_listener()->FunctionDone();
1637402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1638402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
16396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16416ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
16426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
164344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate_->active_function_info_listener() != NULL) {
164444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope());
1645402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1646402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
16476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16496ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
165044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->active_function_info_listener()->FunctionCode(code);
1651402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
16526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
165444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
165544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return isolate->active_function_info_listener() != NULL;
1656402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1657402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
16586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else  // ENABLE_DEBUGGER_SUPPORT
16606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// This ifdef-else-endif section provides working or stub implementation of
16626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// LiveEditFunctionTracker.
166344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockLiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
166444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 FunctionLiteral* fun) {
16656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16686ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::~LiveEditFunctionTracker() {
16696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16726ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
16736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
16746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16776ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
16786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16816ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool LiveEditFunctionTracker::IsActive() {
16826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
16836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // ENABLE_DEBUGGER_SUPPORT
16866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1689402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} }  // namespace v8::internal
1690