| Index: src/debug/liveedit.cc
|
| diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc
|
| index fea5d679a91cde427007519c11811ec2874db723..3ced3cc427405584f1dfed241f62d992a302cf87 100644
|
| --- a/src/debug/liveedit.cc
|
| +++ b/src/debug/liveedit.cc
|
| @@ -823,33 +823,35 @@ class LiteralFixer {
|
| public:
|
| static void PatchLiterals(FunctionInfoWrapper* compile_info_wrapper,
|
| Handle<SharedFunctionInfo> shared_info,
|
| - Isolate* isolate) {
|
| + bool feedback_metadata_changed, Isolate* isolate) {
|
| int new_literal_count = compile_info_wrapper->GetLiteralCount();
|
| + int old_literal_count = shared_info->num_literals();
|
|
|
| - // Recreate the literal array and type feedback vector.
|
| - // Since the feedback vector roots literal arrays for nested functions,
|
| - // we can't simply leave it in place because those nested literal
|
| - // array and feedback vectors may have changed structure.
|
| - Handle<FixedArray> function_instances =
|
| - CollectJSFunctions(shared_info, isolate);
|
| - Handle<TypeFeedbackMetadata> feedback_metadata(
|
| - shared_info->feedback_metadata());
|
| -
|
| - for (int i = 0; i < function_instances->length(); i++) {
|
| - Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i)));
|
| - Handle<TypeFeedbackVector> vector =
|
| - TypeFeedbackVector::New(isolate, feedback_metadata);
|
| - Handle<LiteralsArray> new_literals =
|
| - LiteralsArray::New(isolate, vector, new_literal_count);
|
| - Handle<LiteralsArray> old_literals(fun->literals(), isolate);
|
| - fun->set_literals(*new_literals);
|
| -
|
| - // The literals are rooted in a containing feedback vector.
|
| - // Replace them there, so new closures have the correct literals.
|
| - ReplaceRoots(old_literals, new_literals);
|
| - }
|
| + if (old_literal_count == new_literal_count && !feedback_metadata_changed) {
|
| + // If literal count didn't change, simply go over all functions
|
| + // and clear literal arrays.
|
| + ClearValuesVisitor visitor;
|
| + IterateJSFunctions(shared_info, &visitor);
|
| + } else {
|
| + // When literal count changes, we have to create new array instances.
|
| + // Since we cannot create instances when iterating heap, we should first
|
| + // collect all functions and fix their literal arrays.
|
| + Handle<FixedArray> function_instances =
|
| + CollectJSFunctions(shared_info, isolate);
|
| + Handle<TypeFeedbackMetadata> feedback_metadata(
|
| + shared_info->feedback_metadata());
|
| +
|
| + for (int i = 0; i < function_instances->length(); i++) {
|
| + Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i)));
|
| + Handle<TypeFeedbackVector> vector =
|
| + TypeFeedbackVector::New(isolate, feedback_metadata);
|
| + Handle<LiteralsArray> new_literals =
|
| + LiteralsArray::New(isolate, vector, new_literal_count);
|
| + fun->set_literals(*new_literals);
|
| + }
|
|
|
| - shared_info->set_num_literals(new_literal_count);
|
| + shared_info->set_num_literals(new_literal_count);
|
| + }
|
| }
|
|
|
| private:
|
| @@ -870,56 +872,6 @@ class LiteralFixer {
|
| }
|
| }
|
|
|
| - template <typename Visitor>
|
| - static void IterateAllJSFunctions(Heap* heap, Visitor* visitor) {
|
| - HeapIterator iterator(heap);
|
| - for (HeapObject* obj = iterator.next(); obj != NULL;
|
| - obj = iterator.next()) {
|
| - if (obj->IsJSFunction()) {
|
| - JSFunction* function = JSFunction::cast(obj);
|
| - visitor->visit(function);
|
| - }
|
| - }
|
| - }
|
| -
|
| - class ReplaceRootsVisitor {
|
| - public:
|
| - ReplaceRootsVisitor(Handle<LiteralsArray> old_literals,
|
| - Handle<LiteralsArray> new_literals)
|
| - : old_literals_(old_literals), new_literals_(new_literals) {}
|
| -
|
| - void visit(JSFunction* fun) {
|
| - if (!fun->shared()->is_compiled()) return;
|
| -
|
| - // Look in the type feedback vector for a copy of literals.
|
| - TypeFeedbackVector* vector = fun->feedback_vector();
|
| - // Note: it's important to get the feedback metadata from the
|
| - // type feedback vector, because there may be a new metadata
|
| - // object in the SharedFunctionInfo (with a different slot
|
| - // configuration).
|
| - TypeFeedbackMetadataIterator iter(vector->metadata());
|
| - while (iter.HasNext()) {
|
| - FeedbackVectorSlot slot = iter.Next();
|
| - FeedbackVectorSlotKind kind = iter.kind();
|
| - if (kind == FeedbackVectorSlotKind::CREATE_CLOSURE) {
|
| - Object* obj = vector->Get(slot);
|
| - if (obj == *old_literals_) {
|
| - vector->Set(slot, *new_literals_);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - Handle<LiteralsArray> old_literals_;
|
| - Handle<LiteralsArray> new_literals_;
|
| - };
|
| -
|
| - static void ReplaceRoots(Handle<LiteralsArray> old_literals,
|
| - Handle<LiteralsArray> new_literals) {
|
| - ReplaceRootsVisitor replace_visitor(old_literals, new_literals);
|
| - IterateAllJSFunctions(old_literals->GetHeap(), &replace_visitor);
|
| - }
|
| -
|
| // Finds all instances of JSFunction that refers to the provided shared_info
|
| // and returns array with them.
|
| static Handle<FixedArray> CollectJSFunctions(
|
| @@ -1020,6 +972,7 @@ void LiveEdit::ReplaceFunctionCode(
|
| Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
|
| Handle<SharedFunctionInfo> new_shared_info =
|
| compile_info_wrapper.GetSharedFunctionInfo();
|
| + bool feedback_metadata_changed = false;
|
|
|
| if (shared_info->is_compiled()) {
|
| // Take whatever code we can get from the new shared function info. We
|
| @@ -1066,6 +1019,8 @@ void LiveEdit::ReplaceFunctionCode(
|
| // Update the type feedback vector, if needed.
|
| Handle<TypeFeedbackMetadata> new_feedback_metadata(
|
| new_shared_info->feedback_metadata());
|
| + feedback_metadata_changed =
|
| + new_feedback_metadata->DiffersFrom(shared_info->feedback_metadata());
|
| shared_info->set_feedback_metadata(*new_feedback_metadata);
|
| }
|
|
|
| @@ -1074,7 +1029,8 @@ void LiveEdit::ReplaceFunctionCode(
|
| shared_info->set_start_position(start_position);
|
| shared_info->set_end_position(end_position);
|
|
|
| - LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info, isolate);
|
| + LiteralFixer::PatchLiterals(&compile_info_wrapper, shared_info,
|
| + feedback_metadata_changed, isolate);
|
|
|
| DeoptimizeDependentFunctions(*shared_info);
|
| isolate->compilation_cache()->Remove(shared_info);
|
|
|