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