liveedit.cc revision b0fe1620dcb4135ac3ab2d66ff93072373911299
1402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Copyright 2010 the V8 project authors. All rights reserved. 2402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// Redistribution and use in source and binary forms, with or without 3402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// modification, are permitted provided that the following conditions are 4402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// met: 5402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// 6402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// * Redistributions of source code must retain the above copyright 7402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// notice, this list of conditions and the following disclaimer. 8402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// * Redistributions in binary form must reproduce the above 9402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// copyright notice, this list of conditions and the following 10402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// disclaimer in the documentation and/or other materials provided 11402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// with the distribution. 12402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// * Neither the name of Google Inc. nor the names of its 13402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// contributors may be used to endorse or promote products derived 14402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// from this software without specific prior written permission. 15402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// 16402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 28402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 29402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "v8.h" 30402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 31402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "liveedit.h" 32f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 33402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "compiler.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "compilation-cache.h" 35402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu#include "debug.h" 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h" 37f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "global-handles.h" 386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "memory.h" 39f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "oprofile-agent.h" 40f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "parser.h" 41f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "scopeinfo.h" 42f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "scopes.h" 43402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 44402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace v8 { 45402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace internal { 46402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 47402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef ENABLE_DEBUGGER_SUPPORT 496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// A simple implementation of dynamic programming algorithm. It solves 526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// the problem of finding the difference of 2 arrays. It uses a table of results 536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// of subproblems. Each cell contains a number together with 2-bit flag 546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that helps building the chunk list. 556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass Differencer { 566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit Differencer(Comparator::Input* input) 586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : input_(input), len1_(input->getLength1()), len2_(input->getLength2()) { 596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_ = NewArray<int>(len1_ * len2_); 606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ~Differencer() { 626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DeleteArray(buffer_); 636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Initialize() { 666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int array_size = len1_ * len2_; 676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < array_size; i++) { 686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_[i] = kEmptyCellValue; 696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Makes sure that result for the full problem is calculated and stored 736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // in the table together with flags showing a path through subproblems. 746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void FillTable() { 756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CompareUpToTail(0, 0); 766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SaveResult(Comparator::Output* chunk_writer) { 796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ResultWriter writer(chunk_writer); 806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int pos1 = 0; 826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int pos2 = 0; 836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block while (true) { 846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (pos1 < len1_) { 856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (pos2 < len2_) { 866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Direction dir = get_direction(pos1, pos2); 876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block switch (dir) { 886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case EQ: 896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block writer.eq(); 906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos1++; 916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos2++; 926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case SKIP1: 946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block writer.skip1(1); 956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos1++; 966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case SKIP2: 986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block case SKIP_ANY: 996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block writer.skip2(1); 1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos2++; 1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block default: 1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block UNREACHABLE(); 1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block writer.skip1(len1_ - pos1); 1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (len2_ != pos2) { 1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block writer.skip2(len2_ - pos2); 1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block writer.close(); 1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comparator::Input* input_; 1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int* buffer_; 1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len1_; 1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len2_; 1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block enum Direction { 1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block EQ = 0, 1276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SKIP1, 1286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SKIP2, 1296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SKIP_ANY, 1306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block MAX_DIRECTION_FLAG_VALUE = SKIP_ANY 1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block }; 1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Computes result for a subtask and optionally caches it in the buffer table. 1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // All results values are shifted to make space for flags in the lower bits. 1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int CompareUpToTail(int pos1, int pos2) { 1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (pos1 < len1_) { 1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (pos2 < len2_) { 1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int cached_res = get_value4(pos1, pos2); 1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (cached_res == kEmptyCellValue) { 1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Direction dir; 1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int res; 1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (input_->equals(pos1, pos2)) { 1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block res = CompareUpToTail(pos1 + 1, pos2 + 1); 1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block dir = EQ; 1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int res1 = CompareUpToTail(pos1 + 1, pos2) + 1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (1 << kDirectionSizeBits); 1496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int res2 = CompareUpToTail(pos1, pos2 + 1) + 1506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (1 << kDirectionSizeBits); 1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (res1 == res2) { 1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block res = res1; 1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block dir = SKIP_ANY; 1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (res1 < res2) { 1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block res = res1; 1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block dir = SKIP1; 1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block res = res2; 1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block dir = SKIP2; 1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block set_value4_and_dir(pos1, pos2, res, dir); 1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block cached_res = res; 1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return cached_res; 1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return (len1_ - pos1) << kDirectionSizeBits; 1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return (len2_ - pos2) << kDirectionSizeBits; 1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block inline int& get_cell(int i1, int i2) { 1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return buffer_[i1 + i2 * len1_]; 1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Each cell keeps a value plus direction. Value is multiplied by 4. 1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void set_value4_and_dir(int i1, int i2, int value4, Direction dir) { 1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT((value4 & kDirectionMask) == 0); 1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block get_cell(i1, i2) = value4 | dir; 1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int get_value4(int i1, int i2) { 1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return get_cell(i1, i2) & (kMaxUInt32 ^ kDirectionMask); 1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Direction get_direction(int i1, int i2) { 1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return static_cast<Direction>(get_cell(i1, i2) & kDirectionMask); 1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kDirectionSizeBits = 2; 1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kDirectionMask = (1 << kDirectionSizeBits) - 1; 1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kEmptyCellValue = -1 << kDirectionSizeBits; 1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // This method only holds static assert statement (unfortunately you cannot 1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // place one in class scope). 1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void StaticAssertHolder() { 1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block STATIC_ASSERT(MAX_DIRECTION_FLAG_VALUE < (1 << kDirectionSizeBits)); 1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block class ResultWriter { 2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit ResultWriter(Comparator::Output* chunk_writer) 2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : chunk_writer_(chunk_writer), pos1_(0), pos2_(0), 2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos1_begin_(-1), pos2_begin_(-1), has_open_chunk_(false) { 2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void eq() { 2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FlushChunk(); 2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos1_++; 2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos2_++; 2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void skip1(int len1) { 2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StartChunk(); 2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos1_ += len1; 2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void skip2(int len2) { 2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StartChunk(); 2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos2_ += len2; 2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void close() { 2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FlushChunk(); 2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comparator::Output* chunk_writer_; 2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int pos1_; 2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int pos2_; 2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int pos1_begin_; 2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int pos2_begin_; 2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool has_open_chunk_; 2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void StartChunk() { 2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!has_open_chunk_) { 2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos1_begin_ = pos1_; 2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos2_begin_ = pos2_; 2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block has_open_chunk_ = true; 2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void FlushChunk() { 2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (has_open_chunk_) { 2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block chunk_writer_->AddChunk(pos1_begin_, pos2_begin_, 2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pos1_ - pos1_begin_, pos2_ - pos2_begin_); 2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block has_open_chunk_ = false; 2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block }; 2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid Comparator::CalculateDifference(Comparator::Input* input, 2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comparator::Output* result_writer) { 2536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Differencer differencer(input); 2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block differencer.Initialize(); 2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block differencer.FillTable(); 2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block differencer.SaveResult(result_writer); 2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CompareSubstrings(Handle<String> s1, int pos1, 2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> s2, int pos2, int len) { 2626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static StringInputBuffer buf1; 2636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static StringInputBuffer buf2; 2646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buf1.Reset(*s1); 2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buf1.Seek(pos1); 2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buf2.Reset(*s2); 2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buf2.Seek(pos2); 2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < len; i++) { 2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(buf1.has_more() && buf2.has_more()); 2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (buf1.GetNext() != buf2.GetNext()) { 2716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return false; 2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return true; 2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps raw n-elements line_ends array as a list of n+1 lines. The last line 2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// never has terminating new line character. 2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineEndsWrapper { 2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit LineEndsWrapper(Handle<String> string) 2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : ends_array_(CalculateLineEnds(string, false)), 2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block string_len_(string->length()) { 2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int length() { 2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return ends_array_->length() + 1; 2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Returns start for any line including start of the imaginary line after 2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // the last line. 2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int GetLineStart(int index) { 2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (index == 0) { 2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return 0; 2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return GetLineEnd(index - 1); 2966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int GetLineEnd(int index) { 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (index == ends_array_->length()) { 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // End of the last line is always an end of the whole string. 3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If the string ends with a new line character, the last line is an 3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // empty string after this character. 3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return string_len_; 3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return GetPosAfterNewLine(index); 3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<FixedArray> ends_array_; 3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int string_len_; 3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int GetPosAfterNewLine(int index) { 3146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Smi::cast(ends_array_->get(index))->value() + 1; 3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 3176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents 2 strings as 2 arrays of lines. 3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineArrayCompareInput : public Comparator::Input { 3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineArrayCompareInput(Handle<String> s1, Handle<String> s2, 3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineEndsWrapper line_ends1, LineEndsWrapper line_ends2) 3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : s1_(s1), s2_(s2), line_ends1_(line_ends1), line_ends2_(line_ends2) { 3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int getLength1() { 3276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return line_ends1_.length(); 3286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int getLength2() { 3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return line_ends2_.length(); 3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool equals(int index1, int index2) { 3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_start1 = line_ends1_.GetLineStart(index1); 3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_start2 = line_ends2_.GetLineStart(index2); 3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_end1 = line_ends1_.GetLineEnd(index1); 3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_end2 = line_ends2_.GetLineEnd(index2); 3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len1 = line_end1 - line_start1; 3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len2 = line_end2 - line_start2; 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (len1 != len2) { 3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return false; 3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return CompareSubstrings(s1_, line_start1, s2_, line_start2, len1); 3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> s1_; 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> s2_; 3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineEndsWrapper line_ends1_; 3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineEndsWrapper line_ends2_; 3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Stores compare result in JSArray. Each chunk is stored as 3 array elements: 3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (pos1_begin, pos1_end, pos2_end). 3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass LineArrayCompareOutput : public Comparator::Output { 3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineArrayCompareOutput(LineEndsWrapper line_ends1, LineEndsWrapper line_ends2) 3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : array_(Factory::NewJSArray(10)), current_size_(0), 3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block line_ends1_(line_ends1), line_ends2_(line_ends2) { 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) { 3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int char_pos1 = line_ends1_.GetLineStart(line_pos1); 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int char_pos2 = line_ends2_.GetLineStart(line_pos2); 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1; 3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2; 3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(array_, current_size_, Handle<Object>(Smi::FromInt(char_pos1))); 3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(array_, current_size_ + 1, 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object>(Smi::FromInt(char_pos1 + char_len1))); 3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(array_, current_size_ + 2, 3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object>(Smi::FromInt(char_pos2 + char_len2))); 3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current_size_ += 3; 3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> GetResult() { 3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return array_; 3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> array_; 3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int current_size_; 3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineEndsWrapper line_ends1_; 3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineEndsWrapper line_ends2_; 3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3886ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CompareStringsLinewise(Handle<String> s1, 3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> s2) { 3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineEndsWrapper line_ends1(s1); 3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineEndsWrapper line_ends2(s2); 3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineArrayCompareInput input(s1, s2, line_ends1, line_ends2); 3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LineArrayCompareOutput output(line_ends1, line_ends2); 3956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comparator::CalculateDifference(&input, &output); 3976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return output.GetResult(); 3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void CompileScriptForTracker(Handle<Script> script) { 4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // TODO(635): support extensions. 4046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block PostponeInterruptsScope postpone; 4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Build AST. 407f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompilationInfo info(script); 408f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch info.MarkAsGlobal(); 4093e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (ParserApi::Parse(&info)) { 410f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Compile the code. 411f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LiveEditFunctionTracker tracker(info.function()); 412f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (Compiler::MakeCodeForLiveEdit(&info)) { 413f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ASSERT(!info.code().is_null()); 414f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch tracker.RecordRootFunctionInfo(info.code()); 415f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } else { 416f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Top::StackOverflow(); 417f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 4186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 421f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Unwraps JSValue object, returning its field "value" 4236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) { 4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<Object>(jsValue->value()); 4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 427f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps any object into a OpaqueReference, that will hide the object 4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript. 4306ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<JSValue> WrapInJSValue(Object* object) { 4316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSFunction> constructor = Top::opaque_reference_function(); 4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue> result = 4336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue>::cast(Factory::NewJSObject(constructor)); 4346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result->set_value(object); 4356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result; 4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 438f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 4396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Simple helper class that creates more or less typed structures over 4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// JSArray object. This is an adhoc method of passing structures from C++ 4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// to JavaScript. 4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename S> 4436ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass JSArrayBasedStruct { 4446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 4456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static S Create() { 4466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> array = Factory::NewJSArray(S::kSize_); 4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return S(array); 4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static S cast(Object* object) { 4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSArray* array = JSArray::cast(object); 4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> array_handle(array); 4526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return S(array_handle); 4536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) { 4556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> GetJSArray() { 4576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return array_; 4586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 459f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 4606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block protected: 4616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SetField(int field_position, Handle<Object> value) { 4626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(array_, field_position, value); 4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SetSmiValueField(int field_position, int value) { 4656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value))); 4666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* GetField(int field_position) { 4685913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck return array_->GetElementNoExceptionThrown(field_position); 4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int GetSmiValueField(int field_position) { 4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* res = GetField(field_position); 4726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Smi::cast(res)->value(); 4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 474f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> array_; 4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Represents some function compilation details. This structure will be used 4816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from JavaScript. It contains Code object, which is kept wrapped 4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// into a BlindReference for sanitizing reasons. 4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> { 4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit FunctionInfoWrapper(Handle<JSArray> array) 4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : JSArrayBasedStruct<FunctionInfoWrapper>(array) { 4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SetInitialProperties(Handle<String> name, int start_position, 4896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int end_position, int param_num, int parent_index) { 4906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HandleScope scope; 4916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetField(kFunctionNameOffset_, name); 4926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetSmiValueField(kStartPositionOffset_, start_position); 4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetSmiValueField(kEndPositionOffset_, end_position); 4946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetSmiValueField(kParamNumOffset_, param_num); 4956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetSmiValueField(kParentIndexOffset_, parent_index); 4966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 497756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void SetFunctionCode(Handle<Code> function_code, 498756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Handle<Object> code_scope_info) { 499756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Handle<JSValue> code_wrapper = WrapInJSValue(*function_code); 500756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick this->SetField(kCodeOffset_, code_wrapper); 501756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 502756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Handle<JSValue> scope_wrapper = WrapInJSValue(*code_scope_info); 503756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick this->SetField(kCodeScopeInfoOffset_, scope_wrapper); 5046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 505756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void SetOuterScopeInfo(Handle<Object> scope_info_array) { 506756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick this->SetField(kOuterScopeInfoOffset_, scope_info_array); 5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) { 5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue> info_holder = WrapInJSValue(*info); 5106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetField(kSharedFunctionInfoOffset_, info_holder); 5116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int GetParentIndex() { 5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return this->GetSmiValueField(kParentIndexOffset_); 5146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Code> GetFunctionCode() { 5166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>( 5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSValue::cast(this->GetField(kCodeOffset_)))); 5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<Code>::cast(raw_result); 5196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 520756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Handle<Object> GetCodeScopeInfo() { 521756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>( 522756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick JSValue::cast(this->GetField(kCodeScopeInfoOffset_)))); 523756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick return raw_result; 524756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 5256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int GetStartPosition() { 5266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return this->GetSmiValueField(kStartPositionOffset_); 5276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int GetEndPosition() { 5296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return this->GetSmiValueField(kEndPositionOffset_); 5306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kFunctionNameOffset_ = 0; 5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kStartPositionOffset_ = 1; 5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kEndPositionOffset_ = 2; 5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kParamNumOffset_ = 3; 5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kCodeOffset_ = 4; 538756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick static const int kCodeScopeInfoOffset_ = 5; 539756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick static const int kOuterScopeInfoOffset_ = 6; 540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick static const int kParentIndexOffset_ = 7; 541756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick static const int kSharedFunctionInfoOffset_ = 8; 542756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick static const int kSize_ = 9; 5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block friend class JSArrayBasedStruct<FunctionInfoWrapper>; 5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Wraps SharedFunctionInfo along with some of its fields for passing it 5496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// back to JavaScript. SharedFunctionInfo object itself is additionally 5506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// wrapped into BlindReference for sanitizing reasons. 5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> { 5526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static bool IsInstance(Handle<JSArray> array) { 5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return array->length() == Smi::FromInt(kSize_) && 5555913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck array->GetElementNoExceptionThrown(kSharedInfoOffset_)->IsJSValue(); 5566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit SharedInfoWrapper(Handle<JSArray> array) 5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : JSArrayBasedStruct<SharedInfoWrapper>(array) { 5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SetProperties(Handle<String> name, int start_position, int end_position, 5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> info) { 5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HandleScope scope; 5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetField(kFunctionNameOffset_, name); 5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue> info_holder = WrapInJSValue(*info); 5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetField(kSharedInfoOffset_, info_holder); 5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetSmiValueField(kStartPositionOffset_, start_position); 5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block this->SetSmiValueField(kEndPositionOffset_, end_position); 5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> GetInfo() { 5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* element = this->GetField(kSharedInfoOffset_); 5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue> value_wrapper(JSValue::cast(element)); 5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> raw_result = UnwrapJSValue(value_wrapper); 5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<SharedFunctionInfo>::cast(raw_result); 5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kFunctionNameOffset_ = 0; 5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kStartPositionOffset_ = 1; 5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kEndPositionOffset_ = 2; 5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kSharedInfoOffset_ = 3; 5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kSize_ = 4; 5846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block friend class JSArrayBasedStruct<SharedInfoWrapper>; 5866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 588f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 589402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuclass FunctionInfoListener { 590402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu public: 5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FunctionInfoListener() { 5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current_parent_index_ = -1; 5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block len_ = 0; 5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result_ = Factory::NewJSArray(10); 5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void FunctionStarted(FunctionLiteral* fun) { 5986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HandleScope scope; 5996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FunctionInfoWrapper info = FunctionInfoWrapper::Create(); 6006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block info.SetInitialProperties(fun->name(), fun->start_position(), 6016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block fun->end_position(), fun->num_parameters(), 6026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current_parent_index_); 6036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current_parent_index_ = len_; 6046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(result_, len_, info.GetJSArray()); 6056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block len_++; 606402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu void FunctionDone() { 6096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HandleScope scope; 610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionInfoWrapper info = 611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionInfoWrapper::cast( 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result_->GetElementNoExceptionThrown(current_parent_index_)); 6136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block current_parent_index_ = info.GetParentIndex(); 614402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 615402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 61659151504615d929945dc59db37bf1166937748c6Steve Block // Saves only function code, because for a script function we 61759151504615d929945dc59db37bf1166937748c6Steve Block // may never create a SharedFunctionInfo object. 61859151504615d929945dc59db37bf1166937748c6Steve Block void FunctionCode(Handle<Code> function_code) { 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionInfoWrapper info = 620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionInfoWrapper::cast( 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result_->GetElementNoExceptionThrown(current_parent_index_)); 62259151504615d929945dc59db37bf1166937748c6Steve Block info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value())); 62359151504615d929945dc59db37bf1166937748c6Steve Block } 62459151504615d929945dc59db37bf1166937748c6Steve Block 62559151504615d929945dc59db37bf1166937748c6Steve Block // Saves full information about a function: its code, its scope info 62659151504615d929945dc59db37bf1166937748c6Steve Block // and a SharedFunctionInfo object. 62759151504615d929945dc59db37bf1166937748c6Steve Block void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope) { 62859151504615d929945dc59db37bf1166937748c6Steve Block if (!shared->IsSharedFunctionInfo()) { 62959151504615d929945dc59db37bf1166937748c6Steve Block return; 63059151504615d929945dc59db37bf1166937748c6Steve Block } 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionInfoWrapper info = 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionInfoWrapper::cast( 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result_->GetElementNoExceptionThrown(current_parent_index_)); 63459151504615d929945dc59db37bf1166937748c6Steve Block info.SetFunctionCode(Handle<Code>(shared->code()), 63559151504615d929945dc59db37bf1166937748c6Steve Block Handle<Object>(shared->scope_info())); 63659151504615d929945dc59db37bf1166937748c6Steve Block info.SetSharedFunctionInfo(shared); 63759151504615d929945dc59db37bf1166937748c6Steve Block 63859151504615d929945dc59db37bf1166937748c6Steve Block Handle<Object> scope_info_list(SerializeFunctionScope(scope)); 63959151504615d929945dc59db37bf1166937748c6Steve Block info.SetOuterScopeInfo(scope_info_list); 64059151504615d929945dc59db37bf1166937748c6Steve Block } 64159151504615d929945dc59db37bf1166937748c6Steve Block 64259151504615d929945dc59db37bf1166937748c6Steve Block Handle<JSArray> GetResult() { return result_; } 64359151504615d929945dc59db37bf1166937748c6Steve Block 6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 6456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Object* SerializeFunctionScope(Scope* scope) { 6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HandleScope handle_scope; 6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> scope_info_list = Factory::NewJSArray(10); 6496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int scope_info_length = 0; 6506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Saves some description of scope. It stores name and indexes of 6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // variables in the whole scope chain. Null-named slots delimit 6536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // scopes of this chain. 6546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Scope* outer_scope = scope->outer_scope(); 6556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (outer_scope == NULL) { 6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Heap::undefined_value(); 6576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block do { 6596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ZoneList<Variable*> list(10); 6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block outer_scope->CollectUsedVariables(&list); 6616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int j = 0; 6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < list.length(); i++) { 6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Variable* var1 = list[i]; 6640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Slot* slot = var1->AsSlot(); 6656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (slot != NULL && slot->type() == Slot::CONTEXT) { 6666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (j != i) { 6676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block list[j] = var1; 6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block j++; 6706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Sort it. 6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int k = 1; k < j; k++) { 6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int l = k; 6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int m = k + 1; m < j; m++) { 6770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (list[l]->AsSlot()->index() > list[m]->AsSlot()->index()) { 6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block l = m; 6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block list[k] = list[l]; 6826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < j; i++) { 6846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(scope_info_list, scope_info_length, list[i]->name()); 6856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scope_info_length++; 6866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(scope_info_list, scope_info_length, 6870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Smi>(Smi::FromInt(list[i]->AsSlot()->index()))); 6886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scope_info_length++; 6896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(scope_info_list, scope_info_length, 6916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object>(Heap::null_value())); 6926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block scope_info_length++; 6936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block outer_scope = outer_scope->outer_scope(); 6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } while (outer_scope != NULL); 6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return *scope_info_list; 698402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 699402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 7006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> result_; 7016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len_; 7026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int current_parent_index_; 703402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}; 704402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 705f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 706402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescustatic FunctionInfoListener* active_function_info_listener = NULL; 707402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 7086ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockJSArray* LiveEdit::GatherCompileInfo(Handle<Script> script, 7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> source) { 7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CompilationZoneScope zone_scope(DELETE_ON_EXIT); 7116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FunctionInfoListener listener; 7136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> original_source = Handle<Object>(script->source()); 7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block script->set_source(*source); 7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block active_function_info_listener = &listener; 7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CompileScriptForTracker(script); 7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block active_function_info_listener = NULL; 7186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block script->set_source(*original_source); 7196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return *(listener.GetResult()); 7216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 7226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7246ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) { 7256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HandleScope scope; 7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len = Smi::cast(array->length())->value(); 7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < len; i++) { 7286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> info( 7295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck SharedFunctionInfo::cast(array->GetElementNoExceptionThrown(i))); 7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(); 7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> name_handle(String::cast(info->name())); 7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block info_wrapper.SetProperties(name_handle, info->start_position(), 7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block info->end_position(), info); 73480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetElement(array, i, info_wrapper.GetJSArray()); 7356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 7376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Visitor that collects all references to a particular code object, 7406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// including "CODE_TARGET" references in other code objects. 7416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It works in context of ZoneScope. 7426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ReferenceCollectorVisitor : public ObjectVisitor { 7436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 7446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block explicit ReferenceCollectorVisitor(Code* original) 745791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block : original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) { 7466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block virtual void VisitPointers(Object** start, Object** end) { 7496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (Object** p = start; p < end; p++) { 7506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*p == original_) { 7516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block rvalues_.Add(p); 7526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 756791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block virtual void VisitCodeEntry(Address entry) { 757791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (Code::GetObjectFromEntryAddress(entry) == original_) { 758791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block code_entries_.Add(entry); 759791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 760791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 761791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 762791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block virtual void VisitCodeTarget(RelocInfo* rinfo) { 7636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (RelocInfo::IsCodeTarget(rinfo->rmode()) && 7646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) { 7656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block reloc_infos_.Add(*rinfo); 7666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block virtual void VisitDebugTarget(RelocInfo* rinfo) { 7706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block VisitCodeTarget(rinfo); 7716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Post-visiting method that iterates over all collected references and 7746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // modifies them. 7756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Replace(Code* substitution) { 7766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < rvalues_.length(); i++) { 7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block *(rvalues_[i]) = substitution; 7786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 779791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block Address substitution_entry = substitution->instruction_start(); 7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < reloc_infos_.length(); i++) { 781791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block reloc_infos_[i].set_target_address(substitution_entry); 782791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 783791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block for (int i = 0; i < code_entries_.length(); i++) { 784791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block Address entry = code_entries_[i]; 785791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block Memory::Address_at(entry) = substitution_entry; 7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 7886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 7906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Code* original_; 7916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ZoneList<Object**> rvalues_; 7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ZoneList<RelocInfo> reloc_infos_; 793791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block ZoneList<Address> code_entries_; 7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Finds all references to original and replaces them with substitution. 7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReplaceCodeObject(Code* original, Code* substitution) { 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!Heap::InNewSpace(substitution)); 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_allocations_please; 8026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // A zone scope for ReferenceCollectorVisitor. 8046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ZoneScope scope(DELETE_ON_EXIT); 8056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ReferenceCollectorVisitor visitor(original); 8076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Iterate over all roots. Stack frames may have pointer into original code, 8096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // so temporary replace the pointers with offset numbers 8106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // in prologue/epilogue. 8116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { 8126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Heap::IterateStrongRoots(&visitor, VISIT_ALL); 8136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Now iterate over all pointers of all objects, including code_target 8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // implicit pointers. 8176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HeapIterator iterator; 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { 8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block obj->Iterate(&visitor); 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block visitor.Replace(substitution); 8236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check whether the code is natural function code (not a lazy-compile stub 8276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// code). 8286ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsJSFunctionCode(Code* code) { 8296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return code->kind() == Code::FUNCTION; 8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Returns true if an instance of candidate were inlined into function's code. 834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) { 835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_gc; 836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false; 838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizationInputData* data = 840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizationInputData::cast(function->code()->deoptimization_data()); 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (data == Heap::empty_fixed_array()) return false; 843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FixedArray* literals = data->LiteralArray(); 845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int inlined_count = data->InlinedFunctionCount()->value(); 847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < inlined_count; ++i) { 848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JSFunction* inlined = JSFunction::cast(literals->get(i)); 849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (inlined->shared() == candidate) return true; 850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass DependentFunctionsDeoptimizingVisitor : public OptimizedFunctionVisitor { 857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit DependentFunctionsDeoptimizingVisitor( 859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SharedFunctionInfo* function_info) 860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : function_info_(function_info) {} 861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void EnterContext(Context* context) { 863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void VisitFunction(JSFunction* function) { 866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->shared() == function_info_ || 867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IsInlined(function, function_info_)) { 868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Deoptimizer::DeoptimizeFunction(function); 869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void LeaveContext(Context* context) { 873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SharedFunctionInfo* function_info_; 877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) { 881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_allocation; 882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DependentFunctionsDeoptimizingVisitor visitor(function_info); 884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Deoptimizer::VisitAllOptimizedFunctions(&visitor); 885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8885913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::ReplaceFunctionCode( 8895913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Handle<JSArray> new_compile_info_array, 8905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Handle<JSArray> shared_info_array) { 8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block HandleScope scope; 8926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!SharedInfoWrapper::IsInstance(shared_info_array)) { 8946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Top::ThrowIllegalOperation(); 8956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 8966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); 8986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SharedInfoWrapper shared_info_wrapper(shared_info_array); 8996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); 9016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (IsJSFunctionCode(shared_info->code())) { 9036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ReplaceCodeObject(shared_info->code(), 9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block *(compile_info_wrapper.GetFunctionCode())); 905756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo(); 906756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (code_scope_info->IsFixedArray()) { 907756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info)); 908756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 9096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (shared_info->debug_info()->IsDebugInfo()) { 9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info())); 9136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Code> new_original_code = 9146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Factory::CopyCode(compile_info_wrapper.GetFunctionCode()); 9156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block debug_info->set_original_code(*new_original_code); 9166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block shared_info->set_start_position(compile_info_wrapper.GetStartPosition()); 9196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block shared_info->set_end_position(compile_info_wrapper.GetEndPosition()); 9206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block shared_info->set_construct_stub( 9226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Builtins::builtin(Builtins::JSConstructStubGeneric)); 9236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeDependentFunctions(*shared_info); 925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompilationCache::Remove(shared_info); 926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Heap::undefined_value(); 928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochMaybeObject* LiveEdit::FunctionSourceUpdated( 932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSArray> shared_info_array) { 933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleScope scope; 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!SharedInfoWrapper::IsInstance(shared_info_array)) { 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Top::ThrowIllegalOperation(); 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SharedInfoWrapper shared_info_wrapper(shared_info_array); 940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo(); 941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizeDependentFunctions(*shared_info); 943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompilationCache::Remove(shared_info); 944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 9456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Heap::undefined_value(); 9466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 9476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9496ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper, 9506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> script_handle) { 9516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> shared_info = 9526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper)); 9536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block shared_info->set_script(*script_handle); 954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompilationCache::Remove(shared_info); 9566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 9576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// For a script text change (defined as position_change_array), translates 9606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// position in unchanged text to position in changed text. 9616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Text change is a set of non-overlapping regions in text, that have changed 9626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// their contents and length. It is specified as array of groups of 3 numbers: 9636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// (change_begin, change_end, change_end_new_position). 9646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Each group describes a change in text; groups are sorted by change_begin. 9656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Only position in text beyond any changes may be successfully translated. 9666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// If a positions is inside some region that changed, result is currently 9676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// undefined. 9686ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic int TranslatePosition(int original_position, 9696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> position_change_array) { 9706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int position_diff = 0; 9716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int array_len = Smi::cast(position_change_array->length())->value(); 9726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // TODO(635): binary search may be used here 9736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < array_len; i += 3) { 9745913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Object* element = position_change_array->GetElementNoExceptionThrown(i); 9755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int chunk_start = Smi::cast(element)->value(); 9766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (original_position < chunk_start) { 9776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 9786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9795913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck element = position_change_array->GetElementNoExceptionThrown(i + 1); 9805913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int chunk_end = Smi::cast(element)->value(); 9816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Position mustn't be inside a chunk. 9826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(original_position >= chunk_end); 9835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck element = position_change_array->GetElementNoExceptionThrown(i + 2); 9845913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int chunk_changed_end = Smi::cast(element)->value(); 9856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block position_diff = chunk_changed_end - chunk_end; 9866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 9876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return original_position + position_diff; 9896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 9906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Auto-growing buffer for writing relocation info code section. This buffer 9936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// is a simplified version of buffer from Assembler. Unlike Assembler, this 9946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// class is platform-independent and it works without dealing with instructions. 9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// As specified by RelocInfo format, the buffer is filled in reversed order: 9966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// from upper to lower addresses. 9976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// It uses NewArray/DeleteArray for memory management. 9986ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass RelocInfoBuffer { 9996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 10006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block RelocInfoBuffer(int buffer_initial_capicity, byte* pc) { 10016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_size_ = buffer_initial_capicity + kBufferGap; 10026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_ = NewArray<byte>(buffer_size_); 10036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc); 10056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ~RelocInfoBuffer() { 10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DeleteArray(buffer_); 10086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // As specified by RelocInfo format, the buffer is filled in reversed order: 10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // from upper to lower addresses. 10126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Write(const RelocInfo* rinfo) { 10136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) { 10146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Grow(); 10156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block reloc_info_writer_.Write(rinfo); 10176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Vector<byte> GetResult() { 10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the bytes from pos up to end of buffer. 10216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int result_size = 10226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer_.pos()); 10236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Vector<byte>(reloc_info_writer_.pos(), result_size); 10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Grow() { 10286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Compute new buffer size. 10296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int new_buffer_size; 10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (buffer_size_ < 2 * KB) { 10316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block new_buffer_size = 4 * KB; 10326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block new_buffer_size = 2 * buffer_size_; 10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Some internal data structures overflow for very large buffers, 10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // they must ensure that kMaximalBufferSize is not too large. 10376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (new_buffer_size > kMaximalBufferSize) { 10386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer"); 10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Setup new buffer. 10426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block byte* new_buffer = NewArray<byte>(new_buffer_size); 10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Copy the data. 10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int curently_used_size = 10466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static_cast<int>(buffer_ + buffer_size_ - reloc_info_writer_.pos()); 10476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block memmove(new_buffer + new_buffer_size - curently_used_size, 10486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block reloc_info_writer_.pos(), curently_used_size); 10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block reloc_info_writer_.Reposition( 10516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block new_buffer + new_buffer_size - curently_used_size, 10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block reloc_info_writer_.last_pc()); 10536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DeleteArray(buffer_); 10556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_ = new_buffer; 10566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_size_ = new_buffer_size; 10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block RelocInfoWriter reloc_info_writer_; 10606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block byte* buffer_; 10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int buffer_size_; 10626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke static const int kBufferGap = RelocInfoWriter::kMaxSize; 10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kMaximalBufferSize = 512*MB; 10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Patch positions in code (changes relocation info section) and possibly 10686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// returns new instance of code. 10696ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Code> PatchPositionsInCode(Handle<Code> code, 10706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> position_change_array) { 10716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block RelocInfoBuffer buffer_writer(code->relocation_size(), 10736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block code->instruction_start()); 10746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block { 10766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block AssertNoAllocation no_allocations_please; 10776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (RelocIterator it(*code); !it.done(); it.next()) { 10786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block RelocInfo* rinfo = it.rinfo(); 10796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (RelocInfo::IsPosition(rinfo->rmode())) { 10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int position = static_cast<int>(rinfo->data()); 10816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int new_position = TranslatePosition(position, 10826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block position_change_array); 10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (position != new_position) { 10846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position); 10856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_writer.Write(&info_copy); 10866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block continue; 10876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block buffer_writer.Write(it.rinfo()); 10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Vector<byte> buffer = buffer_writer.GetResult(); 10946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (buffer.length() == code->relocation_size()) { 10966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Simply patch relocation area of code. 10976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block memcpy(code->relocation_start(), buffer.start(), buffer.length()); 10986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return code; 10996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Relocation info section now has different size. We cannot simply 11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // rewrite it inside code object. Instead we have to create a new 11026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // code object. 11036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Code> result(Factory::CopyCode(code, buffer)); 11046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result; 11056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11095913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* LiveEdit::PatchFunctionPositions( 11106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) { 11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!SharedInfoWrapper::IsInstance(shared_info_array)) { 11136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Top::ThrowIllegalOperation(); 11146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SharedInfoWrapper shared_info_wrapper(shared_info_array); 11176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo(); 11186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int old_function_start = info->start_position(); 11206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int new_function_start = TranslatePosition(old_function_start, 11216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block position_change_array); 11226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block info->set_start_position(new_function_start); 11236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block info->set_end_position(TranslatePosition(info->end_position(), 11246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block position_change_array)); 11256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block info->set_function_token_position( 11276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block TranslatePosition(info->function_token_position(), 11286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block position_change_array)); 11296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (IsJSFunctionCode(info->code())) { 11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Patch relocation info section of the code. 11326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()), 11336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block position_change_array); 11346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (*patched_code != info->code()) { 11356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Replace all references to the code across the heap. In particular, 11366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // some stubs may refer to this code and this code may be being executed 11376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // on stack (it is safe to substitute the code object on stack, because 11386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // we only change the structure of rinfo and leave instructions 11396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // untouched). 11406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ReplaceCodeObject(info->code(), *patched_code); 11416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Heap::undefined_value(); 11456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11486ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic Handle<Script> CreateScriptCopy(Handle<Script> original) { 11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> original_source(String::cast(original->source())); 11506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Script> copy = Factory::NewScript(original_source); 11526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_name(original->name()); 11546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_line_offset(original->line_offset()); 11556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_column_offset(original->column_offset()); 11566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_data(original->data()); 11576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_type(original->type()); 11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_context_data(original->context_data()); 11596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_compilation_type(original->compilation_type()); 11606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_eval_from_shared(original->eval_from_shared()); 11616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block copy->set_eval_from_instructions_offset( 11626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block original->eval_from_instructions_offset()); 11636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return copy; 11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11686ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockObject* LiveEdit::ChangeScriptSource(Handle<Script> original_script, 11696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> new_source, 11706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> old_script_name) { 11716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> old_script_object; 11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (old_script_name->IsString()) { 11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Script> old_script = CreateScriptCopy(original_script); 11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block old_script->set_name(String::cast(*old_script_name)); 11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block old_script_object = old_script; 11766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING); 11776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 11786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block old_script_object = Handle<Object>(Heap::null_value()); 11796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block original_script->set_source(*new_source); 11826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Drop line ends so that they will be recalculated. 11846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block original_script->set_line_ends(Heap::undefined_value()); 11856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return *old_script_object; 11876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 11886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEdit::ReplaceRefToNestedFunction( 11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue> parent_function_wrapper, 11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue> orig_function_wrapper, 11946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSValue> subst_function_wrapper) { 11956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> parent_shared = 11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo>::cast(UnwrapJSValue(parent_function_wrapper)); 11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> orig_shared = 11996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo>::cast(UnwrapJSValue(orig_function_wrapper)); 12006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> subst_shared = 12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo>::cast(UnwrapJSValue(subst_function_wrapper)); 12026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) { 12046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) { 12056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (it.rinfo()->target_object() == *orig_shared) { 12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block it.rinfo()->set_target_object(*subst_shared); 12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Check an activation against list of functions. If there is a function 12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// that matches, its status in result array is changed to status argument value. 12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool CheckActivation(Handle<JSArray> shared_info_array, 1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSArray> result, 1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StackFrame* frame, 12186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LiveEdit::FunctionPatchabilityStatus status) { 1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!frame->is_java_script()) return false; 1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> function( 1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JSFunction::cast(JavaScriptFrame::cast(frame)->function())); 1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 12246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len = Smi::cast(shared_info_array->length())->value(); 12256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < len; i++) { 12265913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSValue* wrapper = 12275913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i)); 12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> shared( 12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SharedFunctionInfo::cast(wrapper->value())); 12306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->shared() == *shared || IsInlined(*function, *shared)) { 12326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(result, i, Handle<Smi>(Smi::FromInt(status))); 12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return true; 12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return false; 12376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Iterates over handler chain and removes all elements that are inside 12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames being dropped. 12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool FixTryCatchHandler(StackFrame* top_frame, 12436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame* bottom_frame) { 12446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Address* pointer_address = 12456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block &Memory::Address_at(Top::get_address_from_id(Top::k_handler_address)); 12466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block while (*pointer_address < top_frame->sp()) { 12486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pointer_address = &Memory::Address_at(*pointer_address); 12496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Address* above_frame_address = pointer_address; 12516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block while (*pointer_address < bottom_frame->fp()) { 12526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pointer_address = &Memory::Address_at(*pointer_address); 12536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool change = *above_frame_address != *pointer_address; 12556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block *above_frame_address = *pointer_address; 12566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return change; 12576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Removes specified range of frames from stack. There may be 1 or more 12616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// frames in range. Anyway the bottom frame is restarted rather than dropped, 12626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// and therefore has to be a JavaScript frame. 12636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Returns error message or NULL. 12646ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropFrames(Vector<StackFrame*> frames, 12656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int top_frame_index, 12668defd9ff6930b4e24729971a61cf7469daf119beSteve Block int bottom_js_frame_index, 1267bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Debug::FrameDropMode* mode, 1268bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object*** restarter_frame_function_pointer) { 1269756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (!Debug::kFrameDropperSupported) { 12708defd9ff6930b4e24729971a61cf7469daf119beSteve Block return "Stack manipulations are not supported in this architecture."; 12718defd9ff6930b4e24729971a61cf7469daf119beSteve Block } 12728defd9ff6930b4e24729971a61cf7469daf119beSteve Block 12736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame* pre_top_frame = frames[top_frame_index - 1]; 12746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame* top_frame = frames[top_frame_index]; 12756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; 12766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(bottom_js_frame->is_java_script()); 12786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check the nature of the top frame. 12806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (pre_top_frame->code()->is_inline_cache_stub() && 12816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pre_top_frame->code()->ic_state() == DEBUG_BREAK) { 12826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // OK, we can drop inline cache calls. 12838defd9ff6930b4e24729971a61cf7469daf119beSteve Block *mode = Debug::FRAME_DROPPED_IN_IC_CALL; 12848defd9ff6930b4e24729971a61cf7469daf119beSteve Block } else if (pre_top_frame->code() == Debug::debug_break_slot()) { 12858defd9ff6930b4e24729971a61cf7469daf119beSteve Block // OK, we can drop debug break slot. 12868defd9ff6930b4e24729971a61cf7469daf119beSteve Block *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL; 12876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (pre_top_frame->code() == 12886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Builtins::builtin(Builtins::FrameDropper_LiveEdit)) { 12896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // OK, we can drop our own code. 12908defd9ff6930b4e24729971a61cf7469daf119beSteve Block *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; 12916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else if (pre_top_frame->code()->kind() == Code::STUB && 12926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pre_top_frame->code()->major_key()) { 12938defd9ff6930b4e24729971a61cf7469daf119beSteve Block // Entry from our unit tests, it's fine, we support this case. 12948defd9ff6930b4e24729971a61cf7469daf119beSteve Block *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL; 12956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 12966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return "Unknown structure of stack above changing function"; 12976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 12986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Address unused_stack_top = top_frame->sp(); 13006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Address unused_stack_bottom = bottom_js_frame->fp() 13016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block - Debug::kFrameDropperFrameSize * kPointerSize // Size of the new frame. 13026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block + kPointerSize; // Bigger address end is exclusive. 13036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (unused_stack_top > unused_stack_bottom) { 13056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return "Not enough space for frame dropper frame"; 13066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Committing now. After this point we should return only NULL value. 13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FixTryCatchHandler(pre_top_frame, bottom_js_frame); 13116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Make sure FixTryCatchHandler is idempotent. 13126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); 13136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Code> code(Builtins::builtin(Builtins::FrameDropper_LiveEdit)); 13156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block top_frame->set_pc(code->entry()); 13166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block pre_top_frame->SetCallerFp(bottom_js_frame->fp()); 13176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1318bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch *restarter_frame_function_pointer = 1319bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Debug::SetUpFrameDropperFrame(bottom_js_frame, code); 1320bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1321bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch ASSERT((**restarter_frame_function_pointer)->IsJSFunction()); 13226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (Address a = unused_stack_top; 13246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block a < unused_stack_bottom; 13256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block a += kPointerSize) { 13266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Memory::Object_at(a) = Smi::FromInt(0); 13276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return NULL; 13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13336ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic bool IsDropableFrame(StackFrame* frame) { 13346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return !frame->is_exit(); 13356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 13366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Fills result array with statuses of functions. Modifies the stack 13386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// removing all listed function if possible and if do_drop is true. 13396ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const char* DropActivationsInActiveThread( 13406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) { 13416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ZoneScope scope(DELETE_ON_EXIT); 13436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Vector<StackFrame*> frames = CreateStackMap(); 13446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int array_len = Smi::cast(shared_info_array->length())->value(); 13466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int top_frame_index = -1; 13486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int frame_index = 0; 13496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (; frame_index < frames.length(); frame_index++) { 13506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame* frame = frames[frame_index]; 13516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frame->id() == Debug::break_frame_id()) { 13526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block top_frame_index = frame_index; 13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 13546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (CheckActivation(shared_info_array, result, frame, 13566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { 13576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We are still above break_frame. It is not a target frame, 13586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // it is a problem. 13596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return "Debugger mark-up on stack is not found"; 13606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (top_frame_index == -1) { 13646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We haven't found break frame, but no function is blocking us anyway. 13656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return NULL; 13666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool target_frame_found = false; 13696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int bottom_js_frame_index = top_frame_index; 13706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool c_code_found = false; 13716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (; frame_index < frames.length(); frame_index++) { 13736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame* frame = frames[frame_index]; 13746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!IsDropableFrame(frame)) { 13756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block c_code_found = true; 13766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 13776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (CheckActivation(shared_info_array, result, frame, 13796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block target_frame_found = true; 13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bottom_js_frame_index = frame_index; 13826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (c_code_found) { 13866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // There is a C frames on stack. Check that there are no target frames 13876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // below them. 13886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (; frame_index < frames.length(); frame_index++) { 13896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame* frame = frames[frame_index]; 13906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frame->is_java_script()) { 13916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (CheckActivation(shared_info_array, result, frame, 13926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) { 13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Cannot drop frame under C frames. 13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return NULL; 13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!do_drop) { 14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // We are in check-only mode. 14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return NULL; 14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (!target_frame_found) { 14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Nothing to drop. 14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return NULL; 14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14108defd9ff6930b4e24729971a61cf7469daf119beSteve Block Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED; 1411bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Object** restarter_frame_function_pointer = NULL; 14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* error_message = DropFrames(frames, top_frame_index, 1413bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch bottom_js_frame_index, &drop_mode, 1414bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch &restarter_frame_function_pointer); 14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (error_message != NULL) { 14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return error_message; 14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Adjust break_frame after some frames has been dropped. 14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StackFrame::Id new_id = StackFrame::NO_ID; 14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) { 14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frames[i]->type() == StackFrame::JAVA_SCRIPT) { 14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block new_id = frames[i]->id(); 14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block break; 14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 1428bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Debug::FramesHaveBeenDropped(new_id, drop_mode, 1429bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch restarter_frame_function_pointer); 14306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Replace "blocked on active" with "replaced on active" status. 14326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < array_len; i++) { 14336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result->GetElement(i) == 14346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) { 143580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Handle<Object> replaced( 143680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK)); 143780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetElement(result, i, replaced); 14386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return NULL; 14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 14426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14446ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass InactiveThreadActivationsChecker : public ThreadVisitor { 14456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public: 14466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array, 14476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> result) 14486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : shared_info_array_(shared_info_array), result_(result), 14496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block has_blocked_functions_(false) { 14506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void VisitThread(ThreadLocalTop* top) { 14526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (StackFrameIterator it(top); !it.done(); it.Advance()) { 14536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block has_blocked_functions_ |= CheckActivation( 14546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block shared_info_array_, result_, it.frame(), 14556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK); 14566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool HasBlockedFunctions() { 14596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return has_blocked_functions_; 14606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 14636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> shared_info_array_; 14646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> result_; 14656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool has_blocked_functions_; 14666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}; 14676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14696ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<JSArray> LiveEdit::CheckAndDropActivations( 14706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> shared_info_array, bool do_drop) { 14716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int len = Smi::cast(shared_info_array->length())->value(); 14726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<JSArray> result = Factory::NewJSArray(len); 14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Fill the default values. 14766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block for (int i = 0; i < len; i++) { 14776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(result, i, 14786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH))); 14796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // First check inactive threads. Fail if some functions are blocked there. 14836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array, 14846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result); 14857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ThreadManager::IterateArchivedThreads(&inactive_threads_checker); 14866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (inactive_threads_checker.HasBlockedFunctions()) { 14876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result; 14886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Try to drop activations from the current stack. 14916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const char* error_message = 14926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block DropActivationsInActiveThread(shared_info_array, result, do_drop); 14936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (error_message != NULL) { 14946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Add error message as an array extra element. 14956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Vector<const char> vector_message(error_message, StrLength(error_message)); 14966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> str = Factory::NewStringFromAscii(vector_message); 14976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetElement(result, len, str); 14986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 14996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return result; 15006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1503402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { 1504402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (active_function_info_listener != NULL) { 1505402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu active_function_info_listener->FunctionStarted(fun); 1506402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1507402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 15086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1510402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei PopescuLiveEditFunctionTracker::~LiveEditFunctionTracker() { 1511402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (active_function_info_listener != NULL) { 1512402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu active_function_info_listener->FunctionDone(); 1513402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1514402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 15156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15176ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo( 15186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { 1519402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (active_function_info_listener != NULL) { 15206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block active_function_info_listener->FunctionInfo(info, lit->scope()); 1521402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1522402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 15236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15256ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { 15266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block active_function_info_listener->FunctionCode(code); 1527402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 15286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1530402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescubool LiveEditFunctionTracker::IsActive() { 1531402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu return active_function_info_listener != NULL; 1532402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1533402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 15346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else // ENABLE_DEBUGGER_SUPPORT 15366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// This ifdef-else-endif section provides working or stub implementation of 15386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// LiveEditFunctionTracker. 15396ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { 15406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15436ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockLiveEditFunctionTracker::~LiveEditFunctionTracker() { 15446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15476ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordFunctionInfo( 15486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> info, FunctionLiteral* lit) { 15496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15526ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { 15536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool LiveEditFunctionTracker::IsActive() { 15576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return false; 15586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 15596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif // ENABLE_DEBUGGER_SUPPORT 15616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 15636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1564402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} } // namespace v8::internal 1565