Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 
     29 #include "v8.h"
     30 
     31 #include "liveedit.h"
     32 
     33 #include "code-stubs.h"
     34 #include "compilation-cache.h"
     35 #include "compiler.h"
     36 #include "debug.h"
     37 #include "deoptimizer.h"
     38 #include "global-handles.h"
     39 #include "messages.h"
     40 #include "parser.h"
     41 #include "scopeinfo.h"
     42 #include "scopes.h"
     43 #include "v8memory.h"
     44 
     45 namespace v8 {
     46 namespace internal {
     47 
     48 
     49 #ifdef ENABLE_DEBUGGER_SUPPORT
     50 
     51 
     52 void SetElementNonStrict(Handle<JSObject> object,
     53                          uint32_t index,
     54                          Handle<Object> value) {
     55   // Ignore return value from SetElement. It can only be a failure if there
     56   // are element setters causing exceptions and the debugger context has none
     57   // of these.
     58   Handle<Object> no_failure =
     59       JSObject::SetElement(object, index, value, NONE, kNonStrictMode);
     60   ASSERT(!no_failure.is_null());
     61   USE(no_failure);
     62 }
     63 
     64 
     65 // A simple implementation of dynamic programming algorithm. It solves
     66 // the problem of finding the difference of 2 arrays. It uses a table of results
     67 // of subproblems. Each cell contains a number together with 2-bit flag
     68 // that helps building the chunk list.
     69 class Differencer {
     70  public:
     71   explicit Differencer(Comparator::Input* input)
     72       : input_(input), len1_(input->GetLength1()), len2_(input->GetLength2()) {
     73     buffer_ = NewArray<int>(len1_ * len2_);
     74   }
     75   ~Differencer() {
     76     DeleteArray(buffer_);
     77   }
     78 
     79   void Initialize() {
     80     int array_size = len1_ * len2_;
     81     for (int i = 0; i < array_size; i++) {
     82       buffer_[i] = kEmptyCellValue;
     83     }
     84   }
     85 
     86   // Makes sure that result for the full problem is calculated and stored
     87   // in the table together with flags showing a path through subproblems.
     88   void FillTable() {
     89     CompareUpToTail(0, 0);
     90   }
     91 
     92   void SaveResult(Comparator::Output* chunk_writer) {
     93     ResultWriter writer(chunk_writer);
     94 
     95     int pos1 = 0;
     96     int pos2 = 0;
     97     while (true) {
     98       if (pos1 < len1_) {
     99         if (pos2 < len2_) {
    100           Direction dir = get_direction(pos1, pos2);
    101           switch (dir) {
    102             case EQ:
    103               writer.eq();
    104               pos1++;
    105               pos2++;
    106               break;
    107             case SKIP1:
    108               writer.skip1(1);
    109               pos1++;
    110               break;
    111             case SKIP2:
    112             case SKIP_ANY:
    113               writer.skip2(1);
    114               pos2++;
    115               break;
    116             default:
    117               UNREACHABLE();
    118           }
    119         } else {
    120           writer.skip1(len1_ - pos1);
    121           break;
    122         }
    123       } else {
    124         if (len2_ != pos2) {
    125           writer.skip2(len2_ - pos2);
    126         }
    127         break;
    128       }
    129     }
    130     writer.close();
    131   }
    132 
    133  private:
    134   Comparator::Input* input_;
    135   int* buffer_;
    136   int len1_;
    137   int len2_;
    138 
    139   enum Direction {
    140     EQ = 0,
    141     SKIP1,
    142     SKIP2,
    143     SKIP_ANY,
    144 
    145     MAX_DIRECTION_FLAG_VALUE = SKIP_ANY
    146   };
    147 
    148   // Computes result for a subtask and optionally caches it in the buffer table.
    149   // All results values are shifted to make space for flags in the lower bits.
    150   int CompareUpToTail(int pos1, int pos2) {
    151     if (pos1 < len1_) {
    152       if (pos2 < len2_) {
    153         int cached_res = get_value4(pos1, pos2);
    154         if (cached_res == kEmptyCellValue) {
    155           Direction dir;
    156           int res;
    157           if (input_->Equals(pos1, pos2)) {
    158             res = CompareUpToTail(pos1 + 1, pos2 + 1);
    159             dir = EQ;
    160           } else {
    161             int res1 = CompareUpToTail(pos1 + 1, pos2) +
    162                 (1 << kDirectionSizeBits);
    163             int res2 = CompareUpToTail(pos1, pos2 + 1) +
    164                 (1 << kDirectionSizeBits);
    165             if (res1 == res2) {
    166               res = res1;
    167               dir = SKIP_ANY;
    168             } else if (res1 < res2) {
    169               res = res1;
    170               dir = SKIP1;
    171             } else {
    172               res = res2;
    173               dir = SKIP2;
    174             }
    175           }
    176           set_value4_and_dir(pos1, pos2, res, dir);
    177           cached_res = res;
    178         }
    179         return cached_res;
    180       } else {
    181         return (len1_ - pos1) << kDirectionSizeBits;
    182       }
    183     } else {
    184       return (len2_ - pos2) << kDirectionSizeBits;
    185     }
    186   }
    187 
    188   inline int& get_cell(int i1, int i2) {
    189     return buffer_[i1 + i2 * len1_];
    190   }
    191 
    192   // Each cell keeps a value plus direction. Value is multiplied by 4.
    193   void set_value4_and_dir(int i1, int i2, int value4, Direction dir) {
    194     ASSERT((value4 & kDirectionMask) == 0);
    195     get_cell(i1, i2) = value4 | dir;
    196   }
    197 
    198   int get_value4(int i1, int i2) {
    199     return get_cell(i1, i2) & (kMaxUInt32 ^ kDirectionMask);
    200   }
    201   Direction get_direction(int i1, int i2) {
    202     return static_cast<Direction>(get_cell(i1, i2) & kDirectionMask);
    203   }
    204 
    205   static const int kDirectionSizeBits = 2;
    206   static const int kDirectionMask = (1 << kDirectionSizeBits) - 1;
    207   static const int kEmptyCellValue = -1 << kDirectionSizeBits;
    208 
    209   // This method only holds static assert statement (unfortunately you cannot
    210   // place one in class scope).
    211   void StaticAssertHolder() {
    212     STATIC_ASSERT(MAX_DIRECTION_FLAG_VALUE < (1 << kDirectionSizeBits));
    213   }
    214 
    215   class ResultWriter {
    216    public:
    217     explicit ResultWriter(Comparator::Output* chunk_writer)
    218         : chunk_writer_(chunk_writer), pos1_(0), pos2_(0),
    219           pos1_begin_(-1), pos2_begin_(-1), has_open_chunk_(false) {
    220     }
    221     void eq() {
    222       FlushChunk();
    223       pos1_++;
    224       pos2_++;
    225     }
    226     void skip1(int len1) {
    227       StartChunk();
    228       pos1_ += len1;
    229     }
    230     void skip2(int len2) {
    231       StartChunk();
    232       pos2_ += len2;
    233     }
    234     void close() {
    235       FlushChunk();
    236     }
    237 
    238    private:
    239     Comparator::Output* chunk_writer_;
    240     int pos1_;
    241     int pos2_;
    242     int pos1_begin_;
    243     int pos2_begin_;
    244     bool has_open_chunk_;
    245 
    246     void StartChunk() {
    247       if (!has_open_chunk_) {
    248         pos1_begin_ = pos1_;
    249         pos2_begin_ = pos2_;
    250         has_open_chunk_ = true;
    251       }
    252     }
    253 
    254     void FlushChunk() {
    255       if (has_open_chunk_) {
    256         chunk_writer_->AddChunk(pos1_begin_, pos2_begin_,
    257                                 pos1_ - pos1_begin_, pos2_ - pos2_begin_);
    258         has_open_chunk_ = false;
    259       }
    260     }
    261   };
    262 };
    263 
    264 
    265 void Comparator::CalculateDifference(Comparator::Input* input,
    266                                      Comparator::Output* result_writer) {
    267   Differencer differencer(input);
    268   differencer.Initialize();
    269   differencer.FillTable();
    270   differencer.SaveResult(result_writer);
    271 }
    272 
    273 
    274 static bool CompareSubstrings(Handle<String> s1, int pos1,
    275                               Handle<String> s2, int pos2, int len) {
    276   for (int i = 0; i < len; i++) {
    277     if (s1->Get(i + pos1) != s2->Get(i + pos2)) {
    278       return false;
    279     }
    280   }
    281   return true;
    282 }
    283 
    284 
    285 // Additional to Input interface. Lets switch Input range to subrange.
    286 // More elegant way would be to wrap one Input as another Input object
    287 // and translate positions there, but that would cost us additional virtual
    288 // call per comparison.
    289 class SubrangableInput : public Comparator::Input {
    290  public:
    291   virtual void SetSubrange1(int offset, int len) = 0;
    292   virtual void SetSubrange2(int offset, int len) = 0;
    293 };
    294 
    295 
    296 class SubrangableOutput : public Comparator::Output {
    297  public:
    298   virtual void SetSubrange1(int offset, int len) = 0;
    299   virtual void SetSubrange2(int offset, int len) = 0;
    300 };
    301 
    302 
    303 static int min(int a, int b) {
    304   return a < b ? a : b;
    305 }
    306 
    307 
    308 // Finds common prefix and suffix in input. This parts shouldn't take space in
    309 // linear programming table. Enable subranging in input and output.
    310 static void NarrowDownInput(SubrangableInput* input,
    311     SubrangableOutput* output) {
    312   const int len1 = input->GetLength1();
    313   const int len2 = input->GetLength2();
    314 
    315   int common_prefix_len;
    316   int common_suffix_len;
    317 
    318   {
    319     common_prefix_len = 0;
    320     int prefix_limit = min(len1, len2);
    321     while (common_prefix_len < prefix_limit &&
    322         input->Equals(common_prefix_len, common_prefix_len)) {
    323       common_prefix_len++;
    324     }
    325 
    326     common_suffix_len = 0;
    327     int suffix_limit = min(len1 - common_prefix_len, len2 - common_prefix_len);
    328 
    329     while (common_suffix_len < suffix_limit &&
    330         input->Equals(len1 - common_suffix_len - 1,
    331         len2 - common_suffix_len - 1)) {
    332       common_suffix_len++;
    333     }
    334   }
    335 
    336   if (common_prefix_len > 0 || common_suffix_len > 0) {
    337     int new_len1 = len1 - common_suffix_len - common_prefix_len;
    338     int new_len2 = len2 - common_suffix_len - common_prefix_len;
    339 
    340     input->SetSubrange1(common_prefix_len, new_len1);
    341     input->SetSubrange2(common_prefix_len, new_len2);
    342 
    343     output->SetSubrange1(common_prefix_len, new_len1);
    344     output->SetSubrange2(common_prefix_len, new_len2);
    345   }
    346 }
    347 
    348 
    349 // A helper class that writes chunk numbers into JSArray.
    350 // Each chunk is stored as 3 array elements: (pos1_begin, pos1_end, pos2_end).
    351 class CompareOutputArrayWriter {
    352  public:
    353   explicit CompareOutputArrayWriter(Isolate* isolate)
    354       : array_(isolate->factory()->NewJSArray(10)), current_size_(0) {}
    355 
    356   Handle<JSArray> GetResult() {
    357     return array_;
    358   }
    359 
    360   void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) {
    361     Isolate* isolate = array_->GetIsolate();
    362     SetElementNonStrict(array_,
    363                         current_size_,
    364                         Handle<Object>(Smi::FromInt(char_pos1), isolate));
    365     SetElementNonStrict(array_,
    366                         current_size_ + 1,
    367                         Handle<Object>(Smi::FromInt(char_pos1 + char_len1),
    368                                        isolate));
    369     SetElementNonStrict(array_,
    370                         current_size_ + 2,
    371                         Handle<Object>(Smi::FromInt(char_pos2 + char_len2),
    372                                        isolate));
    373     current_size_ += 3;
    374   }
    375 
    376  private:
    377   Handle<JSArray> array_;
    378   int current_size_;
    379 };
    380 
    381 
    382 // Represents 2 strings as 2 arrays of tokens.
    383 // TODO(LiveEdit): Currently it's actually an array of charactres.
    384 //     Make array of tokens instead.
    385 class TokensCompareInput : public Comparator::Input {
    386  public:
    387   TokensCompareInput(Handle<String> s1, int offset1, int len1,
    388                        Handle<String> s2, int offset2, int len2)
    389       : s1_(s1), offset1_(offset1), len1_(len1),
    390         s2_(s2), offset2_(offset2), len2_(len2) {
    391   }
    392   virtual int GetLength1() {
    393     return len1_;
    394   }
    395   virtual int GetLength2() {
    396     return len2_;
    397   }
    398   bool Equals(int index1, int index2) {
    399     return s1_->Get(offset1_ + index1) == s2_->Get(offset2_ + index2);
    400   }
    401 
    402  private:
    403   Handle<String> s1_;
    404   int offset1_;
    405   int len1_;
    406   Handle<String> s2_;
    407   int offset2_;
    408   int len2_;
    409 };
    410 
    411 
    412 // Stores compare result in JSArray. Converts substring positions
    413 // to absolute positions.
    414 class TokensCompareOutput : public Comparator::Output {
    415  public:
    416   TokensCompareOutput(CompareOutputArrayWriter* array_writer,
    417                       int offset1, int offset2)
    418         : array_writer_(array_writer), offset1_(offset1), offset2_(offset2) {
    419   }
    420 
    421   void AddChunk(int pos1, int pos2, int len1, int len2) {
    422     array_writer_->WriteChunk(pos1 + offset1_, pos2 + offset2_, len1, len2);
    423   }
    424 
    425  private:
    426   CompareOutputArrayWriter* array_writer_;
    427   int offset1_;
    428   int offset2_;
    429 };
    430 
    431 
    432 // Wraps raw n-elements line_ends array as a list of n+1 lines. The last line
    433 // never has terminating new line character.
    434 class LineEndsWrapper {
    435  public:
    436   explicit LineEndsWrapper(Handle<String> string)
    437       : ends_array_(CalculateLineEnds(string, false)),
    438         string_len_(string->length()) {
    439   }
    440   int length() {
    441     return ends_array_->length() + 1;
    442   }
    443   // Returns start for any line including start of the imaginary line after
    444   // the last line.
    445   int GetLineStart(int index) {
    446     if (index == 0) {
    447       return 0;
    448     } else {
    449       return GetLineEnd(index - 1);
    450     }
    451   }
    452   int GetLineEnd(int index) {
    453     if (index == ends_array_->length()) {
    454       // End of the last line is always an end of the whole string.
    455       // If the string ends with a new line character, the last line is an
    456       // empty string after this character.
    457       return string_len_;
    458     } else {
    459       return GetPosAfterNewLine(index);
    460     }
    461   }
    462 
    463  private:
    464   Handle<FixedArray> ends_array_;
    465   int string_len_;
    466 
    467   int GetPosAfterNewLine(int index) {
    468     return Smi::cast(ends_array_->get(index))->value() + 1;
    469   }
    470 };
    471 
    472 
    473 // Represents 2 strings as 2 arrays of lines.
    474 class LineArrayCompareInput : public SubrangableInput {
    475  public:
    476   LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
    477                         LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
    478       : s1_(s1), s2_(s2), line_ends1_(line_ends1),
    479         line_ends2_(line_ends2),
    480         subrange_offset1_(0), subrange_offset2_(0),
    481         subrange_len1_(line_ends1_.length()),
    482         subrange_len2_(line_ends2_.length()) {
    483   }
    484   int GetLength1() {
    485     return subrange_len1_;
    486   }
    487   int GetLength2() {
    488     return subrange_len2_;
    489   }
    490   bool Equals(int index1, int index2) {
    491     index1 += subrange_offset1_;
    492     index2 += subrange_offset2_;
    493 
    494     int line_start1 = line_ends1_.GetLineStart(index1);
    495     int line_start2 = line_ends2_.GetLineStart(index2);
    496     int line_end1 = line_ends1_.GetLineEnd(index1);
    497     int line_end2 = line_ends2_.GetLineEnd(index2);
    498     int len1 = line_end1 - line_start1;
    499     int len2 = line_end2 - line_start2;
    500     if (len1 != len2) {
    501       return false;
    502     }
    503     return CompareSubstrings(s1_, line_start1, s2_, line_start2,
    504                              len1);
    505   }
    506   void SetSubrange1(int offset, int len) {
    507     subrange_offset1_ = offset;
    508     subrange_len1_ = len;
    509   }
    510   void SetSubrange2(int offset, int len) {
    511     subrange_offset2_ = offset;
    512     subrange_len2_ = len;
    513   }
    514 
    515  private:
    516   Handle<String> s1_;
    517   Handle<String> s2_;
    518   LineEndsWrapper line_ends1_;
    519   LineEndsWrapper line_ends2_;
    520   int subrange_offset1_;
    521   int subrange_offset2_;
    522   int subrange_len1_;
    523   int subrange_len2_;
    524 };
    525 
    526 
    527 // Stores compare result in JSArray. For each chunk tries to conduct
    528 // a fine-grained nested diff token-wise.
    529 class TokenizingLineArrayCompareOutput : public SubrangableOutput {
    530  public:
    531   TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1,
    532                                    LineEndsWrapper line_ends2,
    533                                    Handle<String> s1, Handle<String> s2)
    534       : array_writer_(s1->GetIsolate()),
    535         line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2),
    536         subrange_offset1_(0), subrange_offset2_(0) {
    537   }
    538 
    539   void AddChunk(int line_pos1, int line_pos2, int line_len1, int line_len2) {
    540     line_pos1 += subrange_offset1_;
    541     line_pos2 += subrange_offset2_;
    542 
    543     int char_pos1 = line_ends1_.GetLineStart(line_pos1);
    544     int char_pos2 = line_ends2_.GetLineStart(line_pos2);
    545     int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
    546     int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
    547 
    548     if (char_len1 < CHUNK_LEN_LIMIT && char_len2 < CHUNK_LEN_LIMIT) {
    549       // Chunk is small enough to conduct a nested token-level diff.
    550       HandleScope subTaskScope(s1_->GetIsolate());
    551 
    552       TokensCompareInput tokens_input(s1_, char_pos1, char_len1,
    553                                       s2_, char_pos2, char_len2);
    554       TokensCompareOutput tokens_output(&array_writer_, char_pos1,
    555                                           char_pos2);
    556 
    557       Comparator::CalculateDifference(&tokens_input, &tokens_output);
    558     } else {
    559       array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2);
    560     }
    561   }
    562   void SetSubrange1(int offset, int len) {
    563     subrange_offset1_ = offset;
    564   }
    565   void SetSubrange2(int offset, int len) {
    566     subrange_offset2_ = offset;
    567   }
    568 
    569   Handle<JSArray> GetResult() {
    570     return array_writer_.GetResult();
    571   }
    572 
    573  private:
    574   static const int CHUNK_LEN_LIMIT = 800;
    575 
    576   CompareOutputArrayWriter array_writer_;
    577   LineEndsWrapper line_ends1_;
    578   LineEndsWrapper line_ends2_;
    579   Handle<String> s1_;
    580   Handle<String> s2_;
    581   int subrange_offset1_;
    582   int subrange_offset2_;
    583 };
    584 
    585 
    586 Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
    587                                          Handle<String> s2) {
    588   s1 = FlattenGetString(s1);
    589   s2 = FlattenGetString(s2);
    590 
    591   LineEndsWrapper line_ends1(s1);
    592   LineEndsWrapper line_ends2(s2);
    593 
    594   LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
    595   TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
    596 
    597   NarrowDownInput(&input, &output);
    598 
    599   Comparator::CalculateDifference(&input, &output);
    600 
    601   return output.GetResult();
    602 }
    603 
    604 
    605 static void CompileScriptForTracker(Isolate* isolate, Handle<Script> script) {
    606   // TODO(635): support extensions.
    607   PostponeInterruptsScope postpone(isolate);
    608 
    609   // Build AST.
    610   CompilationInfoWithZone info(script);
    611   info.MarkAsGlobal();
    612   // Parse and don't allow skipping lazy functions.
    613   if (Parser::Parse(&info)) {
    614     // Compile the code.
    615     LiveEditFunctionTracker tracker(info.isolate(), info.function());
    616     if (Compiler::MakeCodeForLiveEdit(&info)) {
    617       ASSERT(!info.code().is_null());
    618       tracker.RecordRootFunctionInfo(info.code());
    619     } else {
    620       info.isolate()->StackOverflow();
    621     }
    622   }
    623 }
    624 
    625 
    626 // Unwraps JSValue object, returning its field "value"
    627 static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
    628   return Handle<Object>(jsValue->value(), jsValue->GetIsolate());
    629 }
    630 
    631 
    632 // Wraps any object into a OpaqueReference, that will hide the object
    633 // from JavaScript.
    634 static Handle<JSValue> WrapInJSValue(Handle<HeapObject> object) {
    635   Isolate* isolate = object->GetIsolate();
    636   Handle<JSFunction> constructor = isolate->opaque_reference_function();
    637   Handle<JSValue> result =
    638       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
    639   result->set_value(*object);
    640   return result;
    641 }
    642 
    643 
    644 static Handle<SharedFunctionInfo> UnwrapSharedFunctionInfoFromJSValue(
    645     Handle<JSValue> jsValue) {
    646   Object* shared = jsValue->value();
    647   CHECK(shared->IsSharedFunctionInfo());
    648   return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(shared));
    649 }
    650 
    651 
    652 static int GetArrayLength(Handle<JSArray> array) {
    653   Object* length = array->length();
    654   CHECK(length->IsSmi());
    655   return Smi::cast(length)->value();
    656 }
    657 
    658 
    659 // Simple helper class that creates more or less typed structures over
    660 // JSArray object. This is an adhoc method of passing structures from C++
    661 // to JavaScript.
    662 template<typename S>
    663 class JSArrayBasedStruct {
    664  public:
    665   static S Create(Isolate* isolate) {
    666     Factory* factory = isolate->factory();
    667     Handle<JSArray> array = factory->NewJSArray(S::kSize_);
    668     return S(array);
    669   }
    670   static S cast(Object* object) {
    671     JSArray* array = JSArray::cast(object);
    672     Handle<JSArray> array_handle(array);
    673     return S(array_handle);
    674   }
    675   explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
    676   }
    677   Handle<JSArray> GetJSArray() {
    678     return array_;
    679   }
    680   Isolate* isolate() const {
    681     return array_->GetIsolate();
    682   }
    683 
    684  protected:
    685   void SetField(int field_position, Handle<Object> value) {
    686     SetElementNonStrict(array_, field_position, value);
    687   }
    688   void SetSmiValueField(int field_position, int value) {
    689     SetElementNonStrict(array_,
    690                         field_position,
    691                         Handle<Smi>(Smi::FromInt(value), isolate()));
    692   }
    693   Object* GetField(int field_position) {
    694     return array_->GetElementNoExceptionThrown(isolate(), field_position);
    695   }
    696   int GetSmiValueField(int field_position) {
    697     Object* res = GetField(field_position);
    698     CHECK(res->IsSmi());
    699     return Smi::cast(res)->value();
    700   }
    701 
    702  private:
    703   Handle<JSArray> array_;
    704 };
    705 
    706 
    707 // Represents some function compilation details. This structure will be used
    708 // from JavaScript. It contains Code object, which is kept wrapped
    709 // into a BlindReference for sanitizing reasons.
    710 class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
    711  public:
    712   explicit FunctionInfoWrapper(Handle<JSArray> array)
    713       : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
    714   }
    715   void SetInitialProperties(Handle<String> name, int start_position,
    716                             int end_position, int param_num,
    717                             int literal_count, int parent_index) {
    718     HandleScope scope(isolate());
    719     this->SetField(kFunctionNameOffset_, name);
    720     this->SetSmiValueField(kStartPositionOffset_, start_position);
    721     this->SetSmiValueField(kEndPositionOffset_, end_position);
    722     this->SetSmiValueField(kParamNumOffset_, param_num);
    723     this->SetSmiValueField(kLiteralNumOffset_, literal_count);
    724     this->SetSmiValueField(kParentIndexOffset_, parent_index);
    725   }
    726   void SetFunctionCode(Handle<Code> function_code,
    727       Handle<HeapObject> code_scope_info) {
    728     Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
    729     this->SetField(kCodeOffset_, code_wrapper);
    730 
    731     Handle<JSValue> scope_wrapper = WrapInJSValue(code_scope_info);
    732     this->SetField(kCodeScopeInfoOffset_, scope_wrapper);
    733   }
    734   void SetFunctionScopeInfo(Handle<Object> scope_info_array) {
    735     this->SetField(kFunctionScopeInfoOffset_, scope_info_array);
    736   }
    737   void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info) {
    738     Handle<JSValue> info_holder = WrapInJSValue(info);
    739     this->SetField(kSharedFunctionInfoOffset_, info_holder);
    740   }
    741   int GetLiteralCount() {
    742     return this->GetSmiValueField(kLiteralNumOffset_);
    743   }
    744   int GetParentIndex() {
    745     return this->GetSmiValueField(kParentIndexOffset_);
    746   }
    747   Handle<Code> GetFunctionCode() {
    748     Object* element = this->GetField(kCodeOffset_);
    749     CHECK(element->IsJSValue());
    750     Handle<JSValue> value_wrapper(JSValue::cast(element));
    751     Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
    752     CHECK(raw_result->IsCode());
    753     return Handle<Code>::cast(raw_result);
    754   }
    755   Handle<Object> GetCodeScopeInfo() {
    756     Object* element = this->GetField(kCodeScopeInfoOffset_);
    757     CHECK(element->IsJSValue());
    758     return UnwrapJSValue(Handle<JSValue>(JSValue::cast(element)));
    759   }
    760   int GetStartPosition() {
    761     return this->GetSmiValueField(kStartPositionOffset_);
    762   }
    763   int GetEndPosition() {
    764     return this->GetSmiValueField(kEndPositionOffset_);
    765   }
    766 
    767  private:
    768   static const int kFunctionNameOffset_ = 0;
    769   static const int kStartPositionOffset_ = 1;
    770   static const int kEndPositionOffset_ = 2;
    771   static const int kParamNumOffset_ = 3;
    772   static const int kCodeOffset_ = 4;
    773   static const int kCodeScopeInfoOffset_ = 5;
    774   static const int kFunctionScopeInfoOffset_ = 6;
    775   static const int kParentIndexOffset_ = 7;
    776   static const int kSharedFunctionInfoOffset_ = 8;
    777   static const int kLiteralNumOffset_ = 9;
    778   static const int kSize_ = 10;
    779 
    780   friend class JSArrayBasedStruct<FunctionInfoWrapper>;
    781 };
    782 
    783 
    784 // Wraps SharedFunctionInfo along with some of its fields for passing it
    785 // back to JavaScript. SharedFunctionInfo object itself is additionally
    786 // wrapped into BlindReference for sanitizing reasons.
    787 class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
    788  public:
    789   static bool IsInstance(Handle<JSArray> array) {
    790     return array->length() == Smi::FromInt(kSize_) &&
    791         array->GetElementNoExceptionThrown(
    792             array->GetIsolate(), kSharedInfoOffset_)->IsJSValue();
    793   }
    794 
    795   explicit SharedInfoWrapper(Handle<JSArray> array)
    796       : JSArrayBasedStruct<SharedInfoWrapper>(array) {
    797   }
    798 
    799   void SetProperties(Handle<String> name, int start_position, int end_position,
    800                      Handle<SharedFunctionInfo> info) {
    801     HandleScope scope(isolate());
    802     this->SetField(kFunctionNameOffset_, name);
    803     Handle<JSValue> info_holder = WrapInJSValue(info);
    804     this->SetField(kSharedInfoOffset_, info_holder);
    805     this->SetSmiValueField(kStartPositionOffset_, start_position);
    806     this->SetSmiValueField(kEndPositionOffset_, end_position);
    807   }
    808   Handle<SharedFunctionInfo> GetInfo() {
    809     Object* element = this->GetField(kSharedInfoOffset_);
    810     CHECK(element->IsJSValue());
    811     Handle<JSValue> value_wrapper(JSValue::cast(element));
    812     return UnwrapSharedFunctionInfoFromJSValue(value_wrapper);
    813   }
    814 
    815  private:
    816   static const int kFunctionNameOffset_ = 0;
    817   static const int kStartPositionOffset_ = 1;
    818   static const int kEndPositionOffset_ = 2;
    819   static const int kSharedInfoOffset_ = 3;
    820   static const int kSize_ = 4;
    821 
    822   friend class JSArrayBasedStruct<SharedInfoWrapper>;
    823 };
    824 
    825 
    826 class FunctionInfoListener {
    827  public:
    828   explicit FunctionInfoListener(Isolate* isolate) {
    829     current_parent_index_ = -1;
    830     len_ = 0;
    831     result_ = isolate->factory()->NewJSArray(10);
    832   }
    833 
    834   void FunctionStarted(FunctionLiteral* fun) {
    835     HandleScope scope(isolate());
    836     FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate());
    837     info.SetInitialProperties(fun->name(), fun->start_position(),
    838                               fun->end_position(), fun->parameter_count(),
    839                               fun->materialized_literal_count(),
    840                               current_parent_index_);
    841     current_parent_index_ = len_;
    842     SetElementNonStrict(result_, len_, info.GetJSArray());
    843     len_++;
    844   }
    845 
    846   void FunctionDone() {
    847     HandleScope scope(isolate());
    848     FunctionInfoWrapper info =
    849         FunctionInfoWrapper::cast(
    850             result_->GetElementNoExceptionThrown(
    851                 isolate(), current_parent_index_));
    852     current_parent_index_ = info.GetParentIndex();
    853   }
    854 
    855   // Saves only function code, because for a script function we
    856   // may never create a SharedFunctionInfo object.
    857   void FunctionCode(Handle<Code> function_code) {
    858     FunctionInfoWrapper info =
    859         FunctionInfoWrapper::cast(
    860             result_->GetElementNoExceptionThrown(
    861                 isolate(), current_parent_index_));
    862     info.SetFunctionCode(function_code,
    863                          Handle<HeapObject>(isolate()->heap()->null_value()));
    864   }
    865 
    866   // Saves full information about a function: its code, its scope info
    867   // and a SharedFunctionInfo object.
    868   void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope,
    869                     Zone* zone) {
    870     if (!shared->IsSharedFunctionInfo()) {
    871       return;
    872     }
    873     FunctionInfoWrapper info =
    874         FunctionInfoWrapper::cast(
    875             result_->GetElementNoExceptionThrown(
    876                 isolate(), current_parent_index_));
    877     info.SetFunctionCode(Handle<Code>(shared->code()),
    878                          Handle<HeapObject>(shared->scope_info()));
    879     info.SetSharedFunctionInfo(shared);
    880 
    881     Handle<Object> scope_info_list(SerializeFunctionScope(scope, zone),
    882                                    isolate());
    883     info.SetFunctionScopeInfo(scope_info_list);
    884   }
    885 
    886   Handle<JSArray> GetResult() { return result_; }
    887 
    888  private:
    889   Isolate* isolate() const { return result_->GetIsolate(); }
    890 
    891   Object* SerializeFunctionScope(Scope* scope, Zone* zone) {
    892     HandleScope handle_scope(isolate());
    893 
    894     Handle<JSArray> scope_info_list = isolate()->factory()->NewJSArray(10);
    895     int scope_info_length = 0;
    896 
    897     // Saves some description of scope. It stores name and indexes of
    898     // variables in the whole scope chain. Null-named slots delimit
    899     // scopes of this chain.
    900     Scope* current_scope = scope;
    901     while (current_scope != NULL) {
    902       ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone);
    903       ZoneList<Variable*> context_list(
    904           current_scope->ContextLocalCount(), zone);
    905       current_scope->CollectStackAndContextLocals(&stack_list, &context_list);
    906       context_list.Sort(&Variable::CompareIndex);
    907 
    908       for (int i = 0; i < context_list.length(); i++) {
    909         SetElementNonStrict(scope_info_list,
    910                             scope_info_length,
    911                             context_list[i]->name());
    912         scope_info_length++;
    913         SetElementNonStrict(
    914             scope_info_list,
    915             scope_info_length,
    916             Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate()));
    917         scope_info_length++;
    918       }
    919       SetElementNonStrict(scope_info_list,
    920                           scope_info_length,
    921                           Handle<Object>(isolate()->heap()->null_value(),
    922                                          isolate()));
    923       scope_info_length++;
    924 
    925       current_scope = current_scope->outer_scope();
    926     }
    927 
    928     return *scope_info_list;
    929   }
    930 
    931   Handle<JSArray> result_;
    932   int len_;
    933   int current_parent_index_;
    934 };
    935 
    936 
    937 JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
    938                                      Handle<String> source) {
    939   Isolate* isolate = script->GetIsolate();
    940 
    941   FunctionInfoListener listener(isolate);
    942   Handle<Object> original_source =
    943       Handle<Object>(script->source(), isolate);
    944   script->set_source(*source);
    945   isolate->set_active_function_info_listener(&listener);
    946 
    947   {
    948     // Creating verbose TryCatch from public API is currently the only way to
    949     // force code save location. We do not use this the object directly.
    950     v8::TryCatch try_catch;
    951     try_catch.SetVerbose(true);
    952 
    953     // A logical 'try' section.
    954     CompileScriptForTracker(isolate, script);
    955   }
    956 
    957   // A logical 'catch' section.
    958   Handle<JSObject> rethrow_exception;
    959   if (isolate->has_pending_exception()) {
    960     Handle<Object> exception(isolate->pending_exception()->ToObjectChecked(),
    961                              isolate);
    962     MessageLocation message_location = isolate->GetMessageLocation();
    963 
    964     isolate->clear_pending_message();
    965     isolate->clear_pending_exception();
    966 
    967     // If possible, copy positions from message object to exception object.
    968     if (exception->IsJSObject() && !message_location.script().is_null()) {
    969       rethrow_exception = Handle<JSObject>::cast(exception);
    970 
    971       Factory* factory = isolate->factory();
    972       Handle<String> start_pos_key = factory->InternalizeOneByteString(
    973           STATIC_ASCII_VECTOR("startPosition"));
    974       Handle<String> end_pos_key = factory->InternalizeOneByteString(
    975           STATIC_ASCII_VECTOR("endPosition"));
    976       Handle<String> script_obj_key = factory->InternalizeOneByteString(
    977           STATIC_ASCII_VECTOR("scriptObject"));
    978       Handle<Smi> start_pos(
    979           Smi::FromInt(message_location.start_pos()), isolate);
    980       Handle<Smi> end_pos(Smi::FromInt(message_location.end_pos()), isolate);
    981       Handle<JSValue> script_obj = GetScriptWrapper(message_location.script());
    982       JSReceiver::SetProperty(
    983           rethrow_exception, start_pos_key, start_pos, NONE, kNonStrictMode);
    984       JSReceiver::SetProperty(
    985           rethrow_exception, end_pos_key, end_pos, NONE, kNonStrictMode);
    986       JSReceiver::SetProperty(
    987           rethrow_exception, script_obj_key, script_obj, NONE, kNonStrictMode);
    988     }
    989   }
    990 
    991   // A logical 'finally' section.
    992   isolate->set_active_function_info_listener(NULL);
    993   script->set_source(*original_source);
    994 
    995   if (rethrow_exception.is_null()) {
    996     return *(listener.GetResult());
    997   } else {
    998     isolate->Throw(*rethrow_exception);
    999     return 0;
   1000   }
   1001 }
   1002 
   1003 
   1004 void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
   1005   Isolate* isolate = array->GetIsolate();
   1006   HandleScope scope(isolate);
   1007   int len = GetArrayLength(array);
   1008   for (int i = 0; i < len; i++) {
   1009     Handle<SharedFunctionInfo> info(
   1010         SharedFunctionInfo::cast(
   1011             array->GetElementNoExceptionThrown(isolate, i)));
   1012     SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
   1013     Handle<String> name_handle(String::cast(info->name()));
   1014     info_wrapper.SetProperties(name_handle, info->start_position(),
   1015                                info->end_position(), info);
   1016     SetElementNonStrict(array, i, info_wrapper.GetJSArray());
   1017   }
   1018 }
   1019 
   1020 
   1021 // Visitor that finds all references to a particular code object,
   1022 // including "CODE_TARGET" references in other code objects and replaces
   1023 // them on the fly.
   1024 class ReplacingVisitor : public ObjectVisitor {
   1025  public:
   1026   explicit ReplacingVisitor(Code* original, Code* substitution)
   1027     : original_(original), substitution_(substitution) {
   1028   }
   1029 
   1030   virtual void VisitPointers(Object** start, Object** end) {
   1031     for (Object** p = start; p < end; p++) {
   1032       if (*p == original_) {
   1033         *p = substitution_;
   1034       }
   1035     }
   1036   }
   1037 
   1038   virtual void VisitCodeEntry(Address entry) {
   1039     if (Code::GetObjectFromEntryAddress(entry) == original_) {
   1040       Address substitution_entry = substitution_->instruction_start();
   1041       Memory::Address_at(entry) = substitution_entry;
   1042     }
   1043   }
   1044 
   1045   virtual void VisitCodeTarget(RelocInfo* rinfo) {
   1046     if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
   1047         Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
   1048       Address substitution_entry = substitution_->instruction_start();
   1049       rinfo->set_target_address(substitution_entry);
   1050     }
   1051   }
   1052 
   1053   virtual void VisitDebugTarget(RelocInfo* rinfo) {
   1054     VisitCodeTarget(rinfo);
   1055   }
   1056 
   1057  private:
   1058   Code* original_;
   1059   Code* substitution_;
   1060 };
   1061 
   1062 
   1063 // Finds all references to original and replaces them with substitution.
   1064 static void ReplaceCodeObject(Handle<Code> original,
   1065                               Handle<Code> substitution) {
   1066   // Perform a full GC in order to ensure that we are not in the middle of an
   1067   // incremental marking phase when we are replacing the code object.
   1068   // Since we are not in an incremental marking phase we can write pointers
   1069   // to code objects (that are never in new space) without worrying about
   1070   // write barriers.
   1071   Heap* heap = original->GetHeap();
   1072   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
   1073                           "liveedit.cc ReplaceCodeObject");
   1074 
   1075   ASSERT(!heap->InNewSpace(*substitution));
   1076 
   1077   DisallowHeapAllocation no_allocation;
   1078 
   1079   ReplacingVisitor visitor(*original, *substitution);
   1080 
   1081   // Iterate over all roots. Stack frames may have pointer into original code,
   1082   // so temporary replace the pointers with offset numbers
   1083   // in prologue/epilogue.
   1084   heap->IterateRoots(&visitor, VISIT_ALL);
   1085 
   1086   // Now iterate over all pointers of all objects, including code_target
   1087   // implicit pointers.
   1088   HeapIterator iterator(heap);
   1089   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
   1090     obj->Iterate(&visitor);
   1091   }
   1092 }
   1093 
   1094 
   1095 // Patch function literals.
   1096 // Name 'literals' is a misnomer. Rather it's a cache for complex object
   1097 // boilerplates and for a native context. We must clean cached values.
   1098 // Additionally we may need to allocate a new array if number of literals
   1099 // changed.
   1100 class LiteralFixer {
   1101  public:
   1102   static void PatchLiterals(FunctionInfoWrapper* compile_info_wrapper,
   1103                             Handle<SharedFunctionInfo> shared_info,
   1104                             Isolate* isolate) {
   1105     int new_literal_count = compile_info_wrapper->GetLiteralCount();
   1106     if (new_literal_count > 0) {
   1107       new_literal_count += JSFunction::kLiteralsPrefixSize;
   1108     }
   1109     int old_literal_count = shared_info->num_literals();
   1110 
   1111     if (old_literal_count == new_literal_count) {
   1112       // If literal count didn't change, simply go over all functions
   1113       // and clear literal arrays.
   1114       ClearValuesVisitor visitor;
   1115       IterateJSFunctions(*shared_info, &visitor);
   1116     } else {
   1117       // When literal count changes, we have to create new array instances.
   1118       // Since we cannot create instances when iterating heap, we should first
   1119       // collect all functions and fix their literal arrays.
   1120       Handle<FixedArray> function_instances =
   1121           CollectJSFunctions(shared_info, isolate);
   1122       for (int i = 0; i < function_instances->length(); i++) {
   1123         Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i)));
   1124         Handle<FixedArray> old_literals(fun->literals());
   1125         Handle<FixedArray> new_literals =
   1126             isolate->factory()->NewFixedArray(new_literal_count);
   1127         if (new_literal_count > 0) {
   1128           Handle<Context> native_context;
   1129           if (old_literals->length() >
   1130               JSFunction::kLiteralNativeContextIndex) {
   1131             native_context = Handle<Context>(
   1132                 JSFunction::NativeContextFromLiterals(fun->literals()));
   1133           } else {
   1134             native_context = Handle<Context>(fun->context()->native_context());
   1135           }
   1136           new_literals->set(JSFunction::kLiteralNativeContextIndex,
   1137               *native_context);
   1138         }
   1139         fun->set_literals(*new_literals);
   1140       }
   1141 
   1142       shared_info->set_num_literals(new_literal_count);
   1143     }
   1144   }
   1145 
   1146  private:
   1147   // Iterates all function instances in the HEAP that refers to the
   1148   // provided shared_info.
   1149   template<typename Visitor>
   1150   static void IterateJSFunctions(SharedFunctionInfo* shared_info,
   1151                                  Visitor* visitor) {
   1152     DisallowHeapAllocation no_allocation;
   1153 
   1154     HeapIterator iterator(shared_info->GetHeap());
   1155     for (HeapObject* obj = iterator.next(); obj != NULL;
   1156         obj = iterator.next()) {
   1157       if (obj->IsJSFunction()) {
   1158         JSFunction* function = JSFunction::cast(obj);
   1159         if (function->shared() == shared_info) {
   1160           visitor->visit(function);
   1161         }
   1162       }
   1163     }
   1164   }
   1165 
   1166   // Finds all instances of JSFunction that refers to the provided shared_info
   1167   // and returns array with them.
   1168   static Handle<FixedArray> CollectJSFunctions(
   1169       Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
   1170     CountVisitor count_visitor;
   1171     count_visitor.count = 0;
   1172     IterateJSFunctions(*shared_info, &count_visitor);
   1173     int size = count_visitor.count;
   1174 
   1175     Handle<FixedArray> result = isolate->factory()->NewFixedArray(size);
   1176     if (size > 0) {
   1177       CollectVisitor collect_visitor(result);
   1178       IterateJSFunctions(*shared_info, &collect_visitor);
   1179     }
   1180     return result;
   1181   }
   1182 
   1183   class ClearValuesVisitor {
   1184    public:
   1185     void visit(JSFunction* fun) {
   1186       FixedArray* literals = fun->literals();
   1187       int len = literals->length();
   1188       for (int j = JSFunction::kLiteralsPrefixSize; j < len; j++) {
   1189         literals->set_undefined(j);
   1190       }
   1191     }
   1192   };
   1193 
   1194   class CountVisitor {
   1195    public:
   1196     void visit(JSFunction* fun) {
   1197       count++;
   1198     }
   1199     int count;
   1200   };
   1201 
   1202   class CollectVisitor {
   1203    public:
   1204     explicit CollectVisitor(Handle<FixedArray> output)
   1205         : m_output(output), m_pos(0) {}
   1206 
   1207     void visit(JSFunction* fun) {
   1208       m_output->set(m_pos, fun);
   1209       m_pos++;
   1210     }
   1211    private:
   1212     Handle<FixedArray> m_output;
   1213     int m_pos;
   1214   };
   1215 };
   1216 
   1217 
   1218 // Check whether the code is natural function code (not a lazy-compile stub
   1219 // code).
   1220 static bool IsJSFunctionCode(Code* code) {
   1221   return code->kind() == Code::FUNCTION;
   1222 }
   1223 
   1224 
   1225 // Returns true if an instance of candidate were inlined into function's code.
   1226 static bool IsInlined(JSFunction* function, SharedFunctionInfo* candidate) {
   1227   DisallowHeapAllocation no_gc;
   1228 
   1229   if (function->code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
   1230 
   1231   DeoptimizationInputData* data =
   1232       DeoptimizationInputData::cast(function->code()->deoptimization_data());
   1233 
   1234   if (data == function->GetIsolate()->heap()->empty_fixed_array()) {
   1235     return false;
   1236   }
   1237 
   1238   FixedArray* literals = data->LiteralArray();
   1239 
   1240   int inlined_count = data->InlinedFunctionCount()->value();
   1241   for (int i = 0; i < inlined_count; ++i) {
   1242     JSFunction* inlined = JSFunction::cast(literals->get(i));
   1243     if (inlined->shared() == candidate) return true;
   1244   }
   1245 
   1246   return false;
   1247 }
   1248 
   1249 
   1250 // Marks code that shares the same shared function info or has inlined
   1251 // code that shares the same function info.
   1252 class DependentFunctionMarker: public OptimizedFunctionVisitor {
   1253  public:
   1254   SharedFunctionInfo* shared_info_;
   1255   bool found_;
   1256 
   1257   explicit DependentFunctionMarker(SharedFunctionInfo* shared_info)
   1258     : shared_info_(shared_info), found_(false) { }
   1259 
   1260   virtual void EnterContext(Context* context) { }  // Don't care.
   1261   virtual void LeaveContext(Context* context)  { }  // Don't care.
   1262   virtual void VisitFunction(JSFunction* function) {
   1263     // It should be guaranteed by the iterator that everything is optimized.
   1264     ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
   1265     if (shared_info_ == function->shared() ||
   1266         IsInlined(function, shared_info_)) {
   1267       // Mark the code for deoptimization.
   1268       function->code()->set_marked_for_deoptimization(true);
   1269       found_ = true;
   1270     }
   1271   }
   1272 };
   1273 
   1274 
   1275 static void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) {
   1276   DisallowHeapAllocation no_allocation;
   1277   DependentFunctionMarker marker(function_info);
   1278   // TODO(titzer): need to traverse all optimized code to find OSR code here.
   1279   Deoptimizer::VisitAllOptimizedFunctions(function_info->GetIsolate(), &marker);
   1280 
   1281   if (marker.found_) {
   1282     // Only go through with the deoptimization if something was found.
   1283     Deoptimizer::DeoptimizeMarkedCode(function_info->GetIsolate());
   1284   }
   1285 }
   1286 
   1287 
   1288 MaybeObject* LiveEdit::ReplaceFunctionCode(
   1289     Handle<JSArray> new_compile_info_array,
   1290     Handle<JSArray> shared_info_array) {
   1291   Isolate* isolate = new_compile_info_array->GetIsolate();
   1292   HandleScope scope(isolate);
   1293 
   1294   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
   1295     return isolate->ThrowIllegalOperation();
   1296   }
   1297 
   1298   FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
   1299   SharedInfoWrapper shared_info_wrapper(shared_info_array);
   1300 
   1301   Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
   1302 
   1303   isolate->heap()->EnsureHeapIsIterable();
   1304 
   1305   if (IsJSFunctionCode(shared_info->code())) {
   1306     Handle<Code> code = compile_info_wrapper.GetFunctionCode();
   1307     ReplaceCodeObject(Handle<Code>(shared_info->code()), code);
   1308     Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
   1309     if (code_scope_info->IsFixedArray()) {
   1310       shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
   1311     }
   1312     shared_info->DisableOptimization(kLiveEdit);
   1313   }
   1314 
   1315   if (shared_info->debug_info()->IsDebugInfo()) {
   1316     Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
   1317     Handle<Code> new_original_code =
   1318         isolate->factory()->CopyCode(compile_info_wrapper.GetFunctionCode());
   1319     debug_info->set_original_code(*new_original_code);
   1320   }
   1321 
   1322   int start_position = compile_info_wrapper.GetStartPosition();
   1323   int end_position = compile_info_wrapper.GetEndPosition();
   1324   shared_info->set_start_position(start_position);
   1325   shared_info->set_end_position(end_position);
   1326 
   1327   LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info, isolate);
   1328 
   1329   shared_info->set_construct_stub(
   1330       isolate->builtins()->builtin(Builtins::kJSConstructStubGeneric));
   1331 
   1332   DeoptimizeDependentFunctions(*shared_info);
   1333   isolate->compilation_cache()->Remove(shared_info);
   1334 
   1335   return isolate->heap()->undefined_value();
   1336 }
   1337 
   1338 
   1339 MaybeObject* LiveEdit::FunctionSourceUpdated(
   1340     Handle<JSArray> shared_info_array) {
   1341   Isolate* isolate = shared_info_array->GetIsolate();
   1342   HandleScope scope(isolate);
   1343 
   1344   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
   1345     return isolate->ThrowIllegalOperation();
   1346   }
   1347 
   1348   SharedInfoWrapper shared_info_wrapper(shared_info_array);
   1349   Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
   1350 
   1351   DeoptimizeDependentFunctions(*shared_info);
   1352   isolate->compilation_cache()->Remove(shared_info);
   1353 
   1354   return isolate->heap()->undefined_value();
   1355 }
   1356 
   1357 
   1358 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
   1359                                  Handle<Object> script_handle) {
   1360   Handle<SharedFunctionInfo> shared_info =
   1361       UnwrapSharedFunctionInfoFromJSValue(function_wrapper);
   1362   CHECK(script_handle->IsScript() || script_handle->IsUndefined());
   1363   shared_info->set_script(*script_handle);
   1364 
   1365   function_wrapper->GetIsolate()->compilation_cache()->Remove(shared_info);
   1366 }
   1367 
   1368 
   1369 // For a script text change (defined as position_change_array), translates
   1370 // position in unchanged text to position in changed text.
   1371 // Text change is a set of non-overlapping regions in text, that have changed
   1372 // their contents and length. It is specified as array of groups of 3 numbers:
   1373 // (change_begin, change_end, change_end_new_position).
   1374 // Each group describes a change in text; groups are sorted by change_begin.
   1375 // Only position in text beyond any changes may be successfully translated.
   1376 // If a positions is inside some region that changed, result is currently
   1377 // undefined.
   1378 static int TranslatePosition(int original_position,
   1379                              Handle<JSArray> position_change_array) {
   1380   int position_diff = 0;
   1381   int array_len = GetArrayLength(position_change_array);
   1382   Isolate* isolate = position_change_array->GetIsolate();
   1383   // TODO(635): binary search may be used here
   1384   for (int i = 0; i < array_len; i += 3) {
   1385     Object* element =
   1386         position_change_array->GetElementNoExceptionThrown(isolate, i);
   1387     CHECK(element->IsSmi());
   1388     int chunk_start = Smi::cast(element)->value();
   1389     if (original_position < chunk_start) {
   1390       break;
   1391     }
   1392     element = position_change_array->GetElementNoExceptionThrown(isolate,
   1393                                                                  i + 1);
   1394     CHECK(element->IsSmi());
   1395     int chunk_end = Smi::cast(element)->value();
   1396     // Position mustn't be inside a chunk.
   1397     ASSERT(original_position >= chunk_end);
   1398     element = position_change_array->GetElementNoExceptionThrown(isolate,
   1399                                                                  i + 2);
   1400     CHECK(element->IsSmi());
   1401     int chunk_changed_end = Smi::cast(element)->value();
   1402     position_diff = chunk_changed_end - chunk_end;
   1403   }
   1404 
   1405   return original_position + position_diff;
   1406 }
   1407 
   1408 
   1409 // Auto-growing buffer for writing relocation info code section. This buffer
   1410 // is a simplified version of buffer from Assembler. Unlike Assembler, this
   1411 // class is platform-independent and it works without dealing with instructions.
   1412 // As specified by RelocInfo format, the buffer is filled in reversed order:
   1413 // from upper to lower addresses.
   1414 // It uses NewArray/DeleteArray for memory management.
   1415 class RelocInfoBuffer {
   1416  public:
   1417   RelocInfoBuffer(int buffer_initial_capicity, byte* pc) {
   1418     buffer_size_ = buffer_initial_capicity + kBufferGap;
   1419     buffer_ = NewArray<byte>(buffer_size_);
   1420 
   1421     reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc);
   1422   }
   1423   ~RelocInfoBuffer() {
   1424     DeleteArray(buffer_);
   1425   }
   1426 
   1427   // As specified by RelocInfo format, the buffer is filled in reversed order:
   1428   // from upper to lower addresses.
   1429   void Write(const RelocInfo* rinfo) {
   1430     if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) {
   1431       Grow();
   1432     }
   1433     reloc_info_writer_.Write(rinfo);
   1434   }
   1435 
   1436   Vector<byte> GetResult() {
   1437     // Return the bytes from pos up to end of buffer.
   1438     int result_size =
   1439         static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer_.pos());
   1440     return Vector<byte>(reloc_info_writer_.pos(), result_size);
   1441   }
   1442 
   1443  private:
   1444   void Grow() {
   1445     // Compute new buffer size.
   1446     int new_buffer_size;
   1447     if (buffer_size_ < 2 * KB) {
   1448       new_buffer_size = 4 * KB;
   1449     } else {
   1450       new_buffer_size = 2 * buffer_size_;
   1451     }
   1452     // Some internal data structures overflow for very large buffers,
   1453     // they must ensure that kMaximalBufferSize is not too large.
   1454     if (new_buffer_size > kMaximalBufferSize) {
   1455       V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer");
   1456     }
   1457 
   1458     // Set up new buffer.
   1459     byte* new_buffer = NewArray<byte>(new_buffer_size);
   1460 
   1461     // Copy the data.
   1462     int curently_used_size =
   1463         static_cast<int>(buffer_ + buffer_size_ - reloc_info_writer_.pos());
   1464     OS::MemMove(new_buffer + new_buffer_size - curently_used_size,
   1465                 reloc_info_writer_.pos(), curently_used_size);
   1466 
   1467     reloc_info_writer_.Reposition(
   1468         new_buffer + new_buffer_size - curently_used_size,
   1469         reloc_info_writer_.last_pc());
   1470 
   1471     DeleteArray(buffer_);
   1472     buffer_ = new_buffer;
   1473     buffer_size_ = new_buffer_size;
   1474   }
   1475 
   1476   RelocInfoWriter reloc_info_writer_;
   1477   byte* buffer_;
   1478   int buffer_size_;
   1479 
   1480   static const int kBufferGap = RelocInfoWriter::kMaxSize;
   1481   static const int kMaximalBufferSize = 512*MB;
   1482 };
   1483 
   1484 
   1485 // Patch positions in code (changes relocation info section) and possibly
   1486 // returns new instance of code.
   1487 static Handle<Code> PatchPositionsInCode(
   1488     Handle<Code> code,
   1489     Handle<JSArray> position_change_array) {
   1490   Isolate* isolate = code->GetIsolate();
   1491 
   1492   RelocInfoBuffer buffer_writer(code->relocation_size(),
   1493                                 code->instruction_start());
   1494 
   1495   {
   1496     DisallowHeapAllocation no_allocation;
   1497     for (RelocIterator it(*code); !it.done(); it.next()) {
   1498       RelocInfo* rinfo = it.rinfo();
   1499       if (RelocInfo::IsPosition(rinfo->rmode())) {
   1500         int position = static_cast<int>(rinfo->data());
   1501         int new_position = TranslatePosition(position,
   1502                                              position_change_array);
   1503         if (position != new_position) {
   1504           RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position, NULL);
   1505           buffer_writer.Write(&info_copy);
   1506           continue;
   1507         }
   1508       }
   1509       if (RelocInfo::IsRealRelocMode(rinfo->rmode())) {
   1510         buffer_writer.Write(it.rinfo());
   1511       }
   1512     }
   1513   }
   1514 
   1515   Vector<byte> buffer = buffer_writer.GetResult();
   1516 
   1517   if (buffer.length() == code->relocation_size()) {
   1518     // Simply patch relocation area of code.
   1519     OS::MemCopy(code->relocation_start(), buffer.start(), buffer.length());
   1520     return code;
   1521   } else {
   1522     // Relocation info section now has different size. We cannot simply
   1523     // rewrite it inside code object. Instead we have to create a new
   1524     // code object.
   1525     Handle<Code> result(isolate->factory()->CopyCode(code, buffer));
   1526     return result;
   1527   }
   1528 }
   1529 
   1530 
   1531 MaybeObject* LiveEdit::PatchFunctionPositions(
   1532     Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
   1533   if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
   1534     return shared_info_array->GetIsolate()->ThrowIllegalOperation();
   1535   }
   1536 
   1537   SharedInfoWrapper shared_info_wrapper(shared_info_array);
   1538   Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
   1539 
   1540   int old_function_start = info->start_position();
   1541   int new_function_start = TranslatePosition(old_function_start,
   1542                                              position_change_array);
   1543   int new_function_end = TranslatePosition(info->end_position(),
   1544                                            position_change_array);
   1545   int new_function_token_pos =
   1546       TranslatePosition(info->function_token_position(), position_change_array);
   1547 
   1548   info->set_start_position(new_function_start);
   1549   info->set_end_position(new_function_end);
   1550   info->set_function_token_position(new_function_token_pos);
   1551 
   1552   info->GetIsolate()->heap()->EnsureHeapIsIterable();
   1553 
   1554   if (IsJSFunctionCode(info->code())) {
   1555     // Patch relocation info section of the code.
   1556     Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()),
   1557                                                      position_change_array);
   1558     if (*patched_code != info->code()) {
   1559       // Replace all references to the code across the heap. In particular,
   1560       // some stubs may refer to this code and this code may be being executed
   1561       // on stack (it is safe to substitute the code object on stack, because
   1562       // we only change the structure of rinfo and leave instructions
   1563       // untouched).
   1564       ReplaceCodeObject(Handle<Code>(info->code()), patched_code);
   1565     }
   1566   }
   1567 
   1568   return info->GetIsolate()->heap()->undefined_value();
   1569 }
   1570 
   1571 
   1572 static Handle<Script> CreateScriptCopy(Handle<Script> original) {
   1573   Isolate* isolate = original->GetIsolate();
   1574 
   1575   Handle<String> original_source(String::cast(original->source()));
   1576   Handle<Script> copy = isolate->factory()->NewScript(original_source);
   1577 
   1578   copy->set_name(original->name());
   1579   copy->set_line_offset(original->line_offset());
   1580   copy->set_column_offset(original->column_offset());
   1581   copy->set_data(original->data());
   1582   copy->set_type(original->type());
   1583   copy->set_context_data(original->context_data());
   1584   copy->set_eval_from_shared(original->eval_from_shared());
   1585   copy->set_eval_from_instructions_offset(
   1586       original->eval_from_instructions_offset());
   1587 
   1588   // Copy all the flags, but clear compilation state.
   1589   copy->set_flags(original->flags());
   1590   copy->set_compilation_state(Script::COMPILATION_STATE_INITIAL);
   1591 
   1592   return copy;
   1593 }
   1594 
   1595 
   1596 Object* LiveEdit::ChangeScriptSource(Handle<Script> original_script,
   1597                                      Handle<String> new_source,
   1598                                      Handle<Object> old_script_name) {
   1599   Isolate* isolate = original_script->GetIsolate();
   1600   Handle<Object> old_script_object;
   1601   if (old_script_name->IsString()) {
   1602     Handle<Script> old_script = CreateScriptCopy(original_script);
   1603     old_script->set_name(String::cast(*old_script_name));
   1604     old_script_object = old_script;
   1605     isolate->debugger()->OnAfterCompile(
   1606         old_script, Debugger::SEND_WHEN_DEBUGGING);
   1607   } else {
   1608     old_script_object = isolate->factory()->null_value();
   1609   }
   1610 
   1611   original_script->set_source(*new_source);
   1612 
   1613   // Drop line ends so that they will be recalculated.
   1614   original_script->set_line_ends(isolate->heap()->undefined_value());
   1615 
   1616   return *old_script_object;
   1617 }
   1618 
   1619 
   1620 
   1621 void LiveEdit::ReplaceRefToNestedFunction(
   1622     Handle<JSValue> parent_function_wrapper,
   1623     Handle<JSValue> orig_function_wrapper,
   1624     Handle<JSValue> subst_function_wrapper) {
   1625 
   1626   Handle<SharedFunctionInfo> parent_shared =
   1627       UnwrapSharedFunctionInfoFromJSValue(parent_function_wrapper);
   1628   Handle<SharedFunctionInfo> orig_shared =
   1629       UnwrapSharedFunctionInfoFromJSValue(orig_function_wrapper);
   1630   Handle<SharedFunctionInfo> subst_shared =
   1631       UnwrapSharedFunctionInfoFromJSValue(subst_function_wrapper);
   1632 
   1633   for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
   1634     if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
   1635       if (it.rinfo()->target_object() == *orig_shared) {
   1636         it.rinfo()->set_target_object(*subst_shared);
   1637       }
   1638     }
   1639   }
   1640 }
   1641 
   1642 
   1643 // Check an activation against list of functions. If there is a function
   1644 // that matches, its status in result array is changed to status argument value.
   1645 static bool CheckActivation(Handle<JSArray> shared_info_array,
   1646                             Handle<JSArray> result,
   1647                             StackFrame* frame,
   1648                             LiveEdit::FunctionPatchabilityStatus status) {
   1649   if (!frame->is_java_script()) return false;
   1650 
   1651   Handle<JSFunction> function(JavaScriptFrame::cast(frame)->function());
   1652 
   1653   Isolate* isolate = shared_info_array->GetIsolate();
   1654   int len = GetArrayLength(shared_info_array);
   1655   for (int i = 0; i < len; i++) {
   1656     Object* element =
   1657         shared_info_array->GetElementNoExceptionThrown(isolate, i);
   1658     CHECK(element->IsJSValue());
   1659     Handle<JSValue> jsvalue(JSValue::cast(element));
   1660     Handle<SharedFunctionInfo> shared =
   1661         UnwrapSharedFunctionInfoFromJSValue(jsvalue);
   1662 
   1663     if (function->shared() == *shared || IsInlined(*function, *shared)) {
   1664       SetElementNonStrict(result, i, Handle<Smi>(Smi::FromInt(status),
   1665                                                  isolate));
   1666       return true;
   1667     }
   1668   }
   1669   return false;
   1670 }
   1671 
   1672 
   1673 // Iterates over handler chain and removes all elements that are inside
   1674 // frames being dropped.
   1675 static bool FixTryCatchHandler(StackFrame* top_frame,
   1676                                StackFrame* bottom_frame) {
   1677   Address* pointer_address =
   1678       &Memory::Address_at(top_frame->isolate()->get_address_from_id(
   1679           Isolate::kHandlerAddress));
   1680 
   1681   while (*pointer_address < top_frame->sp()) {
   1682     pointer_address = &Memory::Address_at(*pointer_address);
   1683   }
   1684   Address* above_frame_address = pointer_address;
   1685   while (*pointer_address < bottom_frame->fp()) {
   1686     pointer_address = &Memory::Address_at(*pointer_address);
   1687   }
   1688   bool change = *above_frame_address != *pointer_address;
   1689   *above_frame_address = *pointer_address;
   1690   return change;
   1691 }
   1692 
   1693 
   1694 // Removes specified range of frames from stack. There may be 1 or more
   1695 // frames in range. Anyway the bottom frame is restarted rather than dropped,
   1696 // and therefore has to be a JavaScript frame.
   1697 // Returns error message or NULL.
   1698 static const char* DropFrames(Vector<StackFrame*> frames,
   1699                               int top_frame_index,
   1700                               int bottom_js_frame_index,
   1701                               Debug::FrameDropMode* mode,
   1702                               Object*** restarter_frame_function_pointer) {
   1703   if (!Debug::kFrameDropperSupported) {
   1704     return "Stack manipulations are not supported in this architecture.";
   1705   }
   1706 
   1707   StackFrame* pre_top_frame = frames[top_frame_index - 1];
   1708   StackFrame* top_frame = frames[top_frame_index];
   1709   StackFrame* bottom_js_frame = frames[bottom_js_frame_index];
   1710 
   1711   ASSERT(bottom_js_frame->is_java_script());
   1712 
   1713   // Check the nature of the top frame.
   1714   Isolate* isolate = bottom_js_frame->isolate();
   1715   Code* pre_top_frame_code = pre_top_frame->LookupCode();
   1716   bool frame_has_padding;
   1717   if (pre_top_frame_code->is_inline_cache_stub() &&
   1718       pre_top_frame_code->is_debug_stub()) {
   1719     // OK, we can drop inline cache calls.
   1720     *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
   1721     frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
   1722   } else if (pre_top_frame_code ==
   1723              isolate->debug()->debug_break_slot()) {
   1724     // OK, we can drop debug break slot.
   1725     *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
   1726     frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
   1727   } else if (pre_top_frame_code ==
   1728       isolate->builtins()->builtin(
   1729           Builtins::kFrameDropper_LiveEdit)) {
   1730     // OK, we can drop our own code.
   1731     pre_top_frame = frames[top_frame_index - 2];
   1732     top_frame = frames[top_frame_index - 1];
   1733     *mode = Debug::CURRENTLY_SET_MODE;
   1734     frame_has_padding = false;
   1735   } else if (pre_top_frame_code ==
   1736       isolate->builtins()->builtin(Builtins::kReturn_DebugBreak)) {
   1737     *mode = Debug::FRAME_DROPPED_IN_RETURN_CALL;
   1738     frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
   1739   } else if (pre_top_frame_code->kind() == Code::STUB &&
   1740       pre_top_frame_code->major_key() == CodeStub::CEntry) {
   1741     // Entry from our unit tests on 'debugger' statement.
   1742     // It's fine, we support this case.
   1743     *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
   1744     // We don't have a padding from 'debugger' statement call.
   1745     // Here the stub is CEntry, it's not debug-only and can't be padded.
   1746     // If anyone would complain, a proxy padded stub could be added.
   1747     frame_has_padding = false;
   1748   } else if (pre_top_frame->type() == StackFrame::ARGUMENTS_ADAPTOR) {
   1749     // This must be adaptor that remain from the frame dropping that
   1750     // is still on stack. A frame dropper frame must be above it.
   1751     ASSERT(frames[top_frame_index - 2]->LookupCode() ==
   1752         isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit));
   1753     pre_top_frame = frames[top_frame_index - 3];
   1754     top_frame = frames[top_frame_index - 2];
   1755     *mode = Debug::CURRENTLY_SET_MODE;
   1756     frame_has_padding = false;
   1757   } else {
   1758     return "Unknown structure of stack above changing function";
   1759   }
   1760 
   1761   Address unused_stack_top = top_frame->sp();
   1762   Address unused_stack_bottom = bottom_js_frame->fp()
   1763       - Debug::kFrameDropperFrameSize * kPointerSize  // Size of the new frame.
   1764       + kPointerSize;  // Bigger address end is exclusive.
   1765 
   1766   Address* top_frame_pc_address = top_frame->pc_address();
   1767 
   1768   // top_frame may be damaged below this point. Do not used it.
   1769   ASSERT(!(top_frame = NULL));
   1770 
   1771   if (unused_stack_top > unused_stack_bottom) {
   1772     if (frame_has_padding) {
   1773       int shortage_bytes =
   1774           static_cast<int>(unused_stack_top - unused_stack_bottom);
   1775 
   1776       Address padding_start = pre_top_frame->fp() -
   1777           Debug::FramePaddingLayout::kFrameBaseSize * kPointerSize;
   1778 
   1779       Address padding_pointer = padding_start;
   1780       Smi* padding_object =
   1781           Smi::FromInt(Debug::FramePaddingLayout::kPaddingValue);
   1782       while (Memory::Object_at(padding_pointer) == padding_object) {
   1783         padding_pointer -= kPointerSize;
   1784       }
   1785       int padding_counter =
   1786           Smi::cast(Memory::Object_at(padding_pointer))->value();
   1787       if (padding_counter * kPointerSize < shortage_bytes) {
   1788         return "Not enough space for frame dropper frame "
   1789             "(even with padding frame)";
   1790       }
   1791       Memory::Object_at(padding_pointer) =
   1792           Smi::FromInt(padding_counter - shortage_bytes / kPointerSize);
   1793 
   1794       StackFrame* pre_pre_frame = frames[top_frame_index - 2];
   1795 
   1796       OS::MemMove(padding_start + kPointerSize - shortage_bytes,
   1797                   padding_start + kPointerSize,
   1798                   Debug::FramePaddingLayout::kFrameBaseSize * kPointerSize);
   1799 
   1800       pre_top_frame->UpdateFp(pre_top_frame->fp() - shortage_bytes);
   1801       pre_pre_frame->SetCallerFp(pre_top_frame->fp());
   1802       unused_stack_top -= shortage_bytes;
   1803 
   1804       STATIC_ASSERT(sizeof(Address) == kPointerSize);
   1805       top_frame_pc_address -= shortage_bytes / kPointerSize;
   1806     } else {
   1807       return "Not enough space for frame dropper frame";
   1808     }
   1809   }
   1810 
   1811   // Committing now. After this point we should return only NULL value.
   1812 
   1813   FixTryCatchHandler(pre_top_frame, bottom_js_frame);
   1814   // Make sure FixTryCatchHandler is idempotent.
   1815   ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
   1816 
   1817   Handle<Code> code = isolate->builtins()->FrameDropper_LiveEdit();
   1818   *top_frame_pc_address = code->entry();
   1819   pre_top_frame->SetCallerFp(bottom_js_frame->fp());
   1820 
   1821   *restarter_frame_function_pointer =
   1822       Debug::SetUpFrameDropperFrame(bottom_js_frame, code);
   1823 
   1824   ASSERT((**restarter_frame_function_pointer)->IsJSFunction());
   1825 
   1826   for (Address a = unused_stack_top;
   1827       a < unused_stack_bottom;
   1828       a += kPointerSize) {
   1829     Memory::Object_at(a) = Smi::FromInt(0);
   1830   }
   1831 
   1832   return NULL;
   1833 }
   1834 
   1835 
   1836 static bool IsDropableFrame(StackFrame* frame) {
   1837   return !frame->is_exit();
   1838 }
   1839 
   1840 
   1841 // Describes a set of call frames that execute any of listed functions.
   1842 // Finding no such frames does not mean error.
   1843 class MultipleFunctionTarget {
   1844  public:
   1845   MultipleFunctionTarget(Handle<JSArray> shared_info_array,
   1846       Handle<JSArray> result)
   1847       : m_shared_info_array(shared_info_array),
   1848         m_result(result) {}
   1849   bool MatchActivation(StackFrame* frame,
   1850       LiveEdit::FunctionPatchabilityStatus status) {
   1851     return CheckActivation(m_shared_info_array, m_result, frame, status);
   1852   }
   1853   const char* GetNotFoundMessage() {
   1854     return NULL;
   1855   }
   1856  private:
   1857   Handle<JSArray> m_shared_info_array;
   1858   Handle<JSArray> m_result;
   1859 };
   1860 
   1861 
   1862 // Drops all call frame matched by target and all frames above them.
   1863 template<typename TARGET>
   1864 static const char* DropActivationsInActiveThreadImpl(
   1865     Isolate* isolate, TARGET& target, bool do_drop) {
   1866   Debug* debug = isolate->debug();
   1867   Zone zone(isolate);
   1868   Vector<StackFrame*> frames = CreateStackMap(isolate, &zone);
   1869 
   1870 
   1871   int top_frame_index = -1;
   1872   int frame_index = 0;
   1873   for (; frame_index < frames.length(); frame_index++) {
   1874     StackFrame* frame = frames[frame_index];
   1875     if (frame->id() == debug->break_frame_id()) {
   1876       top_frame_index = frame_index;
   1877       break;
   1878     }
   1879     if (target.MatchActivation(
   1880             frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
   1881       // We are still above break_frame. It is not a target frame,
   1882       // it is a problem.
   1883       return "Debugger mark-up on stack is not found";
   1884     }
   1885   }
   1886 
   1887   if (top_frame_index == -1) {
   1888     // We haven't found break frame, but no function is blocking us anyway.
   1889     return target.GetNotFoundMessage();
   1890   }
   1891 
   1892   bool target_frame_found = false;
   1893   int bottom_js_frame_index = top_frame_index;
   1894   bool c_code_found = false;
   1895 
   1896   for (; frame_index < frames.length(); frame_index++) {
   1897     StackFrame* frame = frames[frame_index];
   1898     if (!IsDropableFrame(frame)) {
   1899       c_code_found = true;
   1900       break;
   1901     }
   1902     if (target.MatchActivation(
   1903             frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
   1904       target_frame_found = true;
   1905       bottom_js_frame_index = frame_index;
   1906     }
   1907   }
   1908 
   1909   if (c_code_found) {
   1910     // There is a C frames on stack. Check that there are no target frames
   1911     // below them.
   1912     for (; frame_index < frames.length(); frame_index++) {
   1913       StackFrame* frame = frames[frame_index];
   1914       if (frame->is_java_script()) {
   1915         if (target.MatchActivation(
   1916                 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
   1917           // Cannot drop frame under C frames.
   1918           return NULL;
   1919         }
   1920       }
   1921     }
   1922   }
   1923 
   1924   if (!do_drop) {
   1925     // We are in check-only mode.
   1926     return NULL;
   1927   }
   1928 
   1929   if (!target_frame_found) {
   1930     // Nothing to drop.
   1931     return target.GetNotFoundMessage();
   1932   }
   1933 
   1934   Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED;
   1935   Object** restarter_frame_function_pointer = NULL;
   1936   const char* error_message = DropFrames(frames, top_frame_index,
   1937                                          bottom_js_frame_index, &drop_mode,
   1938                                          &restarter_frame_function_pointer);
   1939 
   1940   if (error_message != NULL) {
   1941     return error_message;
   1942   }
   1943 
   1944   // Adjust break_frame after some frames has been dropped.
   1945   StackFrame::Id new_id = StackFrame::NO_ID;
   1946   for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
   1947     if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
   1948       new_id = frames[i]->id();
   1949       break;
   1950     }
   1951   }
   1952   debug->FramesHaveBeenDropped(new_id, drop_mode,
   1953                                restarter_frame_function_pointer);
   1954   return NULL;
   1955 }
   1956 
   1957 
   1958 // Fills result array with statuses of functions. Modifies the stack
   1959 // removing all listed function if possible and if do_drop is true.
   1960 static const char* DropActivationsInActiveThread(
   1961     Handle<JSArray> shared_info_array, Handle<JSArray> result, bool do_drop) {
   1962   MultipleFunctionTarget target(shared_info_array, result);
   1963 
   1964   const char* message = DropActivationsInActiveThreadImpl(
   1965       shared_info_array->GetIsolate(), target, do_drop);
   1966   if (message) {
   1967     return message;
   1968   }
   1969 
   1970   Isolate* isolate = shared_info_array->GetIsolate();
   1971   int array_len = GetArrayLength(shared_info_array);
   1972 
   1973   // Replace "blocked on active" with "replaced on active" status.
   1974   for (int i = 0; i < array_len; i++) {
   1975     if (result->GetElement(result->GetIsolate(), i) ==
   1976         Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
   1977       Handle<Object> replaced(
   1978           Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
   1979       SetElementNonStrict(result, i, replaced);
   1980     }
   1981   }
   1982   return NULL;
   1983 }
   1984 
   1985 
   1986 class InactiveThreadActivationsChecker : public ThreadVisitor {
   1987  public:
   1988   InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
   1989                                    Handle<JSArray> result)
   1990       : shared_info_array_(shared_info_array), result_(result),
   1991         has_blocked_functions_(false) {
   1992   }
   1993   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
   1994     for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
   1995       has_blocked_functions_ |= CheckActivation(
   1996           shared_info_array_, result_, it.frame(),
   1997           LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
   1998     }
   1999   }
   2000   bool HasBlockedFunctions() {
   2001     return has_blocked_functions_;
   2002   }
   2003 
   2004  private:
   2005   Handle<JSArray> shared_info_array_;
   2006   Handle<JSArray> result_;
   2007   bool has_blocked_functions_;
   2008 };
   2009 
   2010 
   2011 Handle<JSArray> LiveEdit::CheckAndDropActivations(
   2012     Handle<JSArray> shared_info_array, bool do_drop) {
   2013   Isolate* isolate = shared_info_array->GetIsolate();
   2014   int len = GetArrayLength(shared_info_array);
   2015 
   2016   Handle<JSArray> result = isolate->factory()->NewJSArray(len);
   2017 
   2018   // Fill the default values.
   2019   for (int i = 0; i < len; i++) {
   2020     SetElementNonStrict(
   2021         result,
   2022         i,
   2023         Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
   2024   }
   2025 
   2026 
   2027   // First check inactive threads. Fail if some functions are blocked there.
   2028   InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
   2029                                                             result);
   2030   isolate->thread_manager()->IterateArchivedThreads(
   2031       &inactive_threads_checker);
   2032   if (inactive_threads_checker.HasBlockedFunctions()) {
   2033     return result;
   2034   }
   2035 
   2036   // Try to drop activations from the current stack.
   2037   const char* error_message =
   2038       DropActivationsInActiveThread(shared_info_array, result, do_drop);
   2039   if (error_message != NULL) {
   2040     // Add error message as an array extra element.
   2041     Vector<const char> vector_message(error_message, StrLength(error_message));
   2042     Handle<String> str = isolate->factory()->NewStringFromAscii(vector_message);
   2043     SetElementNonStrict(result, len, str);
   2044   }
   2045   return result;
   2046 }
   2047 
   2048 
   2049 // Describes a single callframe a target. Not finding this frame
   2050 // means an error.
   2051 class SingleFrameTarget {
   2052  public:
   2053   explicit SingleFrameTarget(JavaScriptFrame* frame)
   2054       : m_frame(frame),
   2055         m_saved_status(LiveEdit::FUNCTION_AVAILABLE_FOR_PATCH) {}
   2056 
   2057   bool MatchActivation(StackFrame* frame,
   2058       LiveEdit::FunctionPatchabilityStatus status) {
   2059     if (frame->fp() == m_frame->fp()) {
   2060       m_saved_status = status;
   2061       return true;
   2062     }
   2063     return false;
   2064   }
   2065   const char* GetNotFoundMessage() {
   2066     return "Failed to found requested frame";
   2067   }
   2068   LiveEdit::FunctionPatchabilityStatus saved_status() {
   2069     return m_saved_status;
   2070   }
   2071  private:
   2072   JavaScriptFrame* m_frame;
   2073   LiveEdit::FunctionPatchabilityStatus m_saved_status;
   2074 };
   2075 
   2076 
   2077 // Finds a drops required frame and all frames above.
   2078 // Returns error message or NULL.
   2079 const char* LiveEdit::RestartFrame(JavaScriptFrame* frame) {
   2080   SingleFrameTarget target(frame);
   2081 
   2082   const char* result = DropActivationsInActiveThreadImpl(
   2083       frame->isolate(), target, true);
   2084   if (result != NULL) {
   2085     return result;
   2086   }
   2087   if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
   2088     return "Function is blocked under native code";
   2089   }
   2090   return NULL;
   2091 }
   2092 
   2093 
   2094 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
   2095                                                  FunctionLiteral* fun)
   2096     : isolate_(isolate) {
   2097   if (isolate_->active_function_info_listener() != NULL) {
   2098     isolate_->active_function_info_listener()->FunctionStarted(fun);
   2099   }
   2100 }
   2101 
   2102 
   2103 LiveEditFunctionTracker::~LiveEditFunctionTracker() {
   2104   if (isolate_->active_function_info_listener() != NULL) {
   2105     isolate_->active_function_info_listener()->FunctionDone();
   2106   }
   2107 }
   2108 
   2109 
   2110 void LiveEditFunctionTracker::RecordFunctionInfo(
   2111     Handle<SharedFunctionInfo> info, FunctionLiteral* lit,
   2112     Zone* zone) {
   2113   if (isolate_->active_function_info_listener() != NULL) {
   2114     isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(),
   2115                                                             zone);
   2116   }
   2117 }
   2118 
   2119 
   2120 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
   2121   isolate_->active_function_info_listener()->FunctionCode(code);
   2122 }
   2123 
   2124 
   2125 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
   2126   return isolate->active_function_info_listener() != NULL;
   2127 }
   2128 
   2129 
   2130 #else  // ENABLE_DEBUGGER_SUPPORT
   2131 
   2132 // This ifdef-else-endif section provides working or stub implementation of
   2133 // LiveEditFunctionTracker.
   2134 LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
   2135                                                  FunctionLiteral* fun) {
   2136 }
   2137 
   2138 
   2139 LiveEditFunctionTracker::~LiveEditFunctionTracker() {
   2140 }
   2141 
   2142 
   2143 void LiveEditFunctionTracker::RecordFunctionInfo(
   2144     Handle<SharedFunctionInfo> info, FunctionLiteral* lit,
   2145     Zone* zone) {
   2146 }
   2147 
   2148 
   2149 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
   2150 }
   2151 
   2152 
   2153 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
   2154   return false;
   2155 }
   2156 
   2157 #endif  // ENABLE_DEBUGGER_SUPPORT
   2158 
   2159 
   2160 
   2161 } }  // namespace v8::internal
   2162