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