1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 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
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "compilation-cache.h"
34257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "compiler.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.
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<Object> no_failure =
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      JSObject::SetElement(object, index, value, NONE, 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)
693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : 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;
1543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          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
271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic bool CompareSubstrings(Handle<String> s1, int pos1,
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              Handle<String> s2, int pos2, int len) {
2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (s1->Get(i + pos1) != s2->Get(i + pos2)) {
2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Additional to Input interface. Lets switch Input range to subrange.
2833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// More elegant way would be to wrap one Input as another Input object
2843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// and translate positions there, but that would cost us additional virtual
2853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// call per comparison.
2863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass SubrangableInput : public Comparator::Input {
2873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
2883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void SetSubrange1(int offset, int len) = 0;
2893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void SetSubrange2(int offset, int len) = 0;
2903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
2913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass SubrangableOutput : public Comparator::Output {
2943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
2953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void SetSubrange1(int offset, int len) = 0;
2963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void SetSubrange2(int offset, int len) = 0;
2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
2983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic int min(int a, int b) {
3013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return a < b ? a : b;
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Finds common prefix and suffix in input. This parts shouldn't take space in
3063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// linear programming table. Enable subranging in input and output.
3073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic void NarrowDownInput(SubrangableInput* input,
3083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SubrangableOutput* output) {
3093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int len1 = input->GetLength1();
3103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int len2 = input->GetLength2();
3113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int common_prefix_len;
3133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int common_suffix_len;
3143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  {
3163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    common_prefix_len = 0;
3173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int prefix_limit = min(len1, len2);
3183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (common_prefix_len < prefix_limit &&
3193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        input->Equals(common_prefix_len, common_prefix_len)) {
3203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      common_prefix_len++;
3213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    common_suffix_len = 0;
3243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int suffix_limit = min(len1 - common_prefix_len, len2 - common_prefix_len);
3253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (common_suffix_len < suffix_limit &&
3273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        input->Equals(len1 - common_suffix_len - 1,
3283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        len2 - common_suffix_len - 1)) {
3293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      common_suffix_len++;
3303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
3313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (common_prefix_len > 0 || common_suffix_len > 0) {
3343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int new_len1 = len1 - common_suffix_len - common_prefix_len;
3353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int new_len2 = len2 - common_suffix_len - common_prefix_len;
3363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input->SetSubrange1(common_prefix_len, new_len1);
3383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input->SetSubrange2(common_prefix_len, new_len2);
3393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    output->SetSubrange1(common_prefix_len, new_len1);
3413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    output->SetSubrange2(common_prefix_len, new_len2);
3423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
3443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// A helper class that writes chunk numbers into JSArray.
347b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end).
348b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass CompareOutputArrayWriter {
349b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompareOutputArrayWriter()
35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : array_(FACTORY->NewJSArray(10)), current_size_(0) {}
352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
353b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<JSArray> GetResult() {
354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return array_;
355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) {
35844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
35944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       current_size_,
36044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       Handle<Object>(Smi::FromInt(char_pos1)));
36144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        current_size_ + 1,
36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Handle<Object>(Smi::FromInt(char_pos1 + char_len1)));
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
36544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        current_size_ + 2,
36644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Handle<Object>(Smi::FromInt(char_pos2 + char_len2)));
367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    current_size_ += 3;
368b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
369b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
370b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
371b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<JSArray> array_;
372b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int current_size_;
373b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
374b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
375b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
376b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Represents 2 strings as 2 arrays of tokens.
377b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// TODO(LiveEdit): Currently it's actually an array of charactres.
378b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch//     Make array of tokens instead.
379b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass TokensCompareInput : public Comparator::Input {
380b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
381b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokensCompareInput(Handle<String> s1, int offset1, int len1,
382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       Handle<String> s2, int offset2, int len2)
383b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : s1_(s1), offset1_(offset1), len1_(len1),
384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        s2_(s2), offset2_(offset2), len2_(len2) {
385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
3863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual int GetLength1() {
387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return len1_;
388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual int GetLength2() {
390b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return len2_;
391b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
3923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool Equals(int index1, int index2) {
393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return s1_->Get(offset1_ + index1) == s2_->Get(offset2_ + index2);
394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
397b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s1_;
398b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset1_;
399b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int len1_;
400b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s2_;
401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset2_;
402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int len2_;
403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Stores compare result in JSArray. Converts substring positions
407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// to absolute positions.
408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass TokensCompareOutput : public Comparator::Output {
409b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
410b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokensCompareOutput(CompareOutputArrayWriter* array_writer,
411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                      int offset1, int offset2)
412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        : array_writer_(array_writer), offset1_(offset1), offset2_(offset2) {
413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
415b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void AddChunk(int pos1, int pos2, int len1, int len2) {
416b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    array_writer_->WriteChunk(pos1 + offset1_, pos2 + offset2_, len1, len2);
417b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
418b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
420b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompareOutputArrayWriter* array_writer_;
421b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset1_;
422b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int offset2_;
423b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
424b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
425b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps raw n-elements line_ends array as a list of n+1 lines. The last line
4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// never has terminating new line character.
4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineEndsWrapper {
4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
4306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit LineEndsWrapper(Handle<String> string)
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : ends_array_(CalculateLineEnds(string, false)),
4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        string_len_(string->length()) {
4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int length() {
4356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return ends_array_->length() + 1;
4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Returns start for any line including start of the imaginary line after
4386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the last line.
4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineStart(int index) {
4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == 0) {
4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return 0;
4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
4436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetLineEnd(index - 1);
4446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineEnd(int index) {
4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == ends_array_->length()) {
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // End of the last line is always an end of the whole string.
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If the string ends with a new line character, the last line is an
4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // empty string after this character.
4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return string_len_;
4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
4536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetPosAfterNewLine(index);
4546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
4556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
4586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<FixedArray> ends_array_;
4596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int string_len_;
4606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetPosAfterNewLine(int index) {
4626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(ends_array_->get(index))->value() + 1;
4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents 2 strings as 2 arrays of lines.
4683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass LineArrayCompareInput : public SubrangableInput {
4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : s1_(s1), s2_(s2), line_ends1_(line_ends1),
4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        line_ends2_(line_ends2),
4743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        subrange_offset1_(0), subrange_offset2_(0),
4753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        subrange_len1_(line_ends1_.length()),
4763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        subrange_len2_(line_ends2_.length()) {
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int GetLength1() {
4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return subrange_len1_;
4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int GetLength2() {
4823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return subrange_len2_;
4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool Equals(int index1, int index2) {
4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    index1 += subrange_offset1_;
4863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    index2 += subrange_offset2_;
4873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start1 = line_ends1_.GetLineStart(index1);
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start2 = line_ends2_.GetLineStart(index2);
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end1 = line_ends1_.GetLineEnd(index1);
4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end2 = line_ends2_.GetLineEnd(index2);
4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len1 = line_end1 - line_start1;
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len2 = line_end2 - line_start2;
4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (len1 != len2) {
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return CompareSubstrings(s1_, line_start1, s2_, line_start2,
49844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                             len1);
4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void SetSubrange1(int offset, int len) {
5013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subrange_offset1_ = offset;
5023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subrange_len1_ = len;
5033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void SetSubrange2(int offset, int len) {
5053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subrange_offset2_ = offset;
5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subrange_len2_ = len;
5073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
5106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s1_;
5116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s2_;
5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
5143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int subrange_offset1_;
5153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int subrange_offset2_;
5163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int subrange_len1_;
5173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int subrange_len2_;
5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
521b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Stores compare result in JSArray. For each chunk tries to conduct
522b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// a fine-grained nested diff token-wise.
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass TokenizingLineArrayCompareOutput : public SubrangableOutput {
5246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
525b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1,
526b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                   LineEndsWrapper line_ends2,
527b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                   Handle<String> s1, Handle<String> s2)
5283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2),
5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        subrange_offset1_(0), subrange_offset2_(0) {
5306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    line_pos1 += subrange_offset1_;
5343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    line_pos2 += subrange_offset2_;
5353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos1 = line_ends1_.GetLineStart(line_pos1);
5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos2 = line_ends2_.GetLineStart(line_pos2);
5386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
5396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
5406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (char_len1 < CHUNK_LEN_LIMIT && char_len2 < CHUNK_LEN_LIMIT) {
542b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      // Chunk is small enough to conduct a nested token-level diff.
543b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      HandleScope subTaskScope;
544b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
545b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      TokensCompareInput tokens_input(s1_, char_pos1, char_len1,
546b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                      s2_, char_pos2, char_len2);
547b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      TokensCompareOutput tokens_output(&array_writer_, char_pos1,
548b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                          char_pos2);
549b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
550b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Comparator::CalculateDifference(&tokens_input, &tokens_output);
551b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } else {
552b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2);
553b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void SetSubrange1(int offset, int len) {
5563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subrange_offset1_ = offset;
5573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void SetSubrange2(int offset, int len) {
5593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    subrange_offset2_ = offset;
5603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetResult() {
563b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return array_writer_.GetResult();
5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  static const int CHUNK_LEN_LIMIT = 800;
568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CompareOutputArrayWriter array_writer_;
5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s1_;
573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<String> s2_;
5743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int subrange_offset1_;
5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int subrange_offset2_;
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
579b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben MurdochHandle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
580b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                         Handle<String> s2) {
581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  s1 = FlattenGetString(s1);
582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  s2 = FlattenGetString(s2);
583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1(s1);
5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2(s2);
5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
588b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  NarrowDownInput(&input, &output);
5913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comparator::CalculateDifference(&input, &output);
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return output.GetResult();
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
59844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic void CompileScriptForTracker(Isolate* isolate, Handle<Script> script) {
5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): support extensions.
60044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  PostponeInterruptsScope postpone(isolate);
6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Build AST.
603f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompilationInfo info(script);
604f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  info.MarkAsGlobal();
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Parse and don't allow skipping lazy functions.
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (ParserApi::Parse(&info, kNoParsingFlags)) {
607f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    // Compile the code.
60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LiveEditFunctionTracker tracker(info.isolate(), info.function());
609f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    if (Compiler::MakeCodeForLiveEdit(&info)) {
610f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      ASSERT(!info.code().is_null());
611f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      tracker.RecordRootFunctionInfo(info.code());
612f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    } else {
61344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      info.isolate()->StackOverflow();
614f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
6156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
618f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Unwraps JSValue object, returning its field "value"
6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Handle<Object>(jsValue->value());
6226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
624f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps any object into a OpaqueReference, that will hide the object
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript.
627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic Handle<JSValue> WrapInJSValue(Handle<Object> object) {
62844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSFunction> constructor =
62944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->opaque_reference_function();
6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSValue> result =
63144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Handle<JSValue>::cast(FACTORY->NewJSObject(constructor));
632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  result->set_value(*object);
6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
6346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
6356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
636f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Simple helper class that creates more or less typed structures over
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// JSArray object. This is an adhoc method of passing structures from C++
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// to JavaScript.
6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename S>
6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass JSArrayBasedStruct {
6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S Create() {
64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<JSArray> array = FACTORY->NewJSArray(S::kSize_);
6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array);
6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S cast(Object* object) {
6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    JSArray* array = JSArray::cast(object);
6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> array_handle(array);
6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array_handle);
6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetJSArray() {
6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array_;
6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
657f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected:
6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetField(int field_position, Handle<Object> value) {
66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_, field_position, value);
6616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSmiValueField(int field_position, int value) {
66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array_,
66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        field_position,
66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                        Handle<Smi>(Smi::FromInt(value)));
6666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* GetField(int field_position) {
6685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    return array_->GetElementNoExceptionThrown(field_position);
6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetSmiValueField(int field_position) {
6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* res = GetField(field_position);
6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(res)->value();
6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
674f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> array_;
6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents some function compilation details. This structure will be used
6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript. It contains Code object, which is kept wrapped
6826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// into a BlindReference for sanitizing reasons.
6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
6856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit FunctionInfoWrapper(Handle<JSArray> array)
6866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
6876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetInitialProperties(Handle<String> name, int start_position,
6896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            int end_position, int param_num, int parent_index) {
6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParamNumOffset_, param_num);
6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParentIndexOffset_, parent_index);
6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
697756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetFunctionCode(Handle<Code> function_code,
698756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Handle<Object> code_scope_info) {
699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
700756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeOffset_, code_wrapper);
701756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<JSValue> scope_wrapper = WrapInJSValue(code_scope_info);
703756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeScopeInfoOffset_, scope_wrapper);
7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
705756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetOuterScopeInfo(Handle<Object> scope_info_array) {
706756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kOuterScopeInfoOffset_, scope_info_array);
7076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) {
709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<JSValue> info_holder = WrapInJSValue(info);
7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedFunctionInfoOffset_, info_holder);
7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetParentIndex() {
7136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kParentIndexOffset_);
7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> GetFunctionCode() {
7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        JSValue::cast(this->GetField(kCodeOffset_))));
7186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<Code>::cast(raw_result);
7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
720756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Handle<Object> GetCodeScopeInfo() {
721756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
722756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        JSValue::cast(this->GetField(kCodeScopeInfoOffset_))));
723756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return raw_result;
724756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetStartPosition() {
7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kStartPositionOffset_);
7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetEndPosition() {
7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kEndPositionOffset_);
7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
7346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
7356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
7366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kParamNumOffset_ = 3;
7376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kCodeOffset_ = 4;
738756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kCodeScopeInfoOffset_ = 5;
739756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kOuterScopeInfoOffset_ = 6;
740756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kParentIndexOffset_ = 7;
741756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSharedFunctionInfoOffset_ = 8;
742756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSize_ = 9;
7436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<FunctionInfoWrapper>;
7456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
747f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
7486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps SharedFunctionInfo along with some of its fields for passing it
7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// back to JavaScript. SharedFunctionInfo object itself is additionally
7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// wrapped into BlindReference for sanitizing reasons.
7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
7526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
7536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static bool IsInstance(Handle<JSArray> array) {
7546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array->length() == Smi::FromInt(kSize_) &&
7555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        array->GetElementNoExceptionThrown(kSharedInfoOffset_)->IsJSValue();
7566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit SharedInfoWrapper(Handle<JSArray> array)
7596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<SharedInfoWrapper>(array) {
7606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetProperties(Handle<String> name, int start_position, int end_position,
7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     Handle<SharedFunctionInfo> info) {
7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
7656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Handle<JSValue> info_holder = WrapInJSValue(info);
7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedInfoOffset_, info_holder);
7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> GetInfo() {
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* element = this->GetField(kSharedInfoOffset_);
7736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> value_wrapper(JSValue::cast(element));
7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<SharedFunctionInfo>::cast(raw_result);
7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSharedInfoOffset_ = 3;
7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSize_ = 4;
7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<SharedInfoWrapper>;
7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
788f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
789402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuclass FunctionInfoListener {
790402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu public:
7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener() {
7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = -1;
7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_ = 0;
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    result_ = FACTORY->NewJSArray(10);
7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
797402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionStarted(FunctionLiteral* fun) {
7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FunctionInfoWrapper info = FunctionInfoWrapper::Create();
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info.SetInitialProperties(fun->name(), fun->start_position(),
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              fun->end_position(), fun->parameter_count(),
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              current_parent_index_);
8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = len_;
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(result_, len_, info.GetJSArray());
8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_++;
806402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
807402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
808402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionDone() {
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = info.GetParentIndex();
814402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
815402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
81659151504615d929945dc59db37bf1166937748c6Steve Block  // Saves only function code, because for a script function we
81759151504615d929945dc59db37bf1166937748c6Steve Block  // may never create a SharedFunctionInfo object.
81859151504615d929945dc59db37bf1166937748c6Steve Block  void FunctionCode(Handle<Code> function_code) {
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    info.SetFunctionCode(function_code, Handle<Object>(HEAP->null_value()));
82359151504615d929945dc59db37bf1166937748c6Steve Block  }
82459151504615d929945dc59db37bf1166937748c6Steve Block
82559151504615d929945dc59db37bf1166937748c6Steve Block  // Saves full information about a function: its code, its scope info
82659151504615d929945dc59db37bf1166937748c6Steve Block  // and a SharedFunctionInfo object.
82759151504615d929945dc59db37bf1166937748c6Steve Block  void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) {
82859151504615d929945dc59db37bf1166937748c6Steve Block    if (!shared->IsSharedFunctionInfo()) {
82959151504615d929945dc59db37bf1166937748c6Steve Block      return;
83059151504615d929945dc59db37bf1166937748c6Steve Block    }
831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionInfoWrapper info =
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        FunctionInfoWrapper::cast(
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            result_->GetElementNoExceptionThrown(current_parent_index_));
83459151504615d929945dc59db37bf1166937748c6Steve Block    info.SetFunctionCode(Handle<Code>(shared->code()),
83559151504615d929945dc59db37bf1166937748c6Steve Block        Handle<Object>(shared->scope_info()));
83659151504615d929945dc59db37bf1166937748c6Steve Block    info.SetSharedFunctionInfo(shared);
83759151504615d929945dc59db37bf1166937748c6Steve Block
83859151504615d929945dc59db37bf1166937748c6Steve Block    Handle<Object> scope_info_list(SerializeFunctionScope(scope));
83959151504615d929945dc59db37bf1166937748c6Steve Block    info.SetOuterScopeInfo(scope_info_list);
84059151504615d929945dc59db37bf1166937748c6Steve Block  }
84159151504615d929945dc59db37bf1166937748c6Steve Block
84259151504615d929945dc59db37bf1166937748c6Steve Block  Handle<JSArray> GetResult() { return result_; }
84359151504615d929945dc59db37bf1166937748c6Steve Block
8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* SerializeFunctionScope(Scope* scope) {
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope handle_scope;
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<JSArray> scope_info_list = FACTORY->NewJSArray(10);
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int scope_info_length = 0;
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Saves some description of scope. It stores name and indexes of
8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // variables in the whole scope chain. Null-named slots delimit
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // scopes of this chain.
8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Scope* outer_scope = scope->outer_scope();
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (outer_scope == NULL) {
85644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return HEAP->undefined_value();
8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
8586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    do {
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ZoneList<Variable*> stack_list(outer_scope->StackLocalCount());
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ZoneList<Variable*> context_list(outer_scope->ContextLocalCount());
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      outer_scope->CollectStackAndContextLocals(&stack_list, &context_list);
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      context_list.Sort(&Variable::CompareIndex);
8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = 0; i < context_list.length(); i++) {
86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        SetElementNonStrict(scope_info_list,
86644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                            scope_info_length,
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            context_list[i]->name());
8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        SetElementNonStrict(
87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block            scope_info_list,
87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            scope_info_length,
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<Smi>(Smi::FromInt(context_list[i]->index())));
8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SetElementNonStrict(scope_info_list,
87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          scope_info_length,
87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                          Handle<Object>(HEAP->null_value()));
8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      scope_info_length++;
8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      outer_scope = outer_scope->outer_scope();
8816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } while (outer_scope != NULL);
8826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return *scope_info_list;
884402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
885402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
8866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
8876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len_;
8886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int current_parent_index_;
889402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu};
890402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
891f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
8926ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockJSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> source) {
89444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
8953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener listener;
8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> original_source = Handle<Object>(script->source());
8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*source);
90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->set_active_function_info_listener(&listener);
90144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CompileScriptForTracker(isolate, script);
90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->set_active_function_info_listener(NULL);
9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*original_source);
9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *(listener.GetResult());
9066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(array->length())->value();
9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info(
9145913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        SharedFunctionInfo::cast(array->GetElementNoExceptionThrown(i)));
9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<String> name_handle(String::cast(info->name()));
9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info_wrapper.SetProperties(name_handle, info->start_position(),
9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               info->end_position(), info);
91944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(array, i, info_wrapper.GetJSArray());
9206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor that collects all references to a particular code object,
9256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// including "CODE_TARGET" references in other code objects.
9266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It works in context of ZoneScope.
9276ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ReferenceCollectorVisitor : public ObjectVisitor {
9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
9296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit ReferenceCollectorVisitor(Code* original)
930791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    : original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) {
9316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitPointers(Object** start, Object** end) {
9346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (Object** p = start; p < end; p++) {
9356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (*p == original_) {
9366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        rvalues_.Add(p);
9376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
9386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
941791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeEntry(Address entry) {
942791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (Code::GetObjectFromEntryAddress(entry) == original_) {
943791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      code_entries_.Add(entry);
944791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
945791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
946791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
947791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeTarget(RelocInfo* rinfo) {
9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
9496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
9506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      reloc_infos_.Add(*rinfo);
9516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitDebugTarget(RelocInfo* rinfo) {
9556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitCodeTarget(rinfo);
9566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Post-visiting method that iterates over all collected references and
9596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // modifies them.
9606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Replace(Code* substitution) {
9616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < rvalues_.length(); i++) {
9626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      *(rvalues_[i]) = substitution;
9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
964791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Address substitution_entry = substitution->instruction_start();
9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < reloc_infos_.length(); i++) {
966791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      reloc_infos_[i].set_target_address(substitution_entry);
967791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
968791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    for (int i = 0; i < code_entries_.length(); i++) {
969791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Address entry = code_entries_[i];
970791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Memory::Address_at(entry) = substitution_entry;
9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
9756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Code* original_;
9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<Object**> rvalues_;
9776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<RelocInfo> reloc_infos_;
978791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ZoneList<Address> code_entries_;
9796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
9806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Finds all references to original and replaces them with substitution.
9836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReplaceCodeObject(Code* original, Code* substitution) {
98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!HEAP->InNewSpace(substitution));
9856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HeapIterator iterator;
9876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  AssertNoAllocation no_allocations_please;
9886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // A zone scope for ReferenceCollectorVisitor.
990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope scope(Isolate::Current(), DELETE_ON_EXIT);
9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ReferenceCollectorVisitor visitor(original);
9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Iterate over all roots. Stack frames may have pointer into original code,
9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // so temporary replace the pointers with offset numbers
9966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in prologue/epilogue.
9976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    HEAP->IterateStrongRoots(&visitor, VISIT_ALL);
9996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Now iterate over all pointers of all objects, including code_target
10026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // implicit pointers.
10036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    obj->Iterate(&visitor);
10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  visitor.Replace(substitution);
10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check whether the code is natural function code (not a lazy-compile stub
10126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// code).
10136ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsJSFunctionCode(Code* code) {
10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return code->kind() == Code::FUNCTION;
10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Returns true if an instance of candidate were inlined into function's code.
1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) {
1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_gc;
1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* data =
1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      DeoptimizationInputData::cast(function->code()->deoptimization_data());
1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (data == HEAP->empty_fixed_array()) return false;
1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  FixedArray* literals = data->LiteralArray();
1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int inlined_count = data->InlinedFunctionCount()->value();
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < inlined_count; ++i) {
1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* inlined = JSFunction::cast(literals->get(i));
1034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (inlined->shared() == candidate) return true;
1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass DependentFunctionsDeoptimizingVisitor : public OptimizedFunctionVisitor {
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit DependentFunctionsDeoptimizingVisitor(
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      SharedFunctionInfo* function_info)
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : function_info_(function_info) {}
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void EnterContext(Context* context) {
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void VisitFunction(JSFunction* function) {
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->shared() == function_info_ ||
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        IsInlined(function, function_info_)) {
1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Deoptimizer::DeoptimizeFunction(function);
1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void LeaveContext(Context* context) {
1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedFunctionInfo* function_info_;
1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) {
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DependentFunctionsDeoptimizingVisitor visitor(function_info);
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Deoptimizer::VisitAllOptimizedFunctions(&visitor);
1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10735913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::ReplaceFunctionCode(
10745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Handle<JSArray> new_compile_info_array,
10755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Handle<JSArray> shared_info_array) {
10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
107944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->ThrowIllegalOperation();
10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
10866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->EnsureHeapIsIterable();
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(shared_info->code())) {
10908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<Code> code = compile_info_wrapper.GetFunctionCode();
10918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ReplaceCodeObject(shared_info->code(), *code);
1092756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> code_scope_info =  compile_info_wrapper.GetCodeScopeInfo();
1093756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (code_scope_info->IsFixedArray()) {
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
1095756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (shared_info->debug_info()->IsDebugInfo()) {
10996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> new_original_code =
110144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        FACTORY->CopyCode(compile_info_wrapper.GetFunctionCode());
11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    debug_info->set_original_code(*new_original_code);
11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int start_position = compile_info_wrapper.GetStartPosition();
11068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int end_position = compile_info_wrapper.GetEndPosition();
11078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  shared_info->set_start_position(start_position);
11088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  shared_info->set_end_position(end_position);
11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_construct_stub(
111144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->builtins()->builtin(
111244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Builtins::kJSConstructStubGeneric));
11136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizeDependentFunctions(*shared_info);
111544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->compilation_cache()->Remove(shared_info);
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
111744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->undefined_value();
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochMaybeObject* LiveEdit::FunctionSourceUpdated(
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<JSArray> shared_info_array) {
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HandleScope scope;
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
112644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->ThrowIllegalOperation();
1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedInfoWrapper shared_info_wrapper(shared_info_array);
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizeDependentFunctions(*shared_info);
113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->compilation_cache()->Remove(shared_info);
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
113544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->undefined_value();
11366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 Handle<Object> script_handle) {
11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info =
11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_script(*script_handle);
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->compilation_cache()->Remove(shared_info);
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// For a script text change (defined as position_change_array), translates
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// position in unchanged text to position in changed text.
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Text change is a set of non-overlapping regions in text, that have changed
11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// their contents and length. It is specified as array of groups of 3 numbers:
11536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (change_begin, change_end, change_end_new_position).
11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Each group describes a change in text; groups are sorted by change_begin.
11556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Only position in text beyond any changes may be successfully translated.
11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// If a positions is inside some region that changed, result is currently
11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// undefined.
11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic int TranslatePosition(int original_position,
11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             Handle<JSArray> position_change_array) {
11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int position_diff = 0;
11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(position_change_array->length())->value();
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): binary search may be used here
11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i += 3) {
11645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    Object* element = position_change_array->GetElementNoExceptionThrown(i);
11655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_start = Smi::cast(element)->value();
11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (original_position < chunk_start) {
11676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11695913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    element = position_change_array->GetElementNoExceptionThrown(i + 1);
11705913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_end = Smi::cast(element)->value();
11716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Position mustn't be inside a chunk.
11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(original_position >= chunk_end);
11735913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    element = position_change_array->GetElementNoExceptionThrown(i + 2);
11745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    int chunk_changed_end = Smi::cast(element)->value();
11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    position_diff = chunk_changed_end - chunk_end;
11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return original_position + position_diff;
11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Auto-growing buffer for writing relocation info code section. This buffer
11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// is a simplified version of buffer from Assembler. Unlike Assembler, this
11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// class is platform-independent and it works without dealing with instructions.
11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// As specified by RelocInfo format, the buffer is filled in reversed order:
11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from upper to lower addresses.
11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It uses NewArray/DeleteArray for memory management.
11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass RelocInfoBuffer {
11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer(int buffer_initial_capicity, byte* pc) {
11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = buffer_initial_capicity + kBufferGap;
11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = NewArray<byte>(buffer_size_);
11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc);
11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~RelocInfoBuffer() {
11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // As specified by RelocInfo format, the buffer is filled in reversed order:
12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // from upper to lower addresses.
12026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Write(const RelocInfo* rinfo) {
12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) {
12046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Grow();
12056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Write(rinfo);
12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> GetResult() {
12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Return the bytes from pos up to end of buffer.
12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int result_size =
12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer_.pos());
12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Vector<byte>(reloc_info_writer_.pos(), result_size);
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
12176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Grow() {
12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Compute new buffer size.
12196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int new_buffer_size;
12206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_size_ < 2 * KB) {
12216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 4 * KB;
12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 2 * buffer_size_;
12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Some internal data structures overflow for very large buffers,
12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // they must ensure that kMaximalBufferSize is not too large.
12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (new_buffer_size > kMaximalBufferSize) {
12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer");
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up new buffer.
12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    byte* new_buffer = NewArray<byte>(new_buffer_size);
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Copy the data.
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int curently_used_size =
12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>(buffer_ + buffer_size_ - reloc_info_writer_.pos());
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memmove(new_buffer + new_buffer_size - curently_used_size,
12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            reloc_info_writer_.pos(), curently_used_size);
12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        new_buffer + new_buffer_size - curently_used_size,
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        reloc_info_writer_.last_pc());
12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = new_buffer;
12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = new_buffer_size;
12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoWriter reloc_info_writer_;
12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  byte* buffer_;
12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int buffer_size_;
12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kBufferGap = RelocInfoWriter::kMaxSize;
12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kMaximalBufferSize = 512*MB;
12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Patch positions in code (changes relocation info section) and possibly
12586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// returns new instance of code.
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Handle<Code> PatchPositionsInCode(
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<Code> code,
12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> position_change_array) {
12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer buffer_writer(code->relocation_size(),
12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                code->instruction_start());
12656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
12676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    AssertNoAllocation no_allocations_please;
12686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (RelocIterator it(*code); !it.done(); it.next()) {
12696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      RelocInfo* rinfo = it.rinfo();
12706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (RelocInfo::IsPosition(rinfo->rmode())) {
12716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int position = static_cast<int>(rinfo->data());
12726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int new_position = TranslatePosition(position,
12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (position != new_position) {
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position, NULL);
12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          buffer_writer.Write(&info_copy);
12776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          continue;
12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
12806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      buffer_writer.Write(it.rinfo());
12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> buffer = buffer_writer.GetResult();
12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (buffer.length() == code->relocation_size()) {
12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Simply patch relocation area of code.
12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memcpy(code->relocation_start(), buffer.start(), buffer.length());
12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return code;
12906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Relocation info section now has different size. We cannot simply
12926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // rewrite it inside code object. Instead we have to create a new
12936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // code object.
129444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<Code> result(FACTORY->CopyCode(code, buffer));
12956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13005913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::PatchFunctionPositions(
13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
130444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return Isolate::Current()->ThrowIllegalOperation();
13056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int old_function_start = info->start_position();
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int new_function_start = TranslatePosition(old_function_start,
13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
13138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int new_function_end = TranslatePosition(info->end_position(),
13148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                           position_change_array);
13158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int new_function_token_pos =
13168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      TranslatePosition(info->function_token_position(), position_change_array);
13176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  info->set_start_position(new_function_start);
13198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  info->set_end_position(new_function_end);
13208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  info->set_function_token_position(new_function_token_pos);
13216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->EnsureHeapIsIterable();
13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(info->code())) {
13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Patch relocation info section of the code.
13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()),
13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                     position_change_array);
13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (*patched_code != info->code()) {
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Replace all references to the code across the heap. In particular,
13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // some stubs may refer to this code and this code may be being executed
13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // on stack (it is safe to substitute the code object on stack, because
13326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // we only change the structure of rinfo and leave instructions
13336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // untouched).
13346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReplaceCodeObject(info->code(), *patched_code);
13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
133844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->undefined_value();
13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Script> CreateScriptCopy(Handle<Script> original) {
13436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> original_source(String::cast(original->source()));
13446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
134544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Script> copy = FACTORY->NewScript(original_source);
13466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_name(original->name());
13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_line_offset(original->line_offset());
13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_column_offset(original->column_offset());
13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_data(original->data());
13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_type(original->type());
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_context_data(original->context_data());
13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_compilation_type(original->compilation_type());
13546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_shared(original->eval_from_shared());
13556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_instructions_offset(
13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      original->eval_from_instructions_offset());
13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return copy;
13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13626ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LiveEdit::ChangeScriptSource(Handle<Script> original_script,
13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> new_source,
13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<Object> old_script_name) {
13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> old_script_object;
13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (old_script_name->IsString()) {
13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Script> old_script = CreateScriptCopy(original_script);
13686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script->set_name(String::cast(*old_script_name));
13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script_object = old_script;
137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate::Current()->debugger()->OnAfterCompile(
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        old_script, Debugger::SEND_WHEN_DEBUGGING);
13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
137344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    old_script_object = Handle<Object>(HEAP->null_value());
13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  original_script->set_source(*new_source);
13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Drop line ends so that they will be recalculated.
137944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  original_script->set_line_ends(HEAP->undefined_value());
13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *old_script_object;
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::ReplaceRefToNestedFunction(
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> parent_function_wrapper,
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> orig_function_wrapper,
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> subst_function_wrapper) {
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> parent_shared =
13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(parent_function_wrapper));
13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> orig_shared =
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(orig_function_wrapper));
13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> subst_shared =
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(subst_function_wrapper));
13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
14006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (it.rinfo()->target_object() == *orig_shared) {
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        it.rinfo()->set_target_object(*subst_shared);
14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check an activation against list of functions. If there is a function
14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that matches, its status in result array is changed to status argument value.
14106ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CheckActivation(Handle<JSArray> shared_info_array,
1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            Handle<JSArray> result,
1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                            StackFrame* frame,
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FunctionPatchabilityStatus status) {
1414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!frame->is_java_script()) return false;
1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<JSFunction> function(
1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JSFunction::cast(JavaScriptFrame::cast(frame)->function()));
1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
14215913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck    JSValue* wrapper =
14225913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck        JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i));
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> shared(
14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SharedFunctionInfo::cast(wrapper->value()));
14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->shared() == *shared || IsInlined(*function, *shared)) {
142744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SetElementNonStrict(result, i, Handle<Smi>(Smi::FromInt(status)));
14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
14306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Iterates over handler chain and removes all elements that are inside
14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames being dropped.
14376ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool FixTryCatchHandler(StackFrame* top_frame,
14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               StackFrame* bottom_frame) {
14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* pointer_address =
144044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &Memory::Address_at(Isolate::Current()->get_address_from_id(
1441589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          Isolate::kHandlerAddress));
14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < top_frame->sp()) {
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
14456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* above_frame_address = pointer_address;
14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < bottom_frame->fp()) {
14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool change = *above_frame_address != *pointer_address;
14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  *above_frame_address = *pointer_address;
14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return change;
14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Removes specified range of frames from stack. There may be 1 or more
14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames in range. Anyway the bottom frame is restarted rather than dropped,
14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// and therefore has to be a JavaScript frame.
14596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Returns error message or NULL.
14606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropFrames(Vector<StackFrame*> frames,
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              int top_frame_index,
14628defd9ff6930b4e24729971a61cf7469daf119beSteve Block                              int bottom_js_frame_index,
1463bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Debug::FrameDropMode* mode,
1464bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Object*** restarter_frame_function_pointer) {
1465756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (!Debug::kFrameDropperSupported) {
14668defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return "Stack manipulations are not supported in this architecture.";
14678defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
14688defd9ff6930b4e24729971a61cf7469daf119beSteve Block
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* pre_top_frame = frames[top_frame_index - 1];
14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* top_frame = frames[top_frame_index];
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* bottom_js_frame = frames[bottom_js_frame_index];
14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(bottom_js_frame->is_java_script());
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the nature of the top frame.
14768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Isolate* isolate = Isolate::Current();
14778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Code* pre_top_frame_code = pre_top_frame->LookupCode();
147844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (pre_top_frame_code->is_inline_cache_stub() &&
147944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      pre_top_frame_code->ic_state() == DEBUG_BREAK) {
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop inline cache calls.
14818defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
148244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (pre_top_frame_code ==
14838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             isolate->debug()->debug_break_slot()) {
14848defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // OK, we can drop debug break slot.
14858defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
148644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (pre_top_frame_code ==
14878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      isolate->builtins()->builtin(
148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Builtins::kFrameDropper_LiveEdit)) {
14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop our own code.
14908defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
1491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } else if (pre_top_frame_code ==
1492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate->builtins()->builtin(Builtins::kReturn_DebugBreak)) {
1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    *mode = Debug::FRAME_DROPPED_IN_RETURN_CALL;
149444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  } else if (pre_top_frame_code->kind() == Code::STUB &&
149544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      pre_top_frame_code->major_key()) {
14968defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Entry from our unit tests, it's fine, we support this case.
14978defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Unknown structure of stack above changing function";
15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_top = top_frame->sp();
15036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_bottom = bottom_js_frame->fp()
15046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      - Debug::kFrameDropperFrameSize * kPointerSize  // Size of the new frame.
15056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      + kPointerSize;  // Bigger address end is exclusive.
15066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (unused_stack_top > unused_stack_bottom) {
15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Not enough space for frame dropper frame";
15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Committing now. After this point we should return only NULL value.
15126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FixTryCatchHandler(pre_top_frame, bottom_js_frame);
15146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Make sure FixTryCatchHandler is idempotent.
15156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
151744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Code> code = Isolate::Current()->builtins()->FrameDropper_LiveEdit();
15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  top_frame->set_pc(code->entry());
15196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  pre_top_frame->SetCallerFp(bottom_js_frame->fp());
15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1521bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  *restarter_frame_function_pointer =
1522bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      Debug::SetUpFrameDropperFrame(bottom_js_frame, code);
1523bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1524bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((**restarter_frame_function_pointer)->IsJSFunction());
15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (Address a = unused_stack_top;
15276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a < unused_stack_bottom;
15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a += kPointerSize) {
15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Memory::Object_at(a) = Smi::FromInt(0);
15306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
15336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDropableFrame(StackFrame* frame) {
15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return !frame->is_exit();
15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
15396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Fills result array with statuses of functions. Modifies the stack
15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// removing all listed function if possible and if do_drop is true.
15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropActivationsInActiveThread(
15436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
1544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Isolate* isolate = Isolate::Current();
1545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Debug* debug = isolate->debug();
1546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope scope(isolate, DELETE_ON_EXIT);
15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<StackFrame*> frames = CreateStackMap();
15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(shared_info_array->length())->value();
15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int top_frame_index = -1;
15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_index = 0;
15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
155544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (frame->id() == debug->break_frame_id()) {
15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      top_frame_index = frame_index;
15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
15616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We are still above break_frame. It is not a target frame,
15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // it is a problem.
15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return "Debugger mark-up on stack is not found";
15646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_frame_index == -1) {
15686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We haven't found break frame, but no function is blocking us anyway.
15696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
15706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool target_frame_found = false;
15736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int bottom_js_frame_index = top_frame_index;
15746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool c_code_found = false;
15756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
15776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
15786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!IsDropableFrame(frame)) {
15796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      c_code_found = true;
15806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
15816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
15836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
15846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      target_frame_found = true;
15856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      bottom_js_frame_index = frame_index;
15866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
15876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
15886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
15896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (c_code_found) {
15906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // There is a C frames on stack. Check that there are no target frames
15916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // below them.
15926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (; frame_index < frames.length(); frame_index++) {
15936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StackFrame* frame = frames[frame_index];
15946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (frame->is_java_script()) {
15956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (CheckActivation(shared_info_array, result, frame,
15966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
15976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // Cannot drop frame under C frames.
15986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          return NULL;
15996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
16006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
16016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
16026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!do_drop) {
16056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We are in check-only mode.
16066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
16076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!target_frame_found) {
16106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Nothing to drop.
16116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
16126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16148defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED;
1615bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object** restarter_frame_function_pointer = NULL;
16166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message = DropFrames(frames, top_frame_index,
1617bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         bottom_js_frame_index, &drop_mode,
1618bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         &restarter_frame_function_pointer);
16196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
16216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return error_message;
16226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Adjust break_frame after some frames has been dropped.
16256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame::Id new_id = StackFrame::NO_ID;
16266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
16276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
16286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_id = frames[i]->id();
16296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
16306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
16316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
163244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  debug->FramesHaveBeenDropped(new_id, drop_mode,
1633bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                               restarter_frame_function_pointer);
16346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Replace "blocked on active" with "replaced on active" status.
16366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i++) {
16376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (result->GetElement(i) ==
16386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
163980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Handle<Object> replaced(
164080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
164144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      SetElementNonStrict(result, i, replaced);
16426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
16436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
16456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
16466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16486ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass InactiveThreadActivationsChecker : public ThreadVisitor {
16496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
16506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
16516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   Handle<JSArray> result)
16526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : shared_info_array_(shared_info_array), result_(result),
16536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_blocked_functions_(false) {
16546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
16568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
16576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      has_blocked_functions_ |= CheckActivation(
16586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          shared_info_array_, result_, it.frame(),
16596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
16606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
16616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool HasBlockedFunctions() {
16636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return has_blocked_functions_;
16646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
16676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> shared_info_array_;
16686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
16696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool has_blocked_functions_;
16706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
16716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16736ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CheckAndDropActivations(
16746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, bool do_drop) {
16756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
16766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
167744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSArray> result = FACTORY->NewJSArray(len);
16786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fill the default values.
16806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
168144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(
168244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        result,
168344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        i,
168444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
16856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First check inactive threads. Fail if some functions are blocked there.
16896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
16906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                            result);
169144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate::Current()->thread_manager()->IterateArchivedThreads(
169244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      &inactive_threads_checker);
16936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (inactive_threads_checker.HasBlockedFunctions()) {
16946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
16956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
16966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
16976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Try to drop activations from the current stack.
16986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message =
16996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      DropActivationsInActiveThread(shared_info_array, result, do_drop);
17006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
17016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Add error message as an array extra element.
17026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Vector<const char> vector_message(error_message, StrLength(error_message));
170344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<String> str = FACTORY->NewStringFromAscii(vector_message);
170444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SetElementNonStrict(result, len, str);
17056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
17066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
17076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
171044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockLiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
171144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 FunctionLiteral* fun)
171244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate) {
171344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate_->active_function_info_listener() != NULL) {
171444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate_->active_function_info_listener()->FunctionStarted(fun);
1715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1716402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
17176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1719402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::~LiveEditFunctionTracker() {
172044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate_->active_function_info_listener() != NULL) {
172144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate_->active_function_info_listener()->FunctionDone();
1722402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1723402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
17246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17266ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
17276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
172844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate_->active_function_info_listener() != NULL) {
172944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope());
1730402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1731402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
17326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17346ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
173544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->active_function_info_listener()->FunctionCode(code);
1736402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
17376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
173944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
174044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return isolate->active_function_info_listener() != NULL;
1741402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1742402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
17436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else  // ENABLE_DEBUGGER_SUPPORT
17456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// This ifdef-else-endif section provides working or stub implementation of
17476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// LiveEditFunctionTracker.
174844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockLiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
174944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                 FunctionLiteral* fun) {
17506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17536ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::~LiveEditFunctionTracker() {
17546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
17586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
17596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
17636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
17676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
17686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
17696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // ENABLE_DEBUGGER_SUPPORT
17716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
17736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1774402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} }  // namespace v8::internal
1775