34bool CompareSubstrings(DirectHandle<String> s1,
int pos1,
35 DirectHandle<String> s2,
int pos2,
int len) {
36 for (
int i = 0;
i < len;
i++) {
37 if (s1->Get(
i + pos1) != s2->Get(
i + pos2))
return false;
46class SubrangableInput :
public Comparator::Input {
48 virtual void SetSubrange1(
int offset,
int len) = 0;
49 virtual void SetSubrange2(
int offset,
int len) = 0;
53class SubrangableOutput :
public Comparator::Output {
55 virtual void SetSubrange1(
int offset,
int len) = 0;
56 virtual void SetSubrange2(
int offset,
int len) = 0;
61void NarrowDownInput(SubrangableInput* input, SubrangableOutput* output) {
62 const int len1 = input->GetLength1();
63 const int len2 = input->GetLength2();
65 int common_prefix_len;
66 int common_suffix_len;
69 common_prefix_len = 0;
70 int prefix_limit = std::min(len1, len2);
71 while (common_prefix_len < prefix_limit &&
72 input->Equals(common_prefix_len, common_prefix_len)) {
76 common_suffix_len = 0;
78 std::min(len1 - common_prefix_len, len2 - common_prefix_len);
80 while (common_suffix_len < suffix_limit &&
81 input->Equals(len1 - common_suffix_len - 1,
82 len2 - common_suffix_len - 1)) {
87 if (common_prefix_len > 0 || common_suffix_len > 0) {
88 int new_len1 = len1 - common_suffix_len - common_prefix_len;
89 int new_len2 = len2 - common_suffix_len - common_prefix_len;
91 input->SetSubrange1(common_prefix_len, new_len1);
92 input->SetSubrange2(common_prefix_len, new_len2);
94 output->SetSubrange1(common_prefix_len, new_len1);
95 output->SetSubrange2(common_prefix_len, new_len2);
102class TokensCompareInput :
public Comparator::Input {
104 TokensCompareInput(Handle<String> s1,
int offset1,
int len1,
105 Handle<String> s2,
int offset2,
int len2)
109 int GetLength1()
override {
return len1_; }
110 int GetLength2()
override {
return len2_; }
111 bool Equals(
int index1,
int index2)
override {
112 return s1_->Get(offset1_ + index1) ==
s2_->Get(offset2_ + index2);
126class TokensCompareOutput :
public Comparator::Output {
128 TokensCompareOutput(
int offset1,
int offset2,
129 std::vector<SourceChangeRange>* output)
132 void AddChunk(
int pos1,
int pos2,
int len1,
int len2)
override {
146class LineEndsWrapper {
148 explicit LineEndsWrapper(Isolate* isolate, DirectHandle<String>
string)
156 int GetLineStart(
int index) {
return index == 0 ? 0 : GetLineEnd(index - 1); }
157 int GetLineEnd(
int index) {
164 return GetPosAfterNewLine(index);
172 int GetPosAfterNewLine(
int index) {
178class LineArrayCompareInput :
public SubrangableInput {
180 LineArrayCompareInput(Handle<String> s1, Handle<String> s2,
181 LineEndsWrapper line_ends1, LineEndsWrapper line_ends2)
190 bool Equals(
int index1,
int index2)
override {
194 int line_start1 =
line_ends1_.GetLineStart(index1);
195 int line_start2 =
line_ends2_.GetLineStart(index2);
198 int len1 = line_end1 - line_start1;
199 int len2 = line_end2 - line_start2;
203 return CompareSubstrings(s1_, line_start1, s2_, line_start2,
206 void SetSubrange1(
int offset,
int len)
override {
210 void SetSubrange2(
int offset,
int len)
override {
228class TokenizingLineArrayCompareOutput :
public SubrangableOutput {
230 TokenizingLineArrayCompareOutput(Isolate* isolate, LineEndsWrapper line_ends1,
231 LineEndsWrapper line_ends2,
232 Handle<String> s1, Handle<String> s2,
233 std::vector<SourceChangeRange>* output)
243 void AddChunk(
int line_pos1,
int line_pos2,
int line_len1,
244 int line_len2)
override {
248 int char_pos1 =
line_ends1_.GetLineStart(line_pos1);
249 int char_pos2 =
line_ends2_.GetLineStart(line_pos2);
250 int char_len1 =
line_ends1_.GetLineStart(line_pos1 + line_len1) - char_pos1;
251 int char_len2 =
line_ends2_.GetLineStart(line_pos2 + line_len2) - char_pos2;
253 if (char_len1 < CHUNK_LEN_LIMIT && char_len2 < CHUNK_LEN_LIMIT) {
255 HandleScope subTaskScope(isolate_);
257 TokensCompareInput tokens_input(s1_, char_pos1, char_len1,
258 s2_, char_pos2, char_len2);
259 TokensCompareOutput tokens_output(char_pos1, char_pos2, output_);
263 output_->emplace_back(SourceChangeRange{
264 char_pos1, char_pos1 + char_len1, char_pos2, char_pos2 + char_len2});
267 void SetSubrange1(
int offset,
int len)
override {
270 void SetSubrange2(
int offset,
int len)
override {
284 std::vector<SourceChangeRange>*
output_;
287struct SourcePositionEvent {
288 enum Type { LITERAL_STARTS, LITERAL_ENDS, DIFF_STARTS, DIFF_ENDS };
298 SourcePositionEvent(FunctionLiteral*
literal,
bool is_start)
301 type(is_start ? LITERAL_STARTS : LITERAL_ENDS),
303 SourcePositionEvent(
const SourceChangeRange& change,
bool is_start)
304 :
position(is_start ? change.start_position : change.end_position),
305 type(is_start ? DIFF_STARTS : DIFF_ENDS),
307 (change.end_position - change.start_position)) {}
309 static bool LessThan(
const SourcePositionEvent& a,
310 const SourcePositionEvent& b) {
311 if (a.position != b.position)
return a.position < b.position;
312 if (a.type != b.type)
return a.type < b.type;
313 if (a.type == LITERAL_STARTS && b.type == LITERAL_STARTS) {
316 if (a.literal->end_position() != b.literal->end_position()) {
317 return a.literal->end_position() > b.literal->end_position();
321 return a.literal->function_literal_id() <
322 b.literal->function_literal_id();
323 }
else if (a.type == LITERAL_ENDS && b.type == LITERAL_ENDS) {
326 if (a.literal->start_position() != b.literal->start_position()) {
327 return a.literal->start_position() > b.literal->start_position();
331 return a.literal->function_literal_id() >
332 b.literal->function_literal_id();
334 return a.pos_diff < b.pos_diff;
339struct FunctionLiteralChange {
347 explicit FunctionLiteralChange(
int new_start_position, FunctionLiteral* outer)
354using FunctionLiteralChanges =
355 std::unordered_map<FunctionLiteral*, FunctionLiteralChange>;
356void CalculateFunctionLiteralChanges(
357 const std::vector<FunctionLiteral*>& literals,
358 const std::vector<SourceChangeRange>& diffs,
359 FunctionLiteralChanges*
result) {
360 std::vector<SourcePositionEvent> events;
361 events.reserve(literals.size() * 2 + diffs.size() * 2);
362 for (FunctionLiteral*
literal : literals) {
363 events.emplace_back(
literal,
true);
364 events.emplace_back(
literal,
false);
366 for (
const SourceChangeRange& diff : diffs) {
367 events.emplace_back(diff,
true);
368 events.emplace_back(diff,
false);
370 std::sort(events.begin(), events.end(), SourcePositionEvent::LessThan);
371 bool inside_diff =
false;
373 std::stack<std::pair<FunctionLiteral*, FunctionLiteralChange>> literal_stack;
374 for (
const SourcePositionEvent& event : events) {
375 switch (event.type) {
376 case SourcePositionEvent::DIFF_ENDS:
379 delta +=
event.pos_diff;
381 case SourcePositionEvent::LITERAL_ENDS: {
382 DCHECK_EQ(literal_stack.top().first, event.literal);
383 FunctionLiteralChange& change = literal_stack.top().second;
384 change.new_end_position = inside_diff
386 :
event.literal->end_position() + delta;
391 case SourcePositionEvent::LITERAL_STARTS:
392 literal_stack.push(std::make_pair(
394 FunctionLiteralChange(
396 : event.literal->start_position() + delta,
397 literal_stack.empty() ?
nullptr : literal_stack.top().first)));
399 case SourcePositionEvent::DIFF_STARTS:
402 if (!literal_stack.empty()) {
407 literal_stack.top().second.has_changes =
true;
419bool HasChangedScope(FunctionLiteral* a, FunctionLiteral* b) {
420 Scope* scope_a = a->scope()->outer_scope();
421 Scope* scope_b = b->scope()->outer_scope();
422 while (scope_a && scope_b) {
423 std::unordered_map<int, Handle<String>> vars;
424 for (
Variable* var : *scope_a->locals()) {
425 if (!var->IsContextSlot())
continue;
426 vars[var->index()] = var->name();
428 for (
Variable* var : *scope_b->locals()) {
429 if (!var->IsContextSlot())
continue;
430 auto it = vars.find(var->index());
431 if (it == vars.end())
return true;
432 if (*it->second != *var->name())
return true;
434 scope_a = scope_a->outer_scope();
435 scope_b = scope_b->outer_scope();
437 return scope_a != scope_b;
440enum ChangeState { UNCHANGED, CHANGED, DAMAGED };
442using LiteralMap = std::unordered_map<FunctionLiteral*, FunctionLiteral*>;
443void MapLiterals(
const FunctionLiteralChanges& changes,
444 const std::vector<FunctionLiteral*>& new_literals,
445 LiteralMap* unchanged, LiteralMap* changed) {
448 const std::pair<int, int> kTopLevelMarker = std::make_pair(-1, -1);
449 std::map<std::pair<int, int>, FunctionLiteral*> position_to_new_literal;
450 for (FunctionLiteral*
literal : new_literals) {
453 std::pair<int, int>
key =
459 DCHECK_EQ(position_to_new_literal.find(
key), position_to_new_literal.end());
463 std::unordered_map<FunctionLiteral*, ChangeState> change_state;
464 for (
const auto& change_pair : changes) {
465 FunctionLiteral*
literal = change_pair.first;
466 const FunctionLiteralChange& change = change_pair.second;
467 std::pair<int, int>
key =
470 : std::make_pair(change.new_start_position,
471 change.new_end_position);
472 auto it = position_to_new_literal.find(
key);
473 if (it == position_to_new_literal.end() ||
474 HasChangedScope(
literal, it->second)) {
475 change_state[
literal] = ChangeState::DAMAGED;
476 if (!change.outer_literal)
continue;
477 if (change_state[change.outer_literal] != ChangeState::DAMAGED) {
478 change_state[change.outer_literal] = ChangeState::CHANGED;
481 mappings[
literal] = it->second;
482 if (change_state.find(
literal) == change_state.end()) {
484 change.has_changes ? ChangeState::CHANGED : ChangeState::UNCHANGED;
488 for (
const auto& mapping : mappings) {
489 if (change_state[mapping.first] == ChangeState::UNCHANGED) {
490 (*unchanged)[mapping.first] = mapping.second;
491 }
else if (change_state[mapping.first] == ChangeState::CHANGED) {
492 (*changed)[mapping.first] = mapping.second;
497class CollectFunctionLiterals final
498 :
public AstTraversalVisitor<CollectFunctionLiterals> {
500 CollectFunctionLiterals(Isolate* isolate, AstNode* root)
501 : AstTraversalVisitor<CollectFunctionLiterals>(isolate, root) {}
502 void VisitFunctionLiteral(FunctionLiteral* lit) {
503 AstTraversalVisitor::VisitFunctionLiteral(lit);
506 void Run(std::vector<FunctionLiteral*>* literals) {
516bool ParseScript(Isolate* isolate,
Handle<Script> script, ParseInfo* parse_info,
517 MaybeDirectHandle<ScopeInfo> outer_scope_info,
518 bool compile_as_well, std::vector<FunctionLiteral*>* literals,
519 debug::LiveEditResult*
result) {
521 DirectHandle<SharedFunctionInfo>
shared;
522 bool success =
false;
523 if (compile_as_well) {
533 parse_info->pending_error_handler()->PrepareErrors(
534 isolate, parse_info->ast_value_factory());
535 parse_info->pending_error_handler()->ReportErrors(isolate, script);
543 i::JSMessageObject::EnsureSourcePositionsAvailable(isolate, msg);
544 result->line_number = msg->GetLineNumber();
545 result->column_number = msg->GetColumnNumber();
549 CollectFunctionLiterals(isolate, parse_info->literal()).Run(literals);
554 explicit FunctionData(FunctionLiteral* literal)
558 MaybeHandle<SharedFunctionInfo> shared;
564 enum StackPosition { NOT_ON_STACK, ON_TOP_ONLY, ON_STACK };
568class FunctionDataMap :
public ThreadVisitor {
570 void AddInterestingLiteral(
int script_id, FunctionLiteral*
literal) {
575 int start_position = sfi->StartPosition();
576 if (!IsScript(sfi->script()) || start_position == -1) {
580 return Lookup(GetFuncId(script->id(), sfi), data);
583 bool Lookup(DirectHandle<Script> script, FunctionLiteral*
literal,
584 FunctionData** data) {
585 return Lookup(GetFuncId(script->id(),
literal), data);
588 void Fill(Isolate* isolate) {
590 HeapObjectIterator iterator(isolate->heap(),
593 obj = iterator.Next()) {
594 if (IsSharedFunctionInfo(obj)) {
596 FunctionData* data =
nullptr;
597 if (!Lookup(sfi, &data))
continue;
598 data->shared =
handle(sfi, isolate);
599 }
else if (IsJSFunction(obj)) {
602 FunctionData* data =
nullptr;
603 if (!Lookup(sfi, &data))
continue;
604 data->js_functions.emplace_back(js_function, isolate);
605 }
else if (IsJSGeneratorObject(obj)) {
607 if (
gen->is_closed())
continue;
609 FunctionData* data =
nullptr;
610 if (!Lookup(sfi, &data))
continue;
611 data->running_generators.emplace_back(
gen, isolate);
617 VisitCurrentThread(isolate);
620 isolate->thread_manager()->IterateArchivedThreads(
this);
627 using FuncId = std::pair<int, int>;
629 FuncId GetFuncId(
int script_id, FunctionLiteral*
literal) {
630 int start_position =
literal->start_position();
631 if (
literal->function_literal_id() == 0) {
637 return FuncId(script_id, start_position);
642 int start_position = sfi->StartPosition();
644 if (sfi->is_toplevel()) {
649 return FuncId(script_id, start_position);
652 bool Lookup(FuncId
id, FunctionData** data) {
653 auto it =
map_.find(
id);
654 if (it ==
map_.end())
return false;
659 void VisitThread(Isolate* isolate, ThreadLocalTop* top)
override {
660 for (JavaScriptStackFrameIterator it(isolate, top); !it.done();
662 std::vector<Handle<SharedFunctionInfo>> sfis;
663 it.frame()->GetFunctions(&sfis);
664 for (
auto& sfi : sfis) {
665 FunctionData* data =
nullptr;
666 if (!Lookup(*sfi, &data))
continue;
667 data->stack_position = FunctionData::ON_STACK;
672 void VisitCurrentThread(Isolate* isolate) {
676 for (DebugStackTraceIterator it(isolate, 0); !it.Done();
677 it.Advance(), is_top =
false) {
678 auto sfi = it.GetSharedFunctionInfo();
679 if (sfi.is_null())
continue;
680 FunctionData* data =
nullptr;
681 if (!Lookup(*sfi, &data))
continue;
686 data->stack_position = is_top && it.CanBeRestarted()
687 ? FunctionData::ON_TOP_ONLY
688 : FunctionData::ON_STACK;
692 std::map<FuncId, FunctionData>
map_;
695bool CanPatchScript(
const LiteralMap& changed, DirectHandle<Script> script,
696 DirectHandle<Script> new_script,
697 FunctionDataMap& function_data_map,
698 bool allow_top_frame_live_editing,
699 debug::LiveEditResult*
result) {
700 for (
const auto& mapping : changed) {
701 FunctionData* data =
nullptr;
702 function_data_map.Lookup(script, mapping.first, &data);
703 FunctionData* new_data =
nullptr;
704 function_data_map.Lookup(new_script, mapping.second, &new_data);
706 if (!data->shared.ToHandle(&sfi)) {
709 DCHECK(script->origin_options().IsModule() && sfi->is_toplevel());
713 }
else if (data->stack_position == FunctionData::ON_STACK) {
716 }
else if (!data->running_generators.empty()) {
719 }
else if (data->stack_position == FunctionData::ON_TOP_ONLY) {
720 if (!allow_top_frame_live_editing) {
724 result->restart_top_frame_required =
true;
730void TranslateSourcePositionTable(Isolate* isolate,
731 DirectHandle<BytecodeArray> code,
732 const std::vector<SourceChangeRange>& diffs) {
734 SourcePositionTableBuilder builder(&zone);
736 DirectHandle<TrustedByteArray> source_position_table(
737 code->SourcePositionTable(), isolate);
738 for (SourcePositionTableIterator iterator(*source_position_table);
739 !iterator.done(); iterator.Advance()) {
740 SourcePosition
position = iterator.source_position();
743 builder.AddPosition(iterator.code_offset(),
position,
744 iterator.is_statement());
747 DirectHandle<TrustedByteArray> new_source_position_table(
748 builder.ToSourcePositionTable(isolate));
749 code->set_source_position_table(*new_source_position_table,
kReleaseStore);
751 CodeLinePosInfoRecordEvent(code->GetFirstBytecodeAddress(),
752 *new_source_position_table,
756void UpdatePositions(Isolate* isolate, DirectHandle<SharedFunctionInfo> sfi,
757 FunctionLiteral* new_function,
758 const std::vector<SourceChangeRange>& diffs) {
759 sfi->UpdateFromFunctionLiteralForLiveEdit(isolate, new_function);
760 if (sfi->HasBytecodeArray()) {
761 TranslateSourcePositionTable(
762 isolate,
direct_handle(sfi->GetBytecodeArray(isolate), isolate), diffs);
768 DirectHandle<Script> script) {
772 SharedFunctionInfo::ScriptIterator it(isolate, *script);
776 if (!sfi->scope_info()->IsEmpty()) {
777 other_scope_info = sfi->scope_info();
781 if (other_scope_info.is_null())
return other_scope_info;
783 while (!other_scope_info->IsEmpty() &&
784 other_scope_info->scope_type() !=
EVAL_SCOPE &&
785 other_scope_info->HasOuterScopeInfo()) {
786 other_scope_info = other_scope_info->OuterScopeInfo();
793 if (!other_scope_info->HasOuterScopeInfo())
return ScopeInfo();
796 other_scope_info = other_scope_info->OuterScopeInfo();
798 while (!other_scope_info->IsEmpty() && !other_scope_info->HasContext() &&
799 other_scope_info->HasOuterScopeInfo()) {
800 other_scope_info = other_scope_info->OuterScopeInfo();
802 return other_scope_info;
808MaybeDirectHandle<ScopeInfo> DetermineOuterScopeInfo(
809 Isolate* isolate, DirectHandle<Script> script) {
814 while (!scope_info->IsEmpty()) {
815 if (scope_info->HasContext()) {
818 FindOuterScopeInfoFromScriptSfi(isolate, script);
820 scope_info == other_scope_info);
823 }
else if (!scope_info->HasOuterScopeInfo()) {
826 scope_info = scope_info->OuterScopeInfo();
836 bool allow_top_frame_live_editing,
838 std::vector<SourceChangeRange> diffs;
852 flags.set_is_eager(
true);
853 flags.set_is_reparse(
true);
854 ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
856 DetermineOuterScopeInfo(isolate, script);
857 std::vector<FunctionLiteral*> literals;
858 if (!ParseScript(isolate, script, &parse_info, outer_scope_info,
false,
863 isolate->factory()->CloneScript(script, new_source);
867 new_flags.set_is_eager(
true);
868 ParseInfo new_parse_info(isolate, new_flags, &new_compile_state,
870 std::vector<FunctionLiteral*> new_literals;
871 if (!ParseScript(isolate, new_script, &new_parse_info, outer_scope_info,
true,
876 FunctionLiteralChanges literal_changes;
877 CalculateFunctionLiteralChanges(literals, diffs, &literal_changes);
880 LiteralMap unchanged;
881 MapLiterals(literal_changes, new_literals, &unchanged, &changed);
883 FunctionDataMap function_data_map;
884 for (
const auto& mapping : changed) {
885 function_data_map.AddInterestingLiteral(script->id(), mapping.first);
886 function_data_map.AddInterestingLiteral(new_script->id(), mapping.second);
888 for (
const auto& mapping : unchanged) {
889 function_data_map.AddInterestingLiteral(script->id(), mapping.first);
891 function_data_map.Fill(isolate);
893 if (!CanPatchScript(changed, script, new_script, function_data_map,
894 allow_top_frame_live_editing,
result)) {
908 isolate->set_disable_bytecode_flushing(
true);
910 std::map<int, int> start_position_to_unchanged_id;
911 for (
const auto& mapping : unchanged) {
912 FunctionData* data =
nullptr;
913 if (!function_data_map.Lookup(script, mapping.first, &data))
continue;
915 if (!data->shared.ToHandle(&sfi))
continue;
918 isolate->compilation_cache()->Remove(sfi);
919 isolate->debug()->DeoptimizeFunction(sfi);
922 isolate->debug()->RemoveBreakInfoAndMaybeFree(debug_info);
925 UpdatePositions(isolate, sfi, mapping.second, diffs);
928 sfi->set_function_literal_id(mapping.second->function_literal_id());
929 new_script->infos()->set(mapping.second->function_literal_id(),
932 mapping.second->function_literal_id());
936 start_position_to_unchanged_id[mapping.second->start_position()] =
937 mapping.second->function_literal_id();
939 if (sfi->HasUncompiledDataWithPreparseData()) {
940 sfi->ClearPreparseData(isolate);
943 for (
auto& js_function : data->js_functions) {
944 js_function->set_raw_feedback_cell(
945 *isolate->factory()->many_closures_cell());
946 if (!js_function->is_compiled(isolate))
continue;
948 js_function->shared()->is_compiled_scope(isolate));
953 if (!sfi->HasBytecodeArray())
continue;
955 sfi->GetBytecodeArray(isolate)->constant_pool();
956 for (
int i = 0;
i < constants->length(); ++
i) {
957 if (!IsSharedFunctionInfo(constants->get(
i)))
continue;
963 auto change_it = changed.find(data->literal);
964 if (change_it == changed.end())
continue;
965 if (!function_data_map.Lookup(new_script, change_it->second, &data)) {
969 if (!data->shared.ToHandle(&new_sfi))
continue;
970 constants->set(
i, *new_sfi);
973 isolate->LocalsBlockListCacheRehash();
974 for (
const auto& mapping : changed) {
975 FunctionData* data =
nullptr;
976 if (!function_data_map.Lookup(new_script, mapping.second, &data))
continue;
981 if (!data->shared.ToHandle(&new_sfi))
continue;
982 DCHECK_EQ(new_sfi->script(), *new_script);
984 if (!function_data_map.Lookup(script, mapping.first, &data))
continue;
986 if (!data->shared.ToHandle(&sfi))
continue;
988 isolate->debug()->DeoptimizeFunction(sfi);
989 isolate->compilation_cache()->Remove(sfi);
990 for (
auto& js_function : data->js_functions) {
991 js_function->set_raw_feedback_cell(
992 *isolate->factory()->many_closures_cell());
993#ifdef V8_ENABLE_LEAPTIERING
994 auto code =
handle(new_sfi->GetCode(isolate), isolate);
995 JSFunction::AllocateDispatchHandle(
996 js_function, isolate,
997 new_sfi->internal_formal_parameter_count_with_receiver(), code);
999 js_function->set_shared(*new_sfi);
1001 if (!js_function->is_compiled(isolate))
continue;
1003 js_function->shared()->is_compiled_scope(isolate));
1005 &is_compiled_scope);
1011 if (!sfi->HasBytecodeArray())
continue;
1013 sfi->GetBytecodeArray(isolate)->constant_pool();
1014 for (
int i = 0;
i < constants->length(); ++
i) {
1015 if (!IsSharedFunctionInfo(constants->get(
i)))
continue;
1021 start_position_to_unchanged_id.find(inner_sfi->StartPosition());
1022 if (unchanged_it == start_position_to_unchanged_id.end())
continue;
1028 new_script->infos()->get(unchanged_it->second).GetHeapObject());
1029 if (old_unchanged_inner_sfi == inner_sfi)
continue;
1030 DCHECK_NE(old_unchanged_inner_sfi, inner_sfi);
1033 DCHECK_EQ(old_unchanged_inner_sfi->script(), *new_script);
1034 constants->set(
i, old_unchanged_inner_sfi);
1045 std::set<int> start_positions;
1047 sfi = script_it.
Next()) {
1052 if (sfi->is_toplevel()) {
1053 DCHECK_EQ(start_positions.find(sfi->StartPosition()),
1054 start_positions.end());
1055 start_positions.insert(sfi->StartPosition());
1058 if (!sfi->HasBytecodeArray())
continue;
1063 sfi->GetBytecodeArray(isolate)->constant_pool();
1064 for (
int i = 0;
i < constants->length(); ++
i) {
1065 if (!IsSharedFunctionInfo(constants->get(
i)))
continue;
1068 DCHECK_EQ(inner_sfi->script(), *new_script);
1069 DCHECK_EQ(inner_sfi, new_script->infos()
1070 ->get(inner_sfi->function_literal_id())
1077 int script_id = script->id();
1078 script->set_id(new_script->id());
1079 new_script->set_id(script_id);
1086 std::vector<SourceChangeRange>* diffs) {
1090 LineEndsWrapper line_ends1(isolate, s1);
1091 LineEndsWrapper line_ends2(isolate, s2);
1093 LineArrayCompareInput input(s1, s2, line_ends1, line_ends2);
1094 TokenizingLineArrayCompareOutput output(isolate, line_ends1, line_ends2, s1,
1097 NarrowDownInput(&input, &output);
1104 auto it = std::lower_bound(diffs.begin(), diffs.end(),
position,
1106 return change.end_position < position;
1108 if (it != diffs.end() &&
position == it->end_position) {
1109 return it->new_end_position;
1111 if (it == diffs.begin())
return position;
1114 return position + (it->new_end_position - it->end_position);
Local< v8::Message > Message() const
static v8::internal::DirectHandle< To > OpenDirectHandle(v8::Local< From > handle)
static void CalculateDifference(Input *input, Output *result_writer)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< SharedFunctionInfo > CompileForLiveEdit(ParseInfo *parse_info, Handle< Script > script, MaybeDirectHandle< ScopeInfo > outer_scope_info, Isolate *isolate)
int function_literal_id() const
int start_position() const
static V8_EXPORT_PRIVATE void EnsureFeedbackVector(Isolate *isolate, DirectHandle< JSFunction > function, IsCompiledScope *compiled_scope)
FeedbackVector eventually. Generally this shouldn't be used to get the.
static void PatchScript(Isolate *isolate, Handle< Script > script, Handle< String > source, bool preview, bool allow_top_frame_live_editing, debug::LiveEditResult *result)
static int TranslatePosition(const std::vector< SourceChangeRange > &changed, int position)
static void CompareStrings(Isolate *isolate, Handle< String > a, Handle< String > b, std::vector< SourceChangeRange > *diffs)
V8_EXPORT_PRIVATE Tagged< SharedFunctionInfo > Next()
static void EnsureSourcePositionsAvailable(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared_info)
static constexpr int ToInt(const Tagged< Object > object)
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
static Handle< FixedArray > CalculateLineEnds(IsolateT *isolate, DirectHandle< String > string, bool include_ending_line)
V8_INLINE constexpr bool is_null() const
static UnoptimizedCompileFlags ForScriptCompile(Isolate *isolate, Tagged< Script > script)
T * insert(const T *pos, It first, It last)
SharedFunctionInfoRef shared
ZoneVector< RpoNumber > & result
Comparator::Output * output_
std::vector< Handle< JSGeneratorObject > > running_generators
FunctionLiteral * literal
std::vector< FunctionLiteral * > * literals_
LineEndsWrapper line_ends2_
static const int CHUNK_LEN_LIMIT
std::vector< Handle< JSFunction > > js_functions
StackPosition stack_position
LineEndsWrapper line_ends1_
FunctionLiteral * outer_literal
Handle< FixedArray > ends_array_
#define LOG_CODE_EVENT(isolate, Call)
SnapshotTable< OpIndex, VariableData >::Key Variable
bool ParseProgram(ParseInfo *info, DirectHandle< Script > script, MaybeDirectHandle< ScopeInfo > maybe_outer_scope_info, Isolate *isolate, ReportStatisticsMode mode)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
constexpr NullMaybeHandleType kNullMaybeHandle
constexpr int kNoSourcePosition
Tagged(T object) -> Tagged< T >
kInterpreterTrampolineOffset Tagged< HeapObject >
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
bool IsModule(FunctionKind kind)
Tagged< MaybeWeak< T > > MakeWeak(Tagged< T > value)
constexpr int kFunctionLiteralIdTopLevel
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
static constexpr ReleaseStoreTag kReleaseStore
v8::Local< T > ToApiHandle(v8::internal::DirectHandle< v8::internal::Object > obj)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
@ BLOCKED_BY_RUNNING_GENERATOR
@ BLOCKED_BY_TOP_LEVEL_ES_MODULE_CHANGE
@ BLOCKED_BY_ACTIVE_FUNCTION