From 422d56e36bc4396317f44d1ea0652268c8f7e6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Thu, 27 Aug 2015 09:10:22 +0200 Subject: [PATCH] deps: update V8 to 4.4.63.30 PR-URL: https://github.com/nodejs/node/pull/2482 Reviewed-By: Ben Noordhuis --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/heap/gc-idle-time-handler.cc | 20 +++++++++++-- deps/v8/src/heap/gc-idle-time-handler.h | 6 +++- deps/v8/src/heap/heap.cc | 6 ++++ deps/v8/src/hydrogen.cc | 21 +++++++------- deps/v8/src/objects.cc | 28 +++++++++++++------ deps/v8/test/cctest/test-api.cc | 3 ++ .../mjsunit/regress/regress-crbug-513602.js | 26 +++++++++++++++++ 8 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-513602.js diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index c52267e024..180969f116 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 4 #define V8_MINOR_VERSION 4 #define V8_BUILD_NUMBER 63 -#define V8_PATCH_LEVEL 26 +#define V8_PATCH_LEVEL 30 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/heap/gc-idle-time-handler.cc b/deps/v8/src/heap/gc-idle-time-handler.cc index e20a1e45cb..5baf024efe 100644 --- a/deps/v8/src/heap/gc-idle-time-handler.cc +++ b/deps/v8/src/heap/gc-idle-time-handler.cc @@ -113,6 +113,10 @@ bool GCIdleTimeHandler::ShouldDoScavenge( size_t idle_time_in_ms, size_t new_space_size, size_t used_new_space_size, size_t scavenge_speed_in_bytes_per_ms, size_t new_space_allocation_throughput_in_bytes_per_ms) { + if (idle_time_in_ms >= kMinBackgroundIdleTime) { + // It is better to do full GC for the background tab. + return false; + } size_t new_space_allocation_limit = kMaxScheduledIdleTime * scavenge_speed_in_bytes_per_ms; @@ -185,7 +189,10 @@ bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure( } -GCIdleTimeAction GCIdleTimeHandler::NothingOrDone() { +GCIdleTimeAction GCIdleTimeHandler::NothingOrDone(double idle_time_in_ms) { + if (idle_time_in_ms >= kMinBackgroundIdleTime) { + return GCIdleTimeAction::Nothing(); + } if (idle_times_which_made_no_progress_per_mode_ >= kMaxNoProgressIdleTimesPerMode) { return GCIdleTimeAction::Done(); @@ -235,6 +242,13 @@ GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms, HeapState heap_state) { Mode next_mode = NextMode(heap_state); + // Immediately go from reduce latency to reduce memory mode in + // background tab. + if (next_mode == kReduceLatency && + idle_time_in_ms >= kMinBackgroundIdleTime) { + next_mode = kReduceMemory; + } + if (next_mode != mode_) { mode_ = next_mode; ResetCounters(); @@ -298,13 +312,13 @@ GCIdleTimeAction GCIdleTimeHandler::Action(double idle_time_in_ms, if (heap_state.sweeping_completed) { return GCIdleTimeAction::FinalizeSweeping(); } else { - return NothingOrDone(); + return NothingOrDone(idle_time_in_ms); } } if (heap_state.incremental_marking_stopped && !heap_state.can_start_incremental_marking && !reduce_memory) { - return NothingOrDone(); + return NothingOrDone(idle_time_in_ms); } size_t step_size = EstimateMarkingStepSize( diff --git a/deps/v8/src/heap/gc-idle-time-handler.h b/deps/v8/src/heap/gc-idle-time-handler.h index 1ffa3efdfc..1ab506d817 100644 --- a/deps/v8/src/heap/gc-idle-time-handler.h +++ b/deps/v8/src/heap/gc-idle-time-handler.h @@ -231,6 +231,10 @@ class GCIdleTimeHandler { size_t scavenger_speed_in_bytes_per_ms, size_t new_space_allocation_throughput_in_bytes_per_ms); + bool ShouldGrowHeapSlowly() { + return mode() == kDone; + } + enum Mode { kReduceLatency, kReduceMemory, kDone }; Mode mode() { return mode_; } @@ -244,7 +248,7 @@ class GCIdleTimeHandler { Mode NextMode(const HeapState& heap_state); GCIdleTimeAction Action(double idle_time_in_ms, const HeapState& heap_state, bool reduce_memory); - GCIdleTimeAction NothingOrDone(); + GCIdleTimeAction NothingOrDone(double idle_time_in_ms); int idle_mark_compacts_; int mark_compacts_; diff --git a/deps/v8/src/heap/heap.cc b/deps/v8/src/heap/heap.cc index 6bfa4ae466..f971359198 100644 --- a/deps/v8/src/heap/heap.cc +++ b/deps/v8/src/heap/heap.cc @@ -5407,6 +5407,12 @@ void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, factor = min_factor; } + const double kConservativeHeapGrowingFactor = 1.3; + if (gc_idle_time_handler_.ShouldGrowHeapSlowly()) { + factor = Min(factor, kConservativeHeapGrowingFactor); + } + + idle_factor = Min(factor, idle_max_factor); old_generation_allocation_limit_ = diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 6a86c736ee..455af79bb6 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -11300,16 +11300,20 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( HValue* object_size_constant = Add(initial_map->instance_size()); PretenureFlag pretenure_flag = NOT_TENURED; - Handle current_site(*site_context->current(), isolate()); + Handle top_site(*site_context->top(), isolate()); if (FLAG_allocation_site_pretenuring) { - pretenure_flag = current_site->GetPretenureMode(); - top_info()->dependencies()->AssumeTenuringDecision(current_site); + pretenure_flag = top_site->GetPretenureMode(); } + Handle current_site(*site_context->current(), isolate()); + if (*top_site == *current_site) { + // We install a dependency for pretenuring only on the outermost literal. + top_info()->dependencies()->AssumeTenuringDecision(top_site); + } top_info()->dependencies()->AssumeTransitionStable(current_site); HInstruction* object = Add( - object_size_constant, type, pretenure_flag, instance_type, current_site); + object_size_constant, type, pretenure_flag, instance_type, top_site); // If allocation folding reaches Page::kMaxRegularHeapObjectSize the // elements array may not get folded into the object. Hence, we set the @@ -11349,9 +11353,8 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( HValue* object_elements_size = Add(elements_size); InstanceType instance_type = boilerplate_object->HasFastDoubleElements() ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE; - object_elements = - Add(object_elements_size, HType::HeapObject(), - pretenure_flag, instance_type, current_site); + object_elements = Add(object_elements_size, HType::HeapObject(), + pretenure_flag, instance_type, top_site); BuildEmitElements(boilerplate_object, elements, object_elements, site_context); Add(object, HObjectAccess::ForElementsPointer(), @@ -11452,10 +11455,6 @@ void HOptimizedGraphBuilder::BuildEmitInObjectProperties( if (representation.IsDouble()) { // Allocate a HeapNumber box and store the value into it. HValue* heap_number_constant = Add(HeapNumber::kSize); - // This heap number alloc does not have a corresponding - // AllocationSite. That is okay because - // 1) it's a child object of another object with a valid allocation site - // 2) we can just use the mode of the parent object for pretenuring HInstruction* double_box = Add(heap_number_constant, HType::HeapObject(), pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE); diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 82a27f4d21..f0dcaab937 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -4765,20 +4765,32 @@ void JSObject::MigrateSlowToFast(Handle object, } } - int inobject_props = object->map()->inobject_properties(); + Handle old_map(object->map(), isolate); + + int inobject_props = old_map->inobject_properties(); // Allocate new map. - Handle new_map = Map::CopyDropDescriptors(handle(object->map())); + Handle new_map = Map::CopyDropDescriptors(old_map); new_map->set_dictionary_map(false); - if (object->map()->is_prototype_map()) { + if (old_map->is_prototype_map() && FLAG_track_prototype_users) { DCHECK(new_map->is_prototype_map()); - new_map->set_prototype_info(object->map()->prototype_info()); - object->map()->set_prototype_info(Smi::FromInt(0)); + + Object* maybe_old_prototype = old_map->prototype(); + if (maybe_old_prototype->IsJSObject()) { + Handle old_prototype(JSObject::cast(maybe_old_prototype)); + bool was_registered = + JSObject::UnregisterPrototypeUser(old_prototype, old_map); + if (was_registered) { + JSObject::LazyRegisterPrototypeUser(new_map, isolate); + } + } + new_map->set_prototype_info(old_map->prototype_info()); + old_map->set_prototype_info(Smi::FromInt(0)); if (FLAG_trace_prototype_users) { PrintF("Moving prototype_info %p from map %p to map %p.\n", reinterpret_cast(new_map->prototype_info()), - reinterpret_cast(object->map()), + reinterpret_cast(*old_map), reinterpret_cast(*new_map)); } } @@ -4786,8 +4798,8 @@ void JSObject::MigrateSlowToFast(Handle object, #if TRACE_MAPS if (FLAG_trace_maps) { PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n", - reinterpret_cast(object->map()), - reinterpret_cast(*new_map), reason); + reinterpret_cast(*old_map), reinterpret_cast(*new_map), + reason); } #endif diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 35e27c3118..145d9bc64d 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -15010,6 +15010,9 @@ TEST(TestIdleNotification) { (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() / static_cast(v8::base::Time::kMicrosecondsPerSecond)) + IdlePauseInSeconds); + if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) { + CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted(); + } } intptr_t final_size = CcTest::heap()->SizeOfObjects(); CHECK(finished); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-513602.js b/deps/v8/test/mjsunit/regress/regress-crbug-513602.js new file mode 100644 index 0000000000..ae0441cbc7 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-513602.js @@ -0,0 +1,26 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function Parent() {} + +function Child() {} +Child.prototype = new Parent(); +var child = new Child(); + +function crash() { + return child.__proto__; +} + +crash(); +crash(); + +// Trigger a fast->slow->fast dance of Parent.prototype's map... +Parent.prototype.__defineSetter__("foo", function() { print("A"); }); +Parent.prototype.__defineSetter__("foo", function() { print("B"); }); +// ...and collect more type feedback. +crash(); + +// Now modify the prototype chain. The right cell fails to get invalidated. +delete Object.prototype.__proto__; +crash();