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