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