liveedit.cc revision 80d68eab642096c1a48b6474d6ec33064b0ad1f5
1402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Copyright 2010 the V8 project authors. All rights reserved.
2402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Redistribution and use in source and binary forms, with or without
3402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// modification, are permitted provided that the following conditions are
4402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// met:
5402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//
6402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//     * Redistributions of source code must retain the above copyright
7402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       notice, this list of conditions and the following disclaimer.
8402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//     * Redistributions in binary form must reproduce the above
9402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       copyright notice, this list of conditions and the following
10402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       disclaimer in the documentation and/or other materials provided
11402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       with the distribution.
12402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//     * Neither the name of Google Inc. nor the names of its
13402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       contributors may be used to endorse or promote products derived
14402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//       from this software without specific prior written permission.
15402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu//
16402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
28402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
29402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "v8.h"
30402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
31402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "liveedit.h"
32402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "compiler.h"
33402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "oprofile-agent.h"
34402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "scopes.h"
35756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#include "scopeinfo.h"
36402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "global-handles.h"
37402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "debug.h"
386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "memory.h"
39402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
40402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace v8 {
41402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace internal {
42402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
43402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT
456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// A simple implementation of dynamic programming algorithm. It solves
486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the problem of finding the difference of 2 arrays. It uses a table of results
496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// of subproblems. Each cell contains a number together with 2-bit flag
506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that helps building the chunk list.
516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass Differencer {
526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit Differencer(Comparator::Input* input)
546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : input_(input), len1_(input->getLength1()), len2_(input->getLength2()) {
556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = NewArray<int>(len1_ * len2_);
566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~Differencer() {
586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Initialize() {
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int array_size = len1_ * len2_;
636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < array_size; i++) {
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      buffer_[i] = kEmptyCellValue;
656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Makes sure that result for the full problem is calculated and stored
696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in the table together with flags showing a path through subproblems.
706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void FillTable() {
716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CompareUpToTail(0, 0);
726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SaveResult(Comparator::Output* chunk_writer) {
756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ResultWriter writer(chunk_writer);
766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1 = 0;
786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2 = 0;
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    while (true) {
806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (pos1 < len1_) {
816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (pos2 < len2_) {
826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Direction dir = get_direction(pos1, pos2);
836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          switch (dir) {
846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case EQ:
856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.eq();
866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos1++;
876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos2++;
886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP1:
906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.skip1(1);
916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos1++;
926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP2:
946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            case SKIP_ANY:
956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              writer.skip2(1);
966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              pos2++;
976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              break;
986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            default:
996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              UNREACHABLE();
1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          writer.skip1(len1_ - pos1);
1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (len2_ != pos2) {
1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          writer.skip2(len2_ - pos2);
1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        break;
1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    writer.close();
1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comparator::Input* input_;
1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int* buffer_;
1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len1_;
1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len2_;
1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  enum Direction {
1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    EQ = 0,
1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP1,
1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP2,
1256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SKIP_ANY,
1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    MAX_DIRECTION_FLAG_VALUE = SKIP_ANY
1286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
1296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Computes result for a subtask and optionally caches it in the buffer table.
1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // All results values are shifted to make space for flags in the lower bits.
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int CompareUpToTail(int pos1, int pos2) {
1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (pos1 < len1_) {
1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (pos2 < len2_) {
1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int cached_res = get_value4(pos1, pos2);
1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (cached_res == kEmptyCellValue) {
1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Direction dir;
1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          int res;
1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (input_->equals(pos1, pos2)) {
1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            res = CompareUpToTail(pos1 + 1, pos2 + 1);
1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            dir = EQ;
1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          } else {
1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int res1 = CompareUpToTail(pos1 + 1, pos2) +
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                (1 << kDirectionSizeBits);
1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            int res2 = CompareUpToTail(pos1, pos2 + 1) +
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                (1 << kDirectionSizeBits);
1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            if (res1 == res2) {
1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res1;
1496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP_ANY;
1506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else if (res1 < res2) {
1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res1;
1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP1;
1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            } else {
1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              res = res2;
1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block              dir = SKIP2;
1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            }
1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          set_value4_and_dir(pos1, pos2, res, dir);
1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          cached_res = res;
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return cached_res;
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        return (len1_ - pos1) << kDirectionSizeBits;
1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return (len2_ - pos2) << kDirectionSizeBits;
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  inline int& get_cell(int i1, int i2) {
1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return buffer_[i1 + i2 * len1_];
1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Each cell keeps a value plus direction. Value is multiplied by 4.
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void set_value4_and_dir(int i1, int i2, int value4, Direction dir) {
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT((value4 & kDirectionMask) == 0);
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    get_cell(i1, i2) = value4 | dir;
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int get_value4(int i1, int i2) {
1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return get_cell(i1, i2) & (kMaxUInt32 ^ kDirectionMask);
1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Direction get_direction(int i1, int i2) {
1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return static_cast<Direction>(get_cell(i1, i2) & kDirectionMask);
1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kDirectionSizeBits = 2;
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kDirectionMask = (1 << kDirectionSizeBits) - 1;
1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEmptyCellValue = -1 << kDirectionSizeBits;
1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // This method only holds static assert statement (unfortunately you cannot
1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // place one in class scope).
1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void StaticAssertHolder() {
1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    STATIC_ASSERT(MAX_DIRECTION_FLAG_VALUE < (1 << kDirectionSizeBits));
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  class ResultWriter {
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   public:
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    explicit ResultWriter(Comparator::Output* chunk_writer)
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        : chunk_writer_(chunk_writer), pos1_(0), pos2_(0),
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          pos1_begin_(-1), pos2_begin_(-1), has_open_chunk_(false) {
2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void eq() {
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FlushChunk();
2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos1_++;
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos2_++;
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void skip1(int len1) {
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StartChunk();
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos1_ += len1;
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void skip2(int len2) {
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StartChunk();
2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pos2_ += len2;
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void close() {
2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      FlushChunk();
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   private:
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Comparator::Output* chunk_writer_;
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1_;
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2_;
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos1_begin_;
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int pos2_begin_;
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool has_open_chunk_;
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void StartChunk() {
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (!has_open_chunk_) {
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        pos1_begin_ = pos1_;
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        pos2_begin_ = pos2_;
2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_open_chunk_ = true;
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void FlushChunk() {
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (has_open_chunk_) {
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        chunk_writer_->AddChunk(pos1_begin_, pos2_begin_,
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                pos1_ - pos1_begin_, pos2_ - pos2_begin_);
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_open_chunk_ = false;
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Comparator::CalculateDifference(Comparator::Input* input,
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Comparator::Output* result_writer) {
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Differencer differencer(input);
2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.Initialize();
2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.FillTable();
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  differencer.SaveResult(result_writer);
2536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CompareSubstrings(Handle<String> s1, int pos1,
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              Handle<String> s2, int pos2, int len) {
2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static StringInputBuffer buf1;
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static StringInputBuffer buf2;
2606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf1.Reset(*s1);
2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf1.Seek(pos1);
2626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf2.Reset(*s2);
2636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  buf2.Seek(pos2);
2646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(buf1.has_more() && buf2.has_more());
2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buf1.GetNext() != buf2.GetNext()) {
2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
2716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps raw n-elements line_ends array as a list of n+1 lines. The last line
2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// never has terminating new line character.
2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineEndsWrapper {
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit LineEndsWrapper(Handle<String> string)
2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : ends_array_(CalculateLineEnds(string, false)),
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        string_len_(string->length()) {
2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int length() {
2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return ends_array_->length() + 1;
2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Returns start for any line including start of the imaginary line after
2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the last line.
2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineStart(int index) {
2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == 0) {
2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return 0;
2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetLineEnd(index - 1);
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetLineEnd(int index) {
2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (index == ends_array_->length()) {
2966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // End of the last line is always an end of the whole string.
2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // If the string ends with a new line character, the last line is an
2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // empty string after this character.
2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return string_len_;
3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return GetPosAfterNewLine(index);
3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<FixedArray> ends_array_;
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int string_len_;
3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetPosAfterNewLine(int index) {
3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(ends_array_->get(index))->value() + 1;
3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents 2 strings as 2 arrays of lines.
3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineArrayCompareInput : public Comparator::Input {
3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : s1_(s1), s2_(s2), line_ends1_(line_ends1), line_ends2_(line_ends2) {
3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int getLength1() {
3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return line_ends1_.length();
3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int getLength2() {
3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return line_ends2_.length();
3276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool equals(int index1, int index2) {
3296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start1 = line_ends1_.GetLineStart(index1);
3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_start2 = line_ends2_.GetLineStart(index2);
3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end1 = line_ends1_.GetLineEnd(index1);
3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int line_end2 = line_ends2_.GetLineEnd(index2);
3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len1 = line_end1 - line_start1;
3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int len2 = line_end2 - line_start2;
3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (len1 != len2) {
3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return CompareSubstrings(s1_, line_start1, s2_, line_start2, len1);
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s1_;
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> s2_;
3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Stores compare result in JSArray. Each chunk is stored as 3 array elements:
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (pos1_begin, pos1_end, pos2_end).
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineArrayCompareOutput : public Comparator::Output {
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareOutput(LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : array_(Factory::NewJSArray(10)), current_size_(0),
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        line_ends1_(line_ends1), line_ends2_(line_ends2) {
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos1 = line_ends1_.GetLineStart(line_pos1);
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_pos2 = line_ends2_.GetLineStart(line_pos2);
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, current_size_, Handle<Object>(Smi::FromInt(char_pos1)));
3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, current_size_ + 1,
3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Handle<Object>(Smi::FromInt(char_pos1 + char_len1)));
3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, current_size_ + 2,
3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Handle<Object>(Smi::FromInt(char_pos2 + char_len2)));
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_size_ += 3;
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetResult() {
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array_;
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> array_;
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int current_size_;
3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1_;
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2_;
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CompareStringsLinewise(Handle<String> s1,
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                 Handle<String> s2) {
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends1(s1);
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineEndsWrapper line_ends2(s2);
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LineArrayCompareOutput output(line_ends1, line_ends2);
3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Comparator::CalculateDifference(&input, &output);
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return output.GetResult();
3956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void CompileScriptForTracker(Handle<Script> script) {
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const bool is_eval = false;
4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const bool is_global = true;
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): support extensions.
4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Extension* extension = NULL;
4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  PostponeInterruptsScope postpone;
4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Only allow non-global compiles for eval.
4076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(is_eval || is_global);
4086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Build AST.
4106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ScriptDataImpl* pre_data = NULL;
4116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionLiteral* lit = MakeAST(is_global, script, extension, pre_data);
4126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check for parse errors.
4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (lit == NULL) {
4156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(Top::has_pending_exception());
4166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return;
4176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Compile the code.
4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompilationInfo info(lit, script, is_eval);
4216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  LiveEditFunctionTracker tracker(lit);
4236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> code = MakeCodeForLiveEdit(&info);
4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check for stack-overflow exceptions.
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (code.is_null()) {
4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Top::StackOverflow();
4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return;
4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  tracker.RecordRootFunctionInfo(code);
4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Unwraps JSValue object, returning its field "value"
4346ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
4356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Handle<Object>(jsValue->value());
4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps any object into a OpaqueReference, that will hide the object
4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript.
4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<JSValue> WrapInJSValue(Object* object) {
4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSFunction> constructor = Top::opaque_reference_function();
4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSValue> result =
4436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<JSValue>::cast(Factory::NewJSObject(constructor));
4446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  result->set_value(object);
4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
4466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Simple helper class that creates more or less typed structures over
4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// JSArray object. This is an adhoc method of passing structures from C++
4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// to JavaScript.
4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename S>
4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass JSArrayBasedStruct {
4536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
4546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S Create() {
4556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> array = Factory::NewJSArray(S::kSize_);
4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array);
4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static S cast(Object* object) {
4596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    JSArray* array = JSArray::cast(object);
4606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> array_handle(array);
4616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return S(array_handle);
4626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetJSArray() {
4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array_;
4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected:
4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetField(int field_position, Handle<Object> value) {
4706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, field_position, value);
4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSmiValueField(int field_position, int value) {
4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value)));
4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* GetField(int field_position) {
4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array_->GetElement(field_position);
4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetSmiValueField(int field_position) {
4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* res = GetField(field_position);
4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Smi::cast(res)->value();
4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> array_;
4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents some function compilation details. This structure will be used
4886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript. It contains Code object, which is kept wrapped
4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// into a BlindReference for sanitizing reasons.
4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit FunctionInfoWrapper(Handle<JSArray> array)
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetInitialProperties(Handle<String> name, int start_position,
4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            int end_position, int param_num, int parent_index) {
4976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
5006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
5016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParamNumOffset_, param_num);
5026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kParentIndexOffset_, parent_index);
5036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
504756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetFunctionCode(Handle<Code> function_code,
505756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      Handle<Object> code_scope_info) {
506756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<JSValue> code_wrapper = WrapInJSValue(*function_code);
507756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeOffset_, code_wrapper);
508756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
509756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<JSValue> scope_wrapper = WrapInJSValue(*code_scope_info);
510756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kCodeScopeInfoOffset_, scope_wrapper);
5116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
512756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SetOuterScopeInfo(Handle<Object> scope_info_array) {
513756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    this->SetField(kOuterScopeInfoOffset_, scope_info_array);
5146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) {
5166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> info_holder = WrapInJSValue(*info);
5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedFunctionInfoOffset_, info_holder);
5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetParentIndex() {
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kParentIndexOffset_);
5216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> GetFunctionCode() {
5236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
5246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        JSValue::cast(this->GetField(kCodeOffset_))));
5256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<Code>::cast(raw_result);
5266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
527756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  Handle<Object> GetCodeScopeInfo() {
528756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
529756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        JSValue::cast(this->GetField(kCodeScopeInfoOffset_))));
530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return raw_result;
531756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetStartPosition() {
5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kStartPositionOffset_);
5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int GetEndPosition() {
5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return this->GetSmiValueField(kEndPositionOffset_);
5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
5406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
5426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kParamNumOffset_ = 3;
5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kCodeOffset_ = 4;
545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kCodeScopeInfoOffset_ = 5;
546756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kOuterScopeInfoOffset_ = 6;
547756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kParentIndexOffset_ = 7;
548756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSharedFunctionInfoOffset_ = 8;
549756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static const int kSize_ = 9;
5506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<FunctionInfoWrapper>;
5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps SharedFunctionInfo along with some of its fields for passing it
5556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// back to JavaScript. SharedFunctionInfo object itself is additionally
5566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// wrapped into BlindReference for sanitizing reasons.
5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static bool IsInstance(Handle<JSArray> array) {
5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return array->length() == Smi::FromInt(kSize_) &&
5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        array->GetElement(kSharedInfoOffset_)->IsJSValue();
5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit SharedInfoWrapper(Handle<JSArray> array)
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : JSArrayBasedStruct<SharedInfoWrapper>(array) {
5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void SetProperties(Handle<String> name, int start_position, int end_position,
5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                     Handle<SharedFunctionInfo> info) {
5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kFunctionNameOffset_, name);
5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> info_holder = WrapInJSValue(*info);
5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetField(kSharedInfoOffset_, info_holder);
5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kStartPositionOffset_, start_position);
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this->SetSmiValueField(kEndPositionOffset_, end_position);
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> GetInfo() {
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* element = this->GetField(kSharedInfoOffset_);
5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> value_wrapper(JSValue::cast(element));
5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Handle<SharedFunctionInfo>::cast(raw_result);
5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kFunctionNameOffset_ = 0;
5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kStartPositionOffset_ = 1;
5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kEndPositionOffset_ = 2;
5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSharedInfoOffset_ = 3;
5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kSize_ = 4;
5906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  friend class JSArrayBasedStruct<SharedInfoWrapper>;
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
594402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuclass FunctionInfoListener {
595402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu public:
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener() {
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = -1;
5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_ = 0;
5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    result_ = Factory::NewJSArray(10);
6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionStarted(FunctionLiteral* fun) {
6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FunctionInfoWrapper info = FunctionInfoWrapper::Create();
6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info.SetInitialProperties(fun->name(), fun->start_position(),
6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              fun->end_position(), fun->num_parameters(),
6076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              current_parent_index_);
6086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = len_;
6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(result_, len_, info.GetJSArray());
6106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    len_++;
611402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
612402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
613402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionDone() {
6146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope scope;
6156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FunctionInfoWrapper info =
6166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_));
6176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current_parent_index_ = info.GetParentIndex();
618402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// TODO(LiveEdit): Move private method below.
6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//     This private section was created here to avoid moving the function
6226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block//      to keep already complex diff simpler.
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Object* SerializeFunctionScope(Scope* scope) {
6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    HandleScope handle_scope;
6266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> scope_info_list = Factory::NewJSArray(10);
6286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int scope_info_length = 0;
6296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Saves some description of scope. It stores name and indexes of
6316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // variables in the whole scope chain. Null-named slots delimit
6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // scopes of this chain.
6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Scope* outer_scope = scope->outer_scope();
6346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (outer_scope == NULL) {
6356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return Heap::undefined_value();
6366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    do {
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ZoneList<Variable*> list(10);
6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      outer_scope->CollectUsedVariables(&list);
6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int j = 0;
6416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 0; i < list.length(); i++) {
6426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Variable* var1 = list[i];
6436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Slot* slot = var1->slot();
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (slot != NULL && slot->type() == Slot::CONTEXT) {
6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (j != i) {
6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            list[j] = var1;
6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          j++;
6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Sort it.
6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int k = 1; k < j; k++) {
6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int l = k;
6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        for (int m = k + 1; m < j; m++) {
6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          if (list[l]->slot()->index() > list[m]->slot()->index()) {
6576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            l = m;
6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          }
6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        list[k] = list[l];
6616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      for (int i = 0; i < j; i++) {
6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SetElement(scope_info_list, scope_info_length, list[i]->name());
6646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
6656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SetElement(scope_info_list, scope_info_length,
6666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                   Handle<Smi>(Smi::FromInt(list[i]->slot()->index())));
6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        scope_info_length++;
6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      SetElement(scope_info_list, scope_info_length,
6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                 Handle<Object>(Heap::null_value()));
6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      scope_info_length++;
6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      outer_scope = outer_scope->outer_scope();
6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } while (outer_scope != NULL);
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return *scope_info_list;
677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
678402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Saves only function code, because for a script function we
6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // may never create a SharedFunctionInfo object.
682402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void FunctionCode(Handle<Code> function_code) {
6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FunctionInfoWrapper info =
6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_));
685756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value()));
6866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
6876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
6886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Saves full information about a function: its code, its scope info
6896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and a SharedFunctionInfo object.
6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) {
6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!shared->IsSharedFunctionInfo()) {
6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return;
6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    FunctionInfoWrapper info =
6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_));
696756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    info.SetFunctionCode(Handle<Code>(shared->code()),
697756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        Handle<Object>(shared->scope_info()));
6986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info.SetSharedFunctionInfo(shared);
6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Object> scope_info_list(SerializeFunctionScope(scope));
701756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    info.SetOuterScopeInfo(scope_info_list);
7026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> GetResult() {
7056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result_;
706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
7076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len_;
7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int current_parent_index_;
712402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu};
713402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
714402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic FunctionInfoListener* active_function_info_listener = NULL;
715402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
7166ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockJSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> source) {
7186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompilationZoneScope zone_scope(DELETE_ON_EXIT);
7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoListener listener;
7216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> original_source = Handle<Object>(script->source());
7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*source);
7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  active_function_info_listener = &listener;
7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CompileScriptForTracker(script);
7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  active_function_info_listener = NULL;
7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  script->set_source(*original_source);
7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *(listener.GetResult());
7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
7346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(array->length())->value();
7356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
7366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info(
7376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SharedFunctionInfo::cast(array->GetElement(i)));
7386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
7396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<String> name_handle(String::cast(info->name()));
7406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    info_wrapper.SetProperties(name_handle, info->start_position(),
7416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               info->end_position(), info);
74280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    SetElement(array, i, info_wrapper.GetJSArray());
7436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
7456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor that collects all references to a particular code object,
7486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// including "CODE_TARGET" references in other code objects.
7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It works in context of ZoneScope.
7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ReferenceCollectorVisitor : public ObjectVisitor {
7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
7526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit ReferenceCollectorVisitor(Code* original)
753791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    : original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) {
7546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitPointers(Object** start, Object** end) {
7576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (Object** p = start; p < end; p++) {
7586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (*p == original_) {
7596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        rvalues_.Add(p);
7606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
7616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
764791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeEntry(Address entry) {
765791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (Code::GetObjectFromEntryAddress(entry) == original_) {
766791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      code_entries_.Add(entry);
767791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
768791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
769791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
770791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  virtual void VisitCodeTarget(RelocInfo* rinfo) {
7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
7736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      reloc_infos_.Add(*rinfo);
7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  virtual void VisitDebugTarget(RelocInfo* rinfo) {
7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    VisitCodeTarget(rinfo);
7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Post-visiting method that iterates over all collected references and
7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // modifies them.
7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Replace(Code* substitution) {
7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < rvalues_.length(); i++) {
7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      *(rvalues_[i]) = substitution;
7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
787791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    Address substitution_entry = substitution->instruction_start();
7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (int i = 0; i < reloc_infos_.length(); i++) {
789791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      reloc_infos_[i].set_target_address(substitution_entry);
790791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
791791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    for (int i = 0; i < code_entries_.length(); i++) {
792791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Address entry = code_entries_[i];
793791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      Memory::Address_at(entry) = substitution_entry;
7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Code* original_;
7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<Object**> rvalues_;
8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<RelocInfo> reloc_infos_;
801791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ZoneList<Address> code_entries_;
8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Finds all references to original and replaces them with substitution.
8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReplaceCodeObject(Code* original, Code* substitution) {
8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!Heap::InNewSpace(substitution));
8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  AssertNoAllocation no_allocations_please;
8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // A zone scope for ReferenceCollectorVisitor.
8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneScope scope(DELETE_ON_EXIT);
8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ReferenceCollectorVisitor visitor(original);
8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Iterate over all roots. Stack frames may have pointer into original code,
8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // so temporary replace the pointers with offset numbers
8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // in prologue/epilogue.
8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Heap::IterateStrongRoots(&visitor, VISIT_ALL);
8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Now iterate over all pointers of all objects, including code_target
8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // implicit pointers.
8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HeapIterator iterator;
8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    obj->Iterate(&visitor);
8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  visitor.Replace(substitution);
8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check whether the code is natural function code (not a lazy-compile stub
8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// code).
8366ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsJSFunctionCode(Code* code) {
8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return code->kind() == Code::FUNCTION;
8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8416ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LiveEdit::ReplaceFunctionCode(Handle<JSArray> new_compile_info_array,
8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                      Handle<JSArray> shared_info_array) {
8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HandleScope scope;
8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Top::ThrowIllegalOperation();
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
8516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
8536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(shared_info->code())) {
8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ReplaceCodeObject(shared_info->code(),
8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                      *(compile_info_wrapper.GetFunctionCode()));
857756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Handle<Object> code_scope_info =  compile_info_wrapper.GetCodeScopeInfo();
858756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (code_scope_info->IsFixedArray()) {
859756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info));
860756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    }
8616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (shared_info->debug_info()->IsDebugInfo()) {
8646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
8656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> new_original_code =
8666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Factory::CopyCode(compile_info_wrapper.GetFunctionCode());
8676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    debug_info->set_original_code(*new_original_code);
8686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_start_position(compile_info_wrapper.GetStartPosition());
8716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
8726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_construct_stub(
8746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Builtins::builtin(Builtins::JSConstructStubGeneric));
8756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Heap::undefined_value();
8776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// TODO(635): Eval caches its scripts (same text -- same compiled info).
8816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Make sure we clear such caches.
8826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
8836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 Handle<Object> script_handle) {
8846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared_info =
8856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
8866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared_info->set_script(*script_handle);
8876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
8886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// For a script text change (defined as position_change_array), translates
8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// position in unchanged text to position in changed text.
8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Text change is a set of non-overlapping regions in text, that have changed
8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// their contents and length. It is specified as array of groups of 3 numbers:
8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (change_begin, change_end, change_end_new_position).
8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Each group describes a change in text; groups are sorted by change_begin.
8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Only position in text beyond any changes may be successfully translated.
8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// If a positions is inside some region that changed, result is currently
8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// undefined.
8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic int TranslatePosition(int original_position,
9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                             Handle<JSArray> position_change_array) {
9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int position_diff = 0;
9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(position_change_array->length())->value();
9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // TODO(635): binary search may be used here
9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i += 3) {
9056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int chunk_start =
9066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Smi::cast(position_change_array->GetElement(i))->value();
9076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (original_position < chunk_start) {
9086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int chunk_end =
9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Smi::cast(position_change_array->GetElement(i + 1))->value();
9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Position mustn't be inside a chunk.
9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(original_position >= chunk_end);
9146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int chunk_changed_end =
9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Smi::cast(position_change_array->GetElement(i + 2))->value();
9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    position_diff = chunk_changed_end - chunk_end;
9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return original_position + position_diff;
9206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
9216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Auto-growing buffer for writing relocation info code section. This buffer
9246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// is a simplified version of buffer from Assembler. Unlike Assembler, this
9256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// class is platform-independent and it works without dealing with instructions.
9266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// As specified by RelocInfo format, the buffer is filled in reversed order:
9276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from upper to lower addresses.
9286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It uses NewArray/DeleteArray for memory management.
9296ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass RelocInfoBuffer {
9306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
9316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer(int buffer_initial_capicity, byte* pc) {
9326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = buffer_initial_capicity + kBufferGap;
9336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = NewArray<byte>(buffer_size_);
9346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc);
9366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~RelocInfoBuffer() {
9386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
9396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // As specified by RelocInfo format, the buffer is filled in reversed order:
9426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // from upper to lower addresses.
9436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Write(const RelocInfo* rinfo) {
9446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) {
9456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Grow();
9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Write(rinfo);
9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> GetResult() {
9516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Return the bytes from pos up to end of buffer.
9526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int result_size =
9536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer_.pos());
9546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Vector<byte>(reloc_info_writer_.pos(), result_size);
9556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
9586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Grow() {
9596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Compute new buffer size.
9606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int new_buffer_size;
9616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (buffer_size_ < 2 * KB) {
9626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 4 * KB;
9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_buffer_size = 2 * buffer_size_;
9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Some internal data structures overflow for very large buffers,
9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // they must ensure that kMaximalBufferSize is not too large.
9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (new_buffer_size > kMaximalBufferSize) {
9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer");
9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Setup new buffer.
9736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    byte* new_buffer = NewArray<byte>(new_buffer_size);
9746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Copy the data.
9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int curently_used_size =
9776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        static_cast<int>(buffer_ + buffer_size_ - reloc_info_writer_.pos());
9786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memmove(new_buffer + new_buffer_size - curently_used_size,
9796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            reloc_info_writer_.pos(), curently_used_size);
9806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    reloc_info_writer_.Reposition(
9826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        new_buffer + new_buffer_size - curently_used_size,
9836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        reloc_info_writer_.last_pc());
9846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    DeleteArray(buffer_);
9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_ = new_buffer;
9876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    buffer_size_ = new_buffer_size;
9886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
9896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoWriter reloc_info_writer_;
9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  byte* buffer_;
9926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int buffer_size_;
9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  static const int kBufferGap = RelocInfoWriter::kMaxSize;
9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  static const int kMaximalBufferSize = 512*MB;
9966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
9976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
9986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Patch positions in code (changes relocation info section) and possibly
9996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// returns new instance of code.
10006ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Code> PatchPositionsInCode(Handle<Code> code,
10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> position_change_array) {
10026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RelocInfoBuffer buffer_writer(code->relocation_size(),
10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                code->instruction_start());
10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  {
10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    AssertNoAllocation no_allocations_please;
10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (RelocIterator it(*code); !it.done(); it.next()) {
10096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      RelocInfo* rinfo = it.rinfo();
10106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (RelocInfo::IsPosition(rinfo->rmode())) {
10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int position = static_cast<int>(rinfo->data());
10126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int new_position = TranslatePosition(position,
10136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (position != new_position) {
10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position);
10166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          buffer_writer.Write(&info_copy);
10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          continue;
10186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      buffer_writer.Write(it.rinfo());
10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<byte> buffer = buffer_writer.GetResult();
10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (buffer.length() == code->relocation_size()) {
10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Simply patch relocation area of code.
10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    memcpy(code->relocation_start(), buffer.start(), buffer.length());
10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return code;
10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Relocation info section now has different size. We cannot simply
10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // rewrite it inside code object. Instead we have to create a new
10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // code object.
10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> result(Factory::CopyCode(code, buffer));
10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10406ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LiveEdit::PatchFunctionPositions(
10416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
10426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return Top::ThrowIllegalOperation();
10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  SharedInfoWrapper shared_info_wrapper(shared_info_array);
10486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int old_function_start = info->start_position();
10516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int new_function_start = TranslatePosition(old_function_start,
10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                             position_change_array);
10536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_start_position(new_function_start);
10546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_end_position(TranslatePosition(info->end_position(),
10556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           position_change_array));
10566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  info->set_function_token_position(
10586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      TranslatePosition(info->function_token_position(),
10596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      position_change_array));
10606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IsJSFunctionCode(info->code())) {
10626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Patch relocation info section of the code.
10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()),
10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                     position_change_array);
10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (*patched_code != info->code()) {
10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Replace all references to the code across the heap. In particular,
10676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // some stubs may refer to this code and this code may be being executed
10686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // on stack (it is safe to substitute the code object on stack, because
10696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // we only change the structure of rinfo and leave instructions
10706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // untouched).
10716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      ReplaceCodeObject(info->code(), *patched_code);
10726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Heap::undefined_value();
10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Script> CreateScriptCopy(Handle<Script> original) {
10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<String> original_source(String::cast(original->source()));
10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Script> copy = Factory::NewScript(original_source);
10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_name(original->name());
10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_line_offset(original->line_offset());
10866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_column_offset(original->column_offset());
10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_data(original->data());
10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_type(original->type());
10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_context_data(original->context_data());
10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_compilation_type(original->compilation_type());
10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_shared(original->eval_from_shared());
10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  copy->set_eval_from_instructions_offset(
10936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      original->eval_from_instructions_offset());
10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return copy;
10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
10976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10996ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LiveEdit::ChangeScriptSource(Handle<Script> original_script,
11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<String> new_source,
11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                     Handle<Object> old_script_name) {
11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Object> old_script_object;
11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (old_script_name->IsString()) {
11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<Script> old_script = CreateScriptCopy(original_script);
11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script->set_name(String::cast(*old_script_name));
11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script_object = old_script;
11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING);
11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
11096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    old_script_object = Handle<Object>(Heap::null_value());
11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  original_script->set_source(*new_source);
11136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Drop line ends so that they will be recalculated.
11156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  original_script->set_line_ends(Heap::undefined_value());
11166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return *old_script_object;
11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::ReplaceRefToNestedFunction(
11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> parent_function_wrapper,
11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> orig_function_wrapper,
11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSValue> subst_function_wrapper) {
11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> parent_shared =
11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(parent_function_wrapper));
11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> orig_shared =
11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(orig_function_wrapper));
11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> subst_shared =
11326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<SharedFunctionInfo>::cast(UnwrapJSValue(subst_function_wrapper));
11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
11366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (it.rinfo()->target_object() == *orig_shared) {
11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        it.rinfo()->set_target_object(*subst_shared);
11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check an activation against list of functions. If there is a function
11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that matches, its status in result array is changed to status argument value.
11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CheckActivation(Handle<JSArray> shared_info_array,
11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            Handle<JSArray> result, StackFrame* frame,
11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FunctionPatchabilityStatus status) {
11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!frame->is_java_script()) {
11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
11536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    JSValue* wrapper = JSValue::cast(shared_info_array->GetElement(i));
11556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> shared(
11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SharedFunctionInfo::cast(wrapper->value()));
11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frame->code() == shared->code()) {
11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      SetElement(result, i, Handle<Smi>(Smi::FromInt(status)));
11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return true;
11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Iterates over handler chain and removes all elements that are inside
11686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames being dropped.
11696ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool FixTryCatchHandler(StackFrame* top_frame,
11706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                               StackFrame* bottom_frame) {
11716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* pointer_address =
11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address));
11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < top_frame->sp()) {
11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address* above_frame_address = pointer_address;
11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (*pointer_address < bottom_frame->fp()) {
11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    pointer_address = &Memory::Address_at(*pointer_address);
11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool change = *above_frame_address != *pointer_address;
11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  *above_frame_address = *pointer_address;
11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return change;
11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Removes specified range of frames from stack. There may be 1 or more
11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames in range. Anyway the bottom frame is restarted rather than dropped,
11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// and therefore has to be a JavaScript frame.
11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Returns error message or NULL.
11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropFrames(Vector<StackFrame*> frames,
11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                              int top_frame_index,
11938defd9ff6930b4e24729971a61cf7469daf119beSteve Block                              int bottom_js_frame_index,
1194bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Debug::FrameDropMode* mode,
1195bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                              Object*** restarter_frame_function_pointer) {
1196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (!Debug::kFrameDropperSupported) {
11978defd9ff6930b4e24729971a61cf7469daf119beSteve Block    return "Stack manipulations are not supported in this architecture.";
11988defd9ff6930b4e24729971a61cf7469daf119beSteve Block  }
11998defd9ff6930b4e24729971a61cf7469daf119beSteve Block
12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* pre_top_frame = frames[top_frame_index - 1];
12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* top_frame = frames[top_frame_index];
12026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame* bottom_js_frame = frames[bottom_js_frame_index];
12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(bottom_js_frame->is_java_script());
12056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check the nature of the top frame.
12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (pre_top_frame->code()->is_inline_cache_stub() &&
12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pre_top_frame->code()->ic_state() == DEBUG_BREAK) {
12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop inline cache calls.
12108defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
12118defd9ff6930b4e24729971a61cf7469daf119beSteve Block  } else if (pre_top_frame->code() == Debug::debug_break_slot()) {
12128defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // OK, we can drop debug break slot.
12138defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (pre_top_frame->code() ==
12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Builtins::builtin(Builtins::FrameDropper_LiveEdit)) {
12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // OK, we can drop our own code.
12178defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (pre_top_frame->code()->kind() == Code::STUB &&
12196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pre_top_frame->code()->major_key()) {
12208defd9ff6930b4e24729971a61cf7469daf119beSteve Block    // Entry from our unit tests, it's fine, we support this case.
12218defd9ff6930b4e24729971a61cf7469daf119beSteve Block    *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Unknown structure of stack above changing function";
12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_top = top_frame->sp();
12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Address unused_stack_bottom = bottom_js_frame->fp()
12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      - Debug::kFrameDropperFrameSize * kPointerSize  // Size of the new frame.
12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      + kPointerSize;  // Bigger address end is exclusive.
12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (unused_stack_top > unused_stack_bottom) {
12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return "Not enough space for frame dropper frame";
12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Committing now. After this point we should return only NULL value.
12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  FixTryCatchHandler(pre_top_frame, bottom_js_frame);
12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Make sure FixTryCatchHandler is idempotent.
12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<Code> code(Builtins::builtin(Builtins::FrameDropper_LiveEdit));
12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  top_frame->set_pc(code->entry());
12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  pre_top_frame->SetCallerFp(bottom_js_frame->fp());
12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1245bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  *restarter_frame_function_pointer =
1246bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      Debug::SetUpFrameDropperFrame(bottom_js_frame, code);
1247bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
1248bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  ASSERT((**restarter_frame_function_pointer)->IsJSFunction());
12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (Address a = unused_stack_top;
12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a < unused_stack_bottom;
12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      a += kPointerSize) {
12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Memory::Object_at(a) = Smi::FromInt(0);
12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDropableFrame(StackFrame* frame) {
12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return !frame->is_exit();
12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Fills result array with statuses of functions. Modifies the stack
12656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// removing all listed function if possible and if do_drop is true.
12666ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropActivationsInActiveThread(
12676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
12686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneScope scope(DELETE_ON_EXIT);
12706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Vector<StackFrame*> frames = CreateStackMap();
12716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int array_len = Smi::cast(shared_info_array->length())->value();
12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int top_frame_index = -1;
12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int frame_index = 0;
12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
12776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frame->id() == Debug::break_frame_id()) {
12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      top_frame_index = frame_index;
12806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
12836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
12846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // We are still above break_frame. It is not a target frame,
12856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // it is a problem.
12866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return "Debugger mark-up on stack is not found";
12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (top_frame_index == -1) {
12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We haven't found break frame, but no function is blocking us anyway.
12926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
12936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
12946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool target_frame_found = false;
12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int bottom_js_frame_index = top_frame_index;
12976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool c_code_found = false;
12986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
12996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (; frame_index < frames.length(); frame_index++) {
13006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = frames[frame_index];
13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!IsDropableFrame(frame)) {
13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      c_code_found = true;
13036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
13046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (CheckActivation(shared_info_array, result, frame,
13066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                        LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      target_frame_found = true;
13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      bottom_js_frame_index = frame_index;
13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (c_code_found) {
13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // There is a C frames on stack. Check that there are no target frames
13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // below them.
13156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (; frame_index < frames.length(); frame_index++) {
13166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      StackFrame* frame = frames[frame_index];
13176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (frame->is_java_script()) {
13186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (CheckActivation(shared_info_array, result, frame,
13196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                            LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
13206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          // Cannot drop frame under C frames.
13216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          return NULL;
13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        }
13236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!do_drop) {
13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // We are in check-only mode.
13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!target_frame_found) {
13336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Nothing to drop.
13346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return NULL;
13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13378defd9ff6930b4e24729971a61cf7469daf119beSteve Block  Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED;
1338bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Object** restarter_frame_function_pointer = NULL;
13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message = DropFrames(frames, top_frame_index,
1340bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         bottom_js_frame_index, &drop_mode,
1341bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                         &restarter_frame_function_pointer);
13426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
13446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return error_message;
13456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Adjust break_frame after some frames has been dropped.
13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  StackFrame::Id new_id = StackFrame::NO_ID;
13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      new_id = frames[i]->id();
13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1355bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Debug::FramesHaveBeenDropped(new_id, drop_mode,
1356bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                               restarter_frame_function_pointer);
13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Replace "blocked on active" with "replaced on active" status.
13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < array_len; i++) {
13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (result->GetElement(i) ==
13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
136280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Handle<Object> replaced(
136380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen          Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK));
136480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      SetElement(result, i, replaced);
13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
13686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass InactiveThreadActivationsChecker : public ThreadVisitor {
13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                   Handle<JSArray> result)
13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      : shared_info_array_(shared_info_array), result_(result),
13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        has_blocked_functions_(false) {
13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void VisitThread(ThreadLocalTop* top) {
13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      has_blocked_functions_ |= CheckActivation(
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          shared_info_array_, result_, it.frame(),
13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool HasBlockedFunctions() {
13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return has_blocked_functions_;
13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> shared_info_array_;
13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result_;
13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool has_blocked_functions_;
13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CheckAndDropActivations(
13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<JSArray> shared_info_array, bool do_drop) {
13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int len = Smi::cast(shared_info_array->length())->value();
13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<JSArray> result = Factory::NewJSArray(len);
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Fill the default values.
14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (int i = 0; i < len; i++) {
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(result, i,
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block               Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH)));
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // First check inactive threads. Fail if some functions are blocked there.
14106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                            result);
14127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  ThreadManager::IterateArchivedThreads(&inactive_threads_checker);
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (inactive_threads_checker.HasBlockedFunctions()) {
14146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Try to drop activations from the current stack.
14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* error_message =
14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      DropActivationsInActiveThread(shared_info_array, result, do_drop);
14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (error_message != NULL) {
14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Add error message as an array extra element.
14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Vector<const char> vector_message(error_message, StrLength(error_message));
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<String> str = Factory::NewStringFromAscii(vector_message);
14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetElement(result, len, str);
14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1430402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
1431402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (active_function_info_listener != NULL) {
1432402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    active_function_info_listener->FunctionStarted(fun);
1433402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1434402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
14356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1437402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::~LiveEditFunctionTracker() {
1438402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (active_function_info_listener != NULL) {
1439402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    active_function_info_listener->FunctionDone();
1440402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1441402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
14456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
1446402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (active_function_info_listener != NULL) {
14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    active_function_info_listener->FunctionInfo(info, lit->scope());
1448402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
1449402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  active_function_info_listener->FunctionCode(code);
1454402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1457402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescubool LiveEditFunctionTracker::IsActive() {
1458402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return active_function_info_listener != NULL;
1459402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
1460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else  // ENABLE_DEBUGGER_SUPPORT
14636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// This ifdef-else-endif section provides working or stub implementation of
14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// LiveEditFunctionTracker.
14666ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
14676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14706ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::~LiveEditFunctionTracker() {
14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo(
14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> info, FunctionLiteral* lit) {
14766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool LiveEditFunctionTracker::IsActive() {
14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return false;
14856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // ENABLE_DEBUGGER_SUPPORT
14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1491402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} }  // namespace v8::internal
1492