49 #ifdef ENABLE_DEBUGGER_SUPPORT
52 void SetElementSloppy(Handle<JSObject>
object,
54 Handle<Object> value) {
58 Handle<Object> no_failure =
60 ASSERT(!no_failure.is_null());
71 explicit Differencer(Comparator::Input* input)
72 : input_(input), len1_(input->GetLength1()), len2_(input->GetLength2()) {
73 buffer_ = NewArray<int>(len1_ * len2_);
80 int array_size = len1_ * len2_;
81 for (
int i = 0; i < array_size; i++) {
82 buffer_[i] = kEmptyCellValue;
89 CompareUpToTail(0, 0);
92 void SaveResult(Comparator::Output* chunk_writer) {
93 ResultWriter writer(chunk_writer);
100 Direction dir = get_direction(pos1, pos2);
120 writer.skip1(len1_ - pos1);
125 writer.skip2(len2_ - pos2);
134 Comparator::Input* input_;
145 MAX_DIRECTION_FLAG_VALUE = SKIP_ANY
150 int CompareUpToTail(
int pos1,
int pos2) {
153 int cached_res = get_value4(pos1, pos2);
154 if (cached_res == kEmptyCellValue) {
157 if (input_->Equals(pos1, pos2)) {
158 res = CompareUpToTail(pos1 + 1, pos2 + 1);
161 int res1 = CompareUpToTail(pos1 + 1, pos2) +
162 (1 << kDirectionSizeBits);
163 int res2 = CompareUpToTail(pos1, pos2 + 1) +
164 (1 << kDirectionSizeBits);
168 }
else if (res1 < res2) {
176 set_value4_and_dir(pos1, pos2, res, dir);
181 return (len1_ - pos1) << kDirectionSizeBits;
184 return (len2_ - pos2) << kDirectionSizeBits;
188 inline int& get_cell(
int i1,
int i2) {
189 return buffer_[i1 + i2 * len1_];
193 void set_value4_and_dir(
int i1,
int i2,
int value4, Direction dir) {
194 ASSERT((value4 & kDirectionMask) == 0);
195 get_cell(i1, i2) = value4 | dir;
198 int get_value4(
int i1,
int i2) {
199 return get_cell(i1, i2) & (
kMaxUInt32 ^ kDirectionMask);
201 Direction get_direction(
int i1,
int i2) {
202 return static_cast<Direction
>(get_cell(i1, i2) & kDirectionMask);
205 static const int kDirectionSizeBits = 2;
206 static const int kDirectionMask = (1 << kDirectionSizeBits) - 1;
207 static const int kEmptyCellValue = -1 << kDirectionSizeBits;
211 void StaticAssertHolder() {
212 STATIC_ASSERT(MAX_DIRECTION_FLAG_VALUE < (1 << kDirectionSizeBits));
217 explicit ResultWriter(Comparator::Output* chunk_writer)
218 : chunk_writer_(chunk_writer), pos1_(0), pos2_(0),
219 pos1_begin_(-1), pos2_begin_(-1), has_open_chunk_(
false) {
226 void skip1(
int len1) {
230 void skip2(
int len2) {
239 Comparator::Output* chunk_writer_;
244 bool has_open_chunk_;
247 if (!has_open_chunk_) {
250 has_open_chunk_ =
true;
255 if (has_open_chunk_) {
256 chunk_writer_->AddChunk(pos1_begin_, pos2_begin_,
257 pos1_ - pos1_begin_, pos2_ - pos2_begin_);
258 has_open_chunk_ =
false;
265 void Comparator::CalculateDifference(Comparator::Input* input,
266 Comparator::Output* result_writer) {
267 Differencer differencer(input);
268 differencer.Initialize();
269 differencer.FillTable();
270 differencer.SaveResult(result_writer);
274 static bool CompareSubstrings(Handle<String>
s1,
int pos1,
275 Handle<String>
s2,
int pos2,
int len) {
276 for (
int i = 0; i < len; i++) {
277 if (s1->Get(i + pos1) != s2->Get(i + pos2)) {
289 class SubrangableInput :
public Comparator::Input {
291 virtual void SetSubrange1(
int offset,
int len) = 0;
292 virtual void SetSubrange2(
int offset,
int len) = 0;
296 class SubrangableOutput :
public Comparator::Output {
298 virtual void SetSubrange1(
int offset,
int len) = 0;
299 virtual void SetSubrange2(
int offset,
int len) = 0;
303 static int min(
int a,
int b) {
304 return a < b ? a : b;
310 static void NarrowDownInput(SubrangableInput* input,
311 SubrangableOutput* output) {
312 const int len1 = input->GetLength1();
313 const int len2 = input->GetLength2();
315 int common_prefix_len;
316 int common_suffix_len;
319 common_prefix_len = 0;
320 int prefix_limit = min(len1, len2);
321 while (common_prefix_len < prefix_limit &&
322 input->Equals(common_prefix_len, common_prefix_len)) {
326 common_suffix_len = 0;
327 int suffix_limit = min(len1 - common_prefix_len, len2 - common_prefix_len);
329 while (common_suffix_len < suffix_limit &&
330 input->Equals(len1 - common_suffix_len - 1,
331 len2 - common_suffix_len - 1)) {
336 if (common_prefix_len > 0 || common_suffix_len > 0) {
337 int new_len1 = len1 - common_suffix_len - common_prefix_len;
338 int new_len2 = len2 - common_suffix_len - common_prefix_len;
340 input->SetSubrange1(common_prefix_len, new_len1);
341 input->SetSubrange2(common_prefix_len, new_len2);
343 output->SetSubrange1(common_prefix_len, new_len1);
344 output->SetSubrange2(common_prefix_len, new_len2);
351 class CompareOutputArrayWriter {
353 explicit CompareOutputArrayWriter(Isolate* isolate)
354 : array_(isolate->factory()->NewJSArray(10)), current_size_(0) {}
356 Handle<JSArray> GetResult() {
360 void WriteChunk(
int char_pos1,
int char_pos2,
int char_len1,
int char_len2) {
361 Isolate* isolate = array_->GetIsolate();
362 SetElementSloppy(array_,
365 SetElementSloppy(array_,
369 SetElementSloppy(array_,
377 Handle<JSArray> array_;
385 class TokensCompareInput :
public Comparator::Input {
387 TokensCompareInput(Handle<String> s1,
int offset1,
int len1,
388 Handle<String> s2,
int offset2,
int len2)
389 : s1_(s1), offset1_(offset1), len1_(len1),
390 s2_(s2), offset2_(offset2), len2_(len2) {
392 virtual int GetLength1() {
395 virtual int GetLength2() {
398 bool Equals(
int index1,
int index2) {
399 return s1_->Get(offset1_ + index1) == s2_->Get(offset2_ + index2);
414 class TokensCompareOutput :
public Comparator::Output {
416 TokensCompareOutput(CompareOutputArrayWriter* array_writer,
417 int offset1,
int offset2)
418 : array_writer_(array_writer), offset1_(offset1), offset2_(offset2) {
421 void AddChunk(
int pos1,
int pos2,
int len1,
int len2) {
422 array_writer_->WriteChunk(pos1 + offset1_, pos2 + offset2_, len1, len2);
426 CompareOutputArrayWriter* array_writer_;
434 class LineEndsWrapper {
436 explicit LineEndsWrapper(Handle<String>
string)
438 string_len_(string->length()) {
441 return ends_array_->length() + 1;
445 int GetLineStart(
int index) {
449 return GetLineEnd(index - 1);
452 int GetLineEnd(
int index) {
453 if (index == ends_array_->length()) {
459 return GetPosAfterNewLine(index);
464 Handle<FixedArray> ends_array_;
467 int GetPosAfterNewLine(
int index) {
468 return Smi::cast(ends_array_->get(index))->value() + 1;
474 class LineArrayCompareInput :
public SubrangableInput {
476 LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
477 LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
478 : s1_(s1), s2_(s2), line_ends1_(line_ends1),
479 line_ends2_(line_ends2),
480 subrange_offset1_(0), subrange_offset2_(0),
481 subrange_len1_(line_ends1_.length()),
482 subrange_len2_(line_ends2_.length()) {
485 return subrange_len1_;
488 return subrange_len2_;
490 bool Equals(
int index1,
int index2) {
491 index1 += subrange_offset1_;
492 index2 += subrange_offset2_;
494 int line_start1 = line_ends1_.GetLineStart(index1);
495 int line_start2 = line_ends2_.GetLineStart(index2);
496 int line_end1 = line_ends1_.GetLineEnd(index1);
497 int line_end2 = line_ends2_.GetLineEnd(index2);
498 int len1 = line_end1 - line_start1;
499 int len2 = line_end2 - line_start2;
503 return CompareSubstrings(s1_, line_start1, s2_, line_start2,
506 void SetSubrange1(
int offset,
int len) {
507 subrange_offset1_ = offset;
508 subrange_len1_ = len;
510 void SetSubrange2(
int offset,
int len) {
511 subrange_offset2_ = offset;
512 subrange_len2_ = len;
518 LineEndsWrapper line_ends1_;
519 LineEndsWrapper line_ends2_;
520 int subrange_offset1_;
521 int subrange_offset2_;
529 class TokenizingLineArrayCompareOutput :
public SubrangableOutput {
531 TokenizingLineArrayCompareOutput(LineEndsWrapper line_ends1,
532 LineEndsWrapper line_ends2,
533 Handle<String> s1, Handle<String> s2)
534 : array_writer_(s1->GetIsolate()),
535 line_ends1_(line_ends1), line_ends2_(line_ends2), s1_(s1), s2_(s2),
536 subrange_offset1_(0), subrange_offset2_(0) {
539 void AddChunk(
int line_pos1,
int line_pos2,
int line_len1,
int line_len2) {
540 line_pos1 += subrange_offset1_;
541 line_pos2 += subrange_offset2_;
543 int char_pos1 = line_ends1_.GetLineStart(line_pos1);
544 int char_pos2 = line_ends2_.GetLineStart(line_pos2);
545 int char_len1 = line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
546 int char_len2 = line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
548 if (char_len1 < CHUNK_LEN_LIMIT && char_len2 < CHUNK_LEN_LIMIT) {
550 HandleScope subTaskScope(s1_->GetIsolate());
552 TokensCompareInput tokens_input(s1_, char_pos1, char_len1,
553 s2_, char_pos2, char_len2);
554 TokensCompareOutput tokens_output(&array_writer_, char_pos1,
557 Comparator::CalculateDifference(&tokens_input, &tokens_output);
559 array_writer_.WriteChunk(char_pos1, char_pos2, char_len1, char_len2);
562 void SetSubrange1(
int offset,
int len) {
563 subrange_offset1_ = offset;
565 void SetSubrange2(
int offset,
int len) {
566 subrange_offset2_ = offset;
569 Handle<JSArray> GetResult() {
570 return array_writer_.GetResult();
574 static const int CHUNK_LEN_LIMIT = 800;
576 CompareOutputArrayWriter array_writer_;
577 LineEndsWrapper line_ends1_;
578 LineEndsWrapper line_ends2_;
581 int subrange_offset1_;
582 int subrange_offset2_;
586 Handle<JSArray> LiveEdit::CompareStrings(Handle<String> s1,
591 LineEndsWrapper line_ends1(s1);
592 LineEndsWrapper line_ends2(s2);
594 LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
595 TokenizingLineArrayCompareOutput output(line_ends1, line_ends2, s1, s2);
597 NarrowDownInput(&input, &output);
599 Comparator::CalculateDifference(&input, &output);
601 return output.GetResult();
606 static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
607 return Handle<Object>(jsValue->value(), jsValue->GetIsolate());
613 static Handle<JSValue> WrapInJSValue(Handle<HeapObject>
object) {
614 Isolate* isolate =
object->GetIsolate();
615 Handle<JSFunction> constructor = isolate->opaque_reference_function();
616 Handle<JSValue> result =
618 result->set_value(*
object);
623 static Handle<SharedFunctionInfo> UnwrapSharedFunctionInfoFromJSValue(
624 Handle<JSValue> jsValue) {
625 Object* shared = jsValue->value();
626 CHECK(shared->IsSharedFunctionInfo());
631 static int GetArrayLength(Handle<JSArray> array) {
632 Object* length = array->length();
633 CHECK(length->IsSmi());
642 class JSArrayBasedStruct {
644 static S Create(Isolate* isolate) {
645 Factory* factory = isolate->factory();
646 Handle<JSArray> array = factory->NewJSArray(S::kSize_);
649 static S cast(
Object*
object) {
651 Handle<JSArray> array_handle(array);
652 return S(array_handle);
654 explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
656 Handle<JSArray> GetJSArray() {
659 Isolate* isolate()
const {
660 return array_->GetIsolate();
664 void SetField(
int field_position, Handle<Object> value) {
665 SetElementSloppy(array_, field_position, value);
667 void SetSmiValueField(
int field_position,
int value) {
668 SetElementSloppy(array_,
672 Handle<Object> GetField(
int field_position) {
674 isolate(), array_, field_position);
676 int GetSmiValueField(
int field_position) {
677 Handle<Object> res = GetField(field_position);
682 Handle<JSArray> array_;
689 class FunctionInfoWrapper :
public JSArrayBasedStruct<FunctionInfoWrapper> {
691 explicit FunctionInfoWrapper(Handle<JSArray> array)
692 : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
694 void SetInitialProperties(Handle<String>
name,
int start_position,
695 int end_position,
int param_num,
696 int literal_count,
int parent_index) {
697 HandleScope scope(isolate());
698 this->SetField(kFunctionNameOffset_, name);
699 this->SetSmiValueField(kStartPositionOffset_, start_position);
700 this->SetSmiValueField(kEndPositionOffset_, end_position);
701 this->SetSmiValueField(kParamNumOffset_, param_num);
702 this->SetSmiValueField(kLiteralNumOffset_, literal_count);
703 this->SetSmiValueField(kParentIndexOffset_, parent_index);
705 void SetFunctionCode(Handle<Code> function_code,
706 Handle<HeapObject> code_scope_info) {
707 Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
708 this->SetField(kCodeOffset_, code_wrapper);
710 Handle<JSValue> scope_wrapper = WrapInJSValue(code_scope_info);
711 this->SetField(kCodeScopeInfoOffset_, scope_wrapper);
713 void SetFunctionScopeInfo(Handle<Object> scope_info_array) {
714 this->SetField(kFunctionScopeInfoOffset_, scope_info_array);
716 void SetSharedFunctionInfo(Handle<SharedFunctionInfo>
info) {
717 Handle<JSValue> info_holder = WrapInJSValue(info);
718 this->SetField(kSharedFunctionInfoOffset_, info_holder);
720 int GetLiteralCount() {
721 return this->GetSmiValueField(kLiteralNumOffset_);
723 int GetParentIndex() {
724 return this->GetSmiValueField(kParentIndexOffset_);
726 Handle<Code> GetFunctionCode() {
727 Handle<Object> element = this->GetField(kCodeOffset_);
729 Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
730 CHECK(raw_result->IsCode());
733 Handle<Object> GetCodeScopeInfo() {
734 Handle<Object> element = this->GetField(kCodeScopeInfoOffset_);
735 return UnwrapJSValue(Handle<JSValue>::cast(element));
737 int GetStartPosition() {
738 return this->GetSmiValueField(kStartPositionOffset_);
740 int GetEndPosition() {
741 return this->GetSmiValueField(kEndPositionOffset_);
745 static const int kFunctionNameOffset_ = 0;
746 static const int kStartPositionOffset_ = 1;
747 static const int kEndPositionOffset_ = 2;
748 static const int kParamNumOffset_ = 3;
749 static const int kCodeOffset_ = 4;
750 static const int kCodeScopeInfoOffset_ = 5;
751 static const int kFunctionScopeInfoOffset_ = 6;
752 static const int kParentIndexOffset_ = 7;
753 static const int kSharedFunctionInfoOffset_ = 8;
754 static const int kLiteralNumOffset_ = 9;
755 static const int kSize_ = 10;
757 friend class JSArrayBasedStruct<FunctionInfoWrapper>;
764 class SharedInfoWrapper :
public JSArrayBasedStruct<SharedInfoWrapper> {
766 static bool IsInstance(Handle<JSArray> array) {
769 array->GetIsolate(), array, kSharedInfoOffset_)->IsJSValue();
772 explicit SharedInfoWrapper(Handle<JSArray> array)
773 : JSArrayBasedStruct<SharedInfoWrapper>(array) {
776 void SetProperties(Handle<String> name,
int start_position,
int end_position,
777 Handle<SharedFunctionInfo>
info) {
778 HandleScope scope(isolate());
779 this->SetField(kFunctionNameOffset_, name);
780 Handle<JSValue> info_holder = WrapInJSValue(info);
781 this->SetField(kSharedInfoOffset_, info_holder);
782 this->SetSmiValueField(kStartPositionOffset_, start_position);
783 this->SetSmiValueField(kEndPositionOffset_, end_position);
785 Handle<SharedFunctionInfo> GetInfo() {
786 Handle<Object> element = this->GetField(kSharedInfoOffset_);
788 return UnwrapSharedFunctionInfoFromJSValue(value_wrapper);
792 static const int kFunctionNameOffset_ = 0;
793 static const int kStartPositionOffset_ = 1;
794 static const int kEndPositionOffset_ = 2;
795 static const int kSharedInfoOffset_ = 3;
796 static const int kSize_ = 4;
798 friend class JSArrayBasedStruct<SharedInfoWrapper>;
802 class FunctionInfoListener {
804 explicit FunctionInfoListener(Isolate* isolate) {
805 current_parent_index_ = -1;
807 result_ = isolate->factory()->NewJSArray(10);
810 void FunctionStarted(FunctionLiteral* fun) {
811 HandleScope scope(isolate());
812 FunctionInfoWrapper
info = FunctionInfoWrapper::Create(isolate());
813 info.SetInitialProperties(fun->name(), fun->start_position(),
814 fun->end_position(), fun->parameter_count(),
815 fun->materialized_literal_count(),
816 current_parent_index_);
817 current_parent_index_ = len_;
818 SetElementSloppy(result_, len_, info.GetJSArray());
822 void FunctionDone() {
823 HandleScope scope(isolate());
824 FunctionInfoWrapper info =
825 FunctionInfoWrapper::cast(
827 isolate(), result_, current_parent_index_));
828 current_parent_index_ = info.GetParentIndex();
833 void FunctionCode(Handle<Code> function_code) {
834 FunctionInfoWrapper info =
835 FunctionInfoWrapper::cast(
837 isolate(), result_, current_parent_index_));
838 info.SetFunctionCode(function_code,
839 Handle<HeapObject>(isolate()->heap()->null_value()));
844 void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope,
846 if (!shared->IsSharedFunctionInfo()) {
849 FunctionInfoWrapper info =
850 FunctionInfoWrapper::cast(
852 isolate(), result_, current_parent_index_));
853 info.SetFunctionCode(Handle<Code>(shared->code()),
854 Handle<HeapObject>(shared->scope_info()));
855 info.SetSharedFunctionInfo(shared);
857 Handle<Object> scope_info_list(SerializeFunctionScope(scope, zone),
859 info.SetFunctionScopeInfo(scope_info_list);
862 Handle<JSArray> GetResult() {
return result_; }
865 Isolate* isolate()
const {
return result_->GetIsolate(); }
867 Object* SerializeFunctionScope(Scope* scope, Zone* zone) {
868 HandleScope handle_scope(isolate());
870 Handle<JSArray> scope_info_list = isolate()->factory()->NewJSArray(10);
871 int scope_info_length = 0;
876 Scope* current_scope = scope;
877 while (current_scope !=
NULL) {
878 ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone);
879 ZoneList<Variable*> context_list(
880 current_scope->ContextLocalCount(), zone);
881 current_scope->CollectStackAndContextLocals(&stack_list, &context_list);
884 for (
int i = 0; i < context_list.length(); i++) {
885 SetElementSloppy(scope_info_list,
887 context_list[i]->
name());
892 Handle<Smi>(
Smi::FromInt(context_list[i]->index()), isolate()));
895 SetElementSloppy(scope_info_list,
897 Handle<Object>(isolate()->heap()->null_value(),
901 current_scope = current_scope->outer_scope();
904 return *scope_info_list;
907 Handle<JSArray> result_;
909 int current_parent_index_;
913 JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
914 Handle<String> source) {
915 Isolate* isolate = script->GetIsolate();
917 FunctionInfoListener listener(isolate);
918 Handle<Object> original_source =
919 Handle<Object>(script->source(), isolate);
920 script->set_source(*source);
921 isolate->set_active_function_info_listener(&listener);
930 Compiler::CompileForLiveEdit(script);
934 Handle<JSObject> rethrow_exception;
935 if (isolate->has_pending_exception()) {
936 Handle<Object> exception(isolate->pending_exception()->ToObjectChecked(),
938 MessageLocation message_location = isolate->GetMessageLocation();
940 isolate->clear_pending_message();
941 isolate->clear_pending_exception();
944 if (exception->IsJSObject() && !message_location.script().is_null()) {
947 Factory* factory = isolate->factory();
948 Handle<String> start_pos_key = factory->InternalizeOneByteString(
950 Handle<String> end_pos_key = factory->InternalizeOneByteString(
952 Handle<String> script_obj_key = factory->InternalizeOneByteString(
954 Handle<Smi> start_pos(
956 Handle<Smi> end_pos(
Smi::FromInt(message_location.end_pos()), isolate);
959 rethrow_exception, start_pos_key, start_pos,
NONE,
SLOPPY);
961 rethrow_exception, end_pos_key, end_pos,
NONE,
SLOPPY);
963 rethrow_exception, script_obj_key, script_obj,
NONE,
SLOPPY);
968 isolate->set_active_function_info_listener(
NULL);
969 script->set_source(*original_source);
971 if (rethrow_exception.is_null()) {
972 return *(listener.GetResult());
974 isolate->Throw(*rethrow_exception);
980 void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
981 Isolate* isolate = array->GetIsolate();
982 HandleScope scope(isolate);
983 int len = GetArrayLength(array);
984 for (
int i = 0; i < len; i++) {
985 Handle<SharedFunctionInfo>
info(
988 SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
990 info_wrapper.SetProperties(name_handle, info->start_position(),
991 info->end_position(),
info);
992 SetElementSloppy(array, i, info_wrapper.GetJSArray());
1000 class ReplacingVisitor :
public ObjectVisitor {
1002 explicit ReplacingVisitor(Code* original, Code* substitution)
1003 : original_(original), substitution_(substitution) {
1006 virtual void VisitPointers(
Object** start,
Object** end) {
1007 for (
Object** p = start; p < end; p++) {
1008 if (*p == original_) {
1014 virtual void VisitCodeEntry(
Address entry) {
1016 Address substitution_entry = substitution_->instruction_start();
1021 virtual void VisitCodeTarget(RelocInfo* rinfo) {
1022 if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
1024 Address substitution_entry = substitution_->instruction_start();
1025 rinfo->set_target_address(substitution_entry);
1029 virtual void VisitDebugTarget(RelocInfo* rinfo) {
1030 VisitCodeTarget(rinfo);
1035 Code* substitution_;
1040 static void ReplaceCodeObject(Handle<Code> original,
1041 Handle<Code> substitution) {
1047 Heap* heap = original->GetHeap();
1049 "liveedit.cc ReplaceCodeObject");
1051 ASSERT(!heap->InNewSpace(*substitution));
1055 ReplacingVisitor visitor(*original, *substitution);
1060 heap->IterateRoots(&visitor,
VISIT_ALL);
1064 HeapIterator iterator(heap);
1065 for (HeapObject*
obj = iterator.next();
obj !=
NULL;
obj = iterator.next()) {
1076 class LiteralFixer {
1078 static void PatchLiterals(FunctionInfoWrapper* compile_info_wrapper,
1079 Handle<SharedFunctionInfo> shared_info,
1081 int new_literal_count = compile_info_wrapper->GetLiteralCount();
1082 if (new_literal_count > 0) {
1085 int old_literal_count = shared_info->num_literals();
1087 if (old_literal_count == new_literal_count) {
1090 ClearValuesVisitor visitor;
1091 IterateJSFunctions(*shared_info, &visitor);
1096 Handle<FixedArray> function_instances =
1097 CollectJSFunctions(shared_info, isolate);
1098 for (
int i = 0; i < function_instances->length(); i++) {
1100 Handle<FixedArray> old_literals(fun->literals());
1101 Handle<FixedArray> new_literals =
1102 isolate->factory()->NewFixedArray(new_literal_count);
1103 if (new_literal_count > 0) {
1104 Handle<Context> native_context;
1105 if (old_literals->length() >
1107 native_context = Handle<Context>(
1110 native_context = Handle<Context>(fun->context()->native_context());
1115 fun->set_literals(*new_literals);
1118 shared_info->set_num_literals(new_literal_count);
1125 template<
typename Visitor>
1126 static void IterateJSFunctions(SharedFunctionInfo* shared_info,
1130 HeapIterator iterator(shared_info->GetHeap());
1131 for (HeapObject*
obj = iterator.next();
obj !=
NULL;
1132 obj = iterator.next()) {
1133 if (
obj->IsJSFunction()) {
1135 if (function->shared() == shared_info) {
1136 visitor->visit(
function);
1144 static Handle<FixedArray> CollectJSFunctions(
1145 Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
1146 CountVisitor count_visitor;
1147 count_visitor.count = 0;
1148 IterateJSFunctions(*shared_info, &count_visitor);
1149 int size = count_visitor.count;
1151 Handle<FixedArray> result = isolate->factory()->NewFixedArray(size);
1153 CollectVisitor collect_visitor(result);
1154 IterateJSFunctions(*shared_info, &collect_visitor);
1159 class ClearValuesVisitor {
1161 void visit(JSFunction* fun) {
1162 FixedArray*
literals = fun->literals();
1163 int len = literals->length();
1165 literals->set_undefined(j);
1170 class CountVisitor {
1172 void visit(JSFunction* fun) {
1178 class CollectVisitor {
1180 explicit CollectVisitor(Handle<FixedArray> output)
1181 : m_output(output), m_pos(0) {}
1183 void visit(JSFunction* fun) {
1184 m_output->set(m_pos, fun);
1188 Handle<FixedArray> m_output;
1196 static bool IsJSFunctionCode(Code*
code) {
1197 return code->kind() == Code::FUNCTION;
1202 static bool IsInlined(JSFunction*
function, SharedFunctionInfo* candidate) {
1205 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION)
return false;
1207 DeoptimizationInputData* data =
1210 if (data == function->GetIsolate()->heap()->empty_fixed_array()) {
1214 FixedArray* literals = data->LiteralArray();
1216 int inlined_count = data->InlinedFunctionCount()->value();
1217 for (
int i = 0; i < inlined_count; ++i) {
1219 if (inlined->shared() == candidate)
return true;
1228 class DependentFunctionMarker:
public OptimizedFunctionVisitor {
1230 SharedFunctionInfo* shared_info_;
1233 explicit DependentFunctionMarker(SharedFunctionInfo* shared_info)
1234 : shared_info_(shared_info), found_(
false) { }
1236 virtual void EnterContext(Context* context) { }
1237 virtual void LeaveContext(Context* context) { }
1238 virtual void VisitFunction(JSFunction*
function) {
1240 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
1241 if (shared_info_ == function->shared() ||
1242 IsInlined(
function, shared_info_)) {
1244 function->code()->set_marked_for_deoptimization(
true);
1251 static void DeoptimizeDependentFunctions(SharedFunctionInfo* function_info) {
1253 DependentFunctionMarker marker(function_info);
1257 if (marker.found_) {
1264 MaybeObject* LiveEdit::ReplaceFunctionCode(
1265 Handle<JSArray> new_compile_info_array,
1266 Handle<JSArray> shared_info_array) {
1267 Isolate* isolate = new_compile_info_array->GetIsolate();
1268 HandleScope scope(isolate);
1270 if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
1271 return isolate->ThrowIllegalOperation();
1274 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
1275 SharedInfoWrapper shared_info_wrapper(shared_info_array);
1277 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
1279 isolate->heap()->EnsureHeapIsIterable();
1281 if (IsJSFunctionCode(shared_info->code())) {
1282 Handle<Code> code = compile_info_wrapper.GetFunctionCode();
1283 ReplaceCodeObject(Handle<Code>(shared_info->code()), code);
1284 Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
1285 if (code_scope_info->IsFixedArray()) {
1288 shared_info->DisableOptimization(kLiveEdit);
1291 if (shared_info->debug_info()->IsDebugInfo()) {
1292 Handle<DebugInfo> debug_info(DebugInfo::cast(shared_info->debug_info()));
1293 Handle<Code> new_original_code =
1294 isolate->factory()->CopyCode(compile_info_wrapper.GetFunctionCode());
1295 debug_info->set_original_code(*new_original_code);
1298 int start_position = compile_info_wrapper.GetStartPosition();
1299 int end_position = compile_info_wrapper.GetEndPosition();
1300 shared_info->set_start_position(start_position);
1301 shared_info->set_end_position(end_position);
1303 LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info, isolate);
1305 shared_info->set_construct_stub(
1306 isolate->builtins()->builtin(Builtins::kJSConstructStubGeneric));
1308 DeoptimizeDependentFunctions(*shared_info);
1309 isolate->compilation_cache()->Remove(shared_info);
1311 return isolate->heap()->undefined_value();
1315 MaybeObject* LiveEdit::FunctionSourceUpdated(
1316 Handle<JSArray> shared_info_array) {
1317 Isolate* isolate = shared_info_array->GetIsolate();
1318 HandleScope scope(isolate);
1320 if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
1321 return isolate->ThrowIllegalOperation();
1324 SharedInfoWrapper shared_info_wrapper(shared_info_array);
1325 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
1327 DeoptimizeDependentFunctions(*shared_info);
1328 isolate->compilation_cache()->Remove(shared_info);
1330 return isolate->heap()->undefined_value();
1334 void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
1335 Handle<Object> script_handle) {
1336 Handle<SharedFunctionInfo> shared_info =
1337 UnwrapSharedFunctionInfoFromJSValue(function_wrapper);
1338 CHECK(script_handle->IsScript() || script_handle->IsUndefined());
1339 shared_info->set_script(*script_handle);
1341 function_wrapper->GetIsolate()->compilation_cache()->Remove(shared_info);
1354 static int TranslatePosition(
int original_position,
1355 Handle<JSArray> position_change_array) {
1356 int position_diff = 0;
1357 int array_len = GetArrayLength(position_change_array);
1358 Isolate* isolate = position_change_array->GetIsolate();
1360 for (
int i = 0; i < array_len; i += 3) {
1361 HandleScope scope(isolate);
1363 isolate, position_change_array, i);
1364 CHECK(element->IsSmi());
1366 if (original_position < chunk_start) {
1370 isolate, position_change_array, i + 1);
1371 CHECK(element->IsSmi());
1374 ASSERT(original_position >= chunk_end);
1376 isolate, position_change_array, i + 2);
1377 CHECK(element->IsSmi());
1379 position_diff = chunk_changed_end - chunk_end;
1382 return original_position + position_diff;
1392 class RelocInfoBuffer {
1394 RelocInfoBuffer(
int buffer_initial_capicity,
byte*
pc) {
1395 buffer_size_ = buffer_initial_capicity + kBufferGap;
1396 buffer_ = NewArray<byte>(buffer_size_);
1398 reloc_info_writer_.Reposition(buffer_ + buffer_size_, pc);
1400 ~RelocInfoBuffer() {
1406 void Write(
const RelocInfo* rinfo) {
1407 if (buffer_ + kBufferGap >= reloc_info_writer_.pos()) {
1410 reloc_info_writer_.Write(rinfo);
1413 Vector<byte> GetResult() {
1416 static_cast<int>((buffer_ + buffer_size_) - reloc_info_writer_.pos());
1417 return Vector<byte>(reloc_info_writer_.pos(), result_size);
1423 int new_buffer_size;
1424 if (buffer_size_ < 2 *
KB) {
1425 new_buffer_size = 4 *
KB;
1427 new_buffer_size = 2 * buffer_size_;
1431 if (new_buffer_size > kMaximalBufferSize) {
1436 byte* new_buffer = NewArray<byte>(new_buffer_size);
1439 int curently_used_size =
1440 static_cast<int>(buffer_ + buffer_size_ - reloc_info_writer_.pos());
1441 OS::MemMove(new_buffer + new_buffer_size - curently_used_size,
1442 reloc_info_writer_.pos(), curently_used_size);
1444 reloc_info_writer_.Reposition(
1445 new_buffer + new_buffer_size - curently_used_size,
1446 reloc_info_writer_.last_pc());
1449 buffer_ = new_buffer;
1450 buffer_size_ = new_buffer_size;
1453 RelocInfoWriter reloc_info_writer_;
1457 static const int kBufferGap = RelocInfoWriter::kMaxSize;
1458 static const int kMaximalBufferSize = 512*
MB;
1464 static Handle<Code> PatchPositionsInCode(
1466 Handle<JSArray> position_change_array) {
1467 Isolate* isolate = code->GetIsolate();
1469 RelocInfoBuffer buffer_writer(code->relocation_size(),
1470 code->instruction_start());
1473 for (RelocIterator it(*code); !it.done(); it.next()) {
1474 RelocInfo* rinfo = it.rinfo();
1475 if (RelocInfo::IsPosition(rinfo->rmode())) {
1476 int position =
static_cast<int>(rinfo->data());
1477 int new_position = TranslatePosition(position,
1478 position_change_array);
1479 if (position != new_position) {
1480 RelocInfo info_copy(rinfo->pc(), rinfo->rmode(), new_position,
NULL);
1481 buffer_writer.Write(&info_copy);
1485 if (RelocInfo::IsRealRelocMode(rinfo->rmode())) {
1486 buffer_writer.Write(it.rinfo());
1491 Vector<byte> buffer = buffer_writer.GetResult();
1493 if (buffer.length() == code->relocation_size()) {
1495 OS::MemCopy(code->relocation_start(), buffer.start(), buffer.length());
1501 Handle<Code> result(isolate->factory()->CopyCode(code, buffer));
1507 MaybeObject* LiveEdit::PatchFunctionPositions(
1508 Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
1509 if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
1510 return shared_info_array->GetIsolate()->ThrowIllegalOperation();
1513 SharedInfoWrapper shared_info_wrapper(shared_info_array);
1514 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
1516 int old_function_start = info->start_position();
1517 int new_function_start = TranslatePosition(old_function_start,
1518 position_change_array);
1519 int new_function_end = TranslatePosition(info->end_position(),
1520 position_change_array);
1521 int new_function_token_pos =
1522 TranslatePosition(info->function_token_position(), position_change_array);
1524 info->set_start_position(new_function_start);
1525 info->set_end_position(new_function_end);
1526 info->set_function_token_position(new_function_token_pos);
1528 info->GetIsolate()->heap()->EnsureHeapIsIterable();
1530 if (IsJSFunctionCode(info->code())) {
1532 Handle<Code> patched_code = PatchPositionsInCode(Handle<Code>(info->code()),
1533 position_change_array);
1534 if (*patched_code != info->code()) {
1540 ReplaceCodeObject(Handle<Code>(info->code()), patched_code);
1544 return info->GetIsolate()->heap()->undefined_value();
1548 static Handle<Script> CreateScriptCopy(Handle<Script> original) {
1549 Isolate* isolate = original->GetIsolate();
1551 Handle<String> original_source(
String::cast(original->source()));
1552 Handle<Script> copy = isolate->factory()->NewScript(original_source);
1554 copy->set_name(original->name());
1555 copy->set_line_offset(original->line_offset());
1556 copy->set_column_offset(original->column_offset());
1557 copy->set_type(original->type());
1558 copy->set_context_data(original->context_data());
1559 copy->set_eval_from_shared(original->eval_from_shared());
1560 copy->set_eval_from_instructions_offset(
1561 original->eval_from_instructions_offset());
1564 copy->set_flags(original->flags());
1571 Object* LiveEdit::ChangeScriptSource(Handle<Script> original_script,
1572 Handle<String> new_source,
1573 Handle<Object> old_script_name) {
1574 Isolate* isolate = original_script->GetIsolate();
1575 Handle<Object> old_script_object;
1576 if (old_script_name->IsString()) {
1577 Handle<Script> old_script = CreateScriptCopy(original_script);
1579 old_script_object = old_script;
1580 isolate->debugger()->OnAfterCompile(
1581 old_script, Debugger::SEND_WHEN_DEBUGGING);
1583 old_script_object = isolate->factory()->null_value();
1586 original_script->set_source(*new_source);
1589 original_script->set_line_ends(isolate->heap()->undefined_value());
1591 return *old_script_object;
1596 void LiveEdit::ReplaceRefToNestedFunction(
1597 Handle<JSValue> parent_function_wrapper,
1598 Handle<JSValue> orig_function_wrapper,
1599 Handle<JSValue> subst_function_wrapper) {
1601 Handle<SharedFunctionInfo> parent_shared =
1602 UnwrapSharedFunctionInfoFromJSValue(parent_function_wrapper);
1603 Handle<SharedFunctionInfo> orig_shared =
1604 UnwrapSharedFunctionInfoFromJSValue(orig_function_wrapper);
1605 Handle<SharedFunctionInfo> subst_shared =
1606 UnwrapSharedFunctionInfoFromJSValue(subst_function_wrapper);
1608 for (RelocIterator it(parent_shared->code()); !it.done(); it.next()) {
1609 if (it.rinfo()->rmode() == RelocInfo::EMBEDDED_OBJECT) {
1610 if (it.rinfo()->target_object() == *orig_shared) {
1611 it.rinfo()->set_target_object(*subst_shared);
1620 static bool CheckActivation(Handle<JSArray> shared_info_array,
1621 Handle<JSArray> result,
1623 LiveEdit::FunctionPatchabilityStatus status) {
1624 if (!frame->is_java_script())
return false;
1628 Isolate* isolate = shared_info_array->GetIsolate();
1629 int len = GetArrayLength(shared_info_array);
1630 for (
int i = 0; i < len; i++) {
1631 HandleScope scope(isolate);
1632 Handle<Object> element =
1635 Handle<SharedFunctionInfo> shared =
1636 UnwrapSharedFunctionInfoFromJSValue(jsvalue);
1638 if (function->shared() == *shared || IsInlined(*
function, *shared)) {
1639 SetElementSloppy(result, i, Handle<Smi>(
Smi::FromInt(status), isolate));
1649 static bool FixTryCatchHandler(
StackFrame* top_frame,
1653 Isolate::kHandlerAddress));
1655 while (*pointer_address < top_frame->
sp()) {
1658 Address* above_frame_address = pointer_address;
1659 while (*pointer_address < bottom_frame->
fp()) {
1662 bool change = *above_frame_address != *pointer_address;
1663 *above_frame_address = *pointer_address;
1672 static const char* DropFrames(Vector<StackFrame*> frames,
1673 int top_frame_index,
1674 int bottom_js_frame_index,
1675 Debug::FrameDropMode*
mode,
1676 Object*** restarter_frame_function_pointer) {
1677 if (!Debug::kFrameDropperSupported) {
1678 return "Stack manipulations are not supported in this architecture.";
1681 StackFrame* pre_top_frame = frames[top_frame_index - 1];
1682 StackFrame* top_frame = frames[top_frame_index];
1683 StackFrame* bottom_js_frame = frames[bottom_js_frame_index];
1685 ASSERT(bottom_js_frame->is_java_script());
1688 Isolate* isolate = bottom_js_frame->isolate();
1689 Code* pre_top_frame_code = pre_top_frame->LookupCode();
1690 bool frame_has_padding;
1691 if (pre_top_frame_code->is_inline_cache_stub() &&
1692 pre_top_frame_code->is_debug_stub()) {
1694 *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
1695 frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
1696 }
else if (pre_top_frame_code ==
1697 isolate->debug()->debug_break_slot()) {
1699 *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
1700 frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
1701 }
else if (pre_top_frame_code ==
1702 isolate->builtins()->builtin(
1703 Builtins::kFrameDropper_LiveEdit)) {
1705 pre_top_frame = frames[top_frame_index - 2];
1706 top_frame = frames[top_frame_index - 1];
1707 *mode = Debug::CURRENTLY_SET_MODE;
1708 frame_has_padding =
false;
1709 }
else if (pre_top_frame_code ==
1710 isolate->builtins()->builtin(Builtins::kReturn_DebugBreak)) {
1711 *mode = Debug::FRAME_DROPPED_IN_RETURN_CALL;
1712 frame_has_padding = Debug::FramePaddingLayout::kIsSupported;
1713 }
else if (pre_top_frame_code->kind() ==
Code::STUB &&
1714 pre_top_frame_code->major_key() == CodeStub::CEntry) {
1717 *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
1721 frame_has_padding =
false;
1725 ASSERT(frames[top_frame_index - 2]->LookupCode() ==
1726 isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit));
1727 pre_top_frame = frames[top_frame_index - 3];
1728 top_frame = frames[top_frame_index - 2];
1729 *mode = Debug::CURRENTLY_SET_MODE;
1730 frame_has_padding =
false;
1732 return "Unknown structure of stack above changing function";
1735 Address unused_stack_top = top_frame->sp();
1736 Address unused_stack_bottom = bottom_js_frame->fp()
1740 Address* top_frame_pc_address = top_frame->pc_address();
1745 if (unused_stack_top > unused_stack_bottom) {
1746 if (frame_has_padding) {
1747 int shortage_bytes =
1748 static_cast<int>(unused_stack_top - unused_stack_bottom);
1750 Address padding_start = pre_top_frame->fp() -
1751 Debug::FramePaddingLayout::kFrameBaseSize *
kPointerSize;
1753 Address padding_pointer = padding_start;
1754 Smi* padding_object =
1755 Smi::FromInt(Debug::FramePaddingLayout::kPaddingValue);
1759 int padding_counter =
1761 if (padding_counter * kPointerSize < shortage_bytes) {
1762 return "Not enough space for frame dropper frame "
1763 "(even with padding frame)";
1766 Smi::FromInt(padding_counter - shortage_bytes / kPointerSize);
1768 StackFrame* pre_pre_frame = frames[top_frame_index - 2];
1770 OS::MemMove(padding_start + kPointerSize - shortage_bytes,
1771 padding_start + kPointerSize,
1772 Debug::FramePaddingLayout::kFrameBaseSize * kPointerSize);
1774 pre_top_frame->UpdateFp(pre_top_frame->fp() - shortage_bytes);
1775 pre_pre_frame->SetCallerFp(pre_top_frame->fp());
1776 unused_stack_top -= shortage_bytes;
1781 return "Not enough space for frame dropper frame";
1787 FixTryCatchHandler(pre_top_frame, bottom_js_frame);
1789 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame));
1791 Handle<Code> code = isolate->builtins()->FrameDropper_LiveEdit();
1792 *top_frame_pc_address = code->entry();
1793 pre_top_frame->SetCallerFp(bottom_js_frame->fp());
1795 *restarter_frame_function_pointer =
1796 Debug::SetUpFrameDropperFrame(bottom_js_frame, code);
1798 ASSERT((**restarter_frame_function_pointer)->IsJSFunction());
1800 for (
Address a = unused_stack_top;
1801 a < unused_stack_bottom;
1810 static bool IsDropableFrame(
StackFrame* frame) {
1811 return !frame->is_exit();
1817 class MultipleFunctionTarget {
1819 MultipleFunctionTarget(Handle<JSArray> shared_info_array,
1820 Handle<JSArray> result)
1821 : m_shared_info_array(shared_info_array),
1824 LiveEdit::FunctionPatchabilityStatus status) {
1825 return CheckActivation(m_shared_info_array, m_result, frame, status);
1827 const char* GetNotFoundMessage() {
1831 Handle<JSArray> m_shared_info_array;
1832 Handle<JSArray> m_result;
1837 template<
typename TARGET>
1838 static const char* DropActivationsInActiveThreadImpl(
1839 Isolate* isolate, TARGET& target,
bool do_drop) {
1840 Debug* debug = isolate->debug();
1845 int top_frame_index = -1;
1846 int frame_index = 0;
1847 for (; frame_index < frames.length(); frame_index++) {
1849 if (frame->id() == debug->break_frame_id()) {
1850 top_frame_index = frame_index;
1853 if (target.MatchActivation(
1854 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
1857 return "Debugger mark-up on stack is not found";
1861 if (top_frame_index == -1) {
1863 return target.GetNotFoundMessage();
1866 bool target_frame_found =
false;
1867 int bottom_js_frame_index = top_frame_index;
1868 bool c_code_found =
false;
1870 for (; frame_index < frames.length(); frame_index++) {
1872 if (!IsDropableFrame(frame)) {
1873 c_code_found =
true;
1876 if (target.MatchActivation(
1877 frame, LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1878 target_frame_found =
true;
1879 bottom_js_frame_index = frame_index;
1886 for (; frame_index < frames.length(); frame_index++) {
1888 if (frame->is_java_script()) {
1889 if (target.MatchActivation(
1890 frame, LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE)) {
1903 if (!target_frame_found) {
1905 return target.GetNotFoundMessage();
1908 Debug::FrameDropMode drop_mode = Debug::FRAMES_UNTOUCHED;
1909 Object** restarter_frame_function_pointer =
NULL;
1910 const char* error_message = DropFrames(frames, top_frame_index,
1911 bottom_js_frame_index, &drop_mode,
1912 &restarter_frame_function_pointer);
1914 if (error_message !=
NULL) {
1915 return error_message;
1919 StackFrame::Id new_id = StackFrame::NO_ID;
1920 for (
int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
1921 if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
1922 new_id = frames[i]->id();
1926 debug->FramesHaveBeenDropped(new_id, drop_mode,
1927 restarter_frame_function_pointer);
1934 static const char* DropActivationsInActiveThread(
1935 Handle<JSArray> shared_info_array, Handle<JSArray> result,
bool do_drop) {
1936 MultipleFunctionTarget target(shared_info_array, result);
1938 const char*
message = DropActivationsInActiveThreadImpl(
1939 shared_info_array->GetIsolate(), target, do_drop);
1944 Isolate* isolate = shared_info_array->GetIsolate();
1945 int array_len = GetArrayLength(shared_info_array);
1948 for (
int i = 0; i < array_len; i++) {
1949 Handle<Object>
obj =
1951 if (*obj ==
Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
1952 Handle<Object> replaced(
1953 Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
1954 SetElementSloppy(result, i, replaced);
1961 class InactiveThreadActivationsChecker :
public ThreadVisitor {
1963 InactiveThreadActivationsChecker(Handle<JSArray> shared_info_array,
1964 Handle<JSArray> result)
1965 : shared_info_array_(shared_info_array), result_(result),
1966 has_blocked_functions_(
false) {
1968 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1969 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1970 has_blocked_functions_ |= CheckActivation(
1971 shared_info_array_, result_, it.frame(),
1972 LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
1975 bool HasBlockedFunctions() {
1976 return has_blocked_functions_;
1980 Handle<JSArray> shared_info_array_;
1981 Handle<JSArray> result_;
1982 bool has_blocked_functions_;
1986 Handle<JSArray> LiveEdit::CheckAndDropActivations(
1987 Handle<JSArray> shared_info_array,
bool do_drop) {
1988 Isolate* isolate = shared_info_array->GetIsolate();
1989 int len = GetArrayLength(shared_info_array);
1991 Handle<JSArray> result = isolate->factory()->NewJSArray(len);
1994 for (
int i = 0; i < len; i++) {
1998 Handle<Smi>(
Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
2003 InactiveThreadActivationsChecker inactive_threads_checker(shared_info_array,
2005 isolate->thread_manager()->IterateArchivedThreads(
2006 &inactive_threads_checker);
2007 if (inactive_threads_checker.HasBlockedFunctions()) {
2012 const char* error_message =
2013 DropActivationsInActiveThread(shared_info_array, result, do_drop);
2014 if (error_message !=
NULL) {
2016 Handle<String> str = isolate->factory()->NewStringFromAscii(
2018 SetElementSloppy(result, len, str);
2026 class SingleFrameTarget {
2028 explicit SingleFrameTarget(JavaScriptFrame* frame)
2030 m_saved_status(LiveEdit::FUNCTION_AVAILABLE_FOR_PATCH) {}
2033 LiveEdit::FunctionPatchabilityStatus status) {
2034 if (frame->fp() == m_frame->fp()) {
2035 m_saved_status = status;
2040 const char* GetNotFoundMessage() {
2041 return "Failed to found requested frame";
2043 LiveEdit::FunctionPatchabilityStatus saved_status() {
2044 return m_saved_status;
2047 JavaScriptFrame* m_frame;
2048 LiveEdit::FunctionPatchabilityStatus m_saved_status;
2054 const char* LiveEdit::RestartFrame(JavaScriptFrame* frame) {
2055 SingleFrameTarget target(frame);
2057 const char* result = DropActivationsInActiveThreadImpl(
2058 frame->isolate(), target,
true);
2059 if (result !=
NULL) {
2062 if (target.saved_status() == LiveEdit::FUNCTION_BLOCKED_UNDER_NATIVE_CODE) {
2063 return "Function is blocked under native code";
2070 FunctionLiteral* fun)
2071 : isolate_(isolate) {
2072 if (isolate_->active_function_info_listener() !=
NULL) {
2073 isolate_->active_function_info_listener()->FunctionStarted(fun);
2079 if (isolate_->active_function_info_listener() !=
NULL) {
2080 isolate_->active_function_info_listener()->FunctionDone();
2086 Handle<SharedFunctionInfo> info, FunctionLiteral* lit,
2088 if (isolate_->active_function_info_listener() !=
NULL) {
2089 isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(),
2096 isolate_->active_function_info_listener()->FunctionCode(code);
2101 return isolate->active_function_info_listener() !=
NULL;
2105 #else // ENABLE_DEBUGGER_SUPPORT
2110 FunctionLiteral* fun) {
2132 #endif // ENABLE_DEBUGGER_SUPPORT
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static Handle< 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)
static Object *& Object_at(Address addr)
void RecordRootFunctionInfo(Handle< Code > code)
static bool IsActive(Isolate *isolate)
static String * cast(Object *obj)
static Smi * FromInt(int value)
static Object * GetObjectFromEntryAddress(Address location_of_address)
Handle< FixedArray > CalculateLineEnds(Handle< String > src, bool with_last_line)
static Handle< T > cast(Handle< S > that)
kSerializedDataOffset Object
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
Vector< StackFrame * > CreateStackMap(Isolate *isolate, Zone *zone)
static Handle< Object > GetElementNoExceptionThrown(Isolate *isolate, Handle< Object > object, uint32_t index)
#define ASSERT(condition)
LiveEditFunctionTracker(Isolate *isolate, FunctionLiteral *fun)
static SharedFunctionInfo * cast(Object *obj)
void SetVerbose(bool value)
static Smi * cast(Object *object)
Handle< String > FlattenGetString(Handle< String > string)
static ScopeInfo * cast(Object *object)
static void VisitAllOptimizedFunctions(Isolate *isolate, OptimizedFunctionVisitor *visitor)
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static const int kLiteralNativeContextIndex
void Iterate(ObjectVisitor *v)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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_string(expose_natives_as
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
static void MemCopy(void *dest, const void *src, size_t size)
static int CompareIndex(Variable *const *v, Variable *const *w)
static Address & Address_at(Address addr)
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static void MemMove(void *dest, const void *src, size_t size)
static Code * GetCodeFromTargetAddress(Address address)
static const int kMakeHeapIterableMask
static JavaScriptFrame * cast(StackFrame *frame)
#define STATIC_ASCII_VECTOR(x)
Vector< const char > CStrVector(const char *data)
static JSArray * cast(Object *obj)
void RecordFunctionInfo(Handle< SharedFunctionInfo > info, FunctionLiteral *lit, Zone *zone)
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
~LiveEditFunctionTracker()
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
const uint32_t kMaxUInt32
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric literals(0o77, 0b11)") DEFINE_bool(harmony_strings
static void DeoptimizeMarkedCode(Isolate *isolate)
void DeleteArray(T *array)
static Context * NativeContextFromLiterals(FixedArray *literals)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV 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 expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
JSFunction * function() const
static const int kLiteralsPrefixSize
static JSFunction * cast(Object *obj)