From 8b71a9d2cdcaf580a3b082dda336f6d137a84cd6 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 2 Jul 2015 00:50:48 +0200 Subject: [PATCH] deps: upgrade v8 to 4.4.63.12 PR-URL: https://github.com/nodejs/io.js/pull/2092 Reviewed-By: Trevor Norris --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/hydrogen.cc | 39 +++++--- deps/v8/src/hydrogen.h | 3 + deps/v8/src/objects-printer.cc | 1 + deps/v8/src/objects.cc | 12 +-- deps/v8/src/runtime/runtime-test.cc | 2 +- deps/v8/src/runtime/runtime-typedarray.cc | 10 +- deps/v8/test/cctest/test-migrations.cc | 112 ++++++++++++++++++++-- src/env-inl.h | 9 -- src/node_buffer.cc | 8 +- 10 files changed, 146 insertions(+), 52 deletions(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 35bfeb71087663..2f2ea5533387d0 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 9 +#define V8_PATCH_LEVEL 12 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index f226730a2b7ecf..a1b06482078471 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -9662,15 +9662,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { HObjectAccess::ForMapAndOffset(initial_map, JSObject::kElementsOffset), empty_fixed_array); - if (initial_map->inobject_properties() != 0) { - HConstant* undefined = graph()->GetConstantUndefined(); - for (int i = 0; i < initial_map->inobject_properties(); i++) { - int property_offset = initial_map->GetInObjectPropertyOffset(i); - Add(receiver, - HObjectAccess::ForMapAndOffset(initial_map, property_offset), - undefined); - } - } + BuildInitializeInobjectProperties(receiver, initial_map); } // Replace the constructor function with a newly allocated receiver using @@ -9713,6 +9705,20 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { } +void HOptimizedGraphBuilder::BuildInitializeInobjectProperties( + HValue* receiver, Handle initial_map) { + if (initial_map->inobject_properties() != 0) { + HConstant* undefined = graph()->GetConstantUndefined(); + for (int i = 0; i < initial_map->inobject_properties(); i++) { + int property_offset = initial_map->GetInObjectPropertyOffset(i); + Add(receiver, HObjectAccess::ForMapAndOffset( + initial_map, property_offset), + undefined); + } + } +} + + HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) { HAllocate* result = BuildAllocate(Add(JSArrayBuffer::kSizeWithInternalFields), @@ -11282,13 +11288,13 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( Handle boilerplate_object, AllocationSiteUsageContext* site_context) { NoObservableSideEffectsScope no_effects(this); - InstanceType instance_type = boilerplate_object->map()->instance_type(); + Handle initial_map(boilerplate_object->map()); + InstanceType instance_type = initial_map->instance_type(); DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); HType type = instance_type == JS_ARRAY_TYPE ? HType::JSArray() : HType::JSObject(); - HValue* object_size_constant = Add( - boilerplate_object->map()->instance_size()); + HValue* object_size_constant = Add(initial_map->instance_size()); PretenureFlag pretenure_flag = NOT_TENURED; Handle current_site(*site_context->current(), isolate()); @@ -11313,6 +11319,11 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( BuildEmitObjectHeader(boilerplate_object, object); + // Similarly to the elements pointer, there is no guarantee that all + // property allocations can get folded, so pre-initialize all in-object + // properties to a safe value. + BuildInitializeInobjectProperties(object, initial_map); + Handle elements(boilerplate_object->elements()); int elements_size = (elements->length() > 0 && elements->map() != isolate()->heap()->fixed_cow_array_map()) ? @@ -11351,8 +11362,8 @@ HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( } // Copy in-object properties. - if (boilerplate_object->map()->NumberOfFields() != 0 || - boilerplate_object->map()->unused_property_fields() > 0) { + if (initial_map->NumberOfFields() != 0 || + initial_map->unused_property_fields() > 0) { BuildEmitInObjectProperties(boilerplate_object, object, site_context, pretenure_flag); } diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h index 0feef24e6b91f8..eabcff4b7d0d65 100644 --- a/deps/v8/src/hydrogen.h +++ b/deps/v8/src/hydrogen.h @@ -2506,6 +2506,9 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { void BuildInlinedCallArray(Expression* expression, int argument_count, Handle site); + void BuildInitializeInobjectProperties(HValue* receiver, + Handle initial_map); + class PropertyAccessInfo { public: PropertyAccessInfo(HOptimizedGraphBuilder* builder, diff --git a/deps/v8/src/objects-printer.cc b/deps/v8/src/objects-printer.cc index c9fdcd94ddf7f1..aa4f4ded195842 100644 --- a/deps/v8/src/objects-printer.cc +++ b/deps/v8/src/objects-printer.cc @@ -415,6 +415,7 @@ void Map::MapPrint(std::ostream& os) { // NOLINT << pre_allocated_property_fields() << "\n"; os << " - unused property fields: " << unused_property_fields() << "\n"; if (is_deprecated()) os << " - deprecated_map\n"; + if (is_stable()) os << " - stable_map\n"; if (is_dictionary_map()) os << " - dictionary_map\n"; if (is_prototype_map()) { os << " - prototype_map\n"; diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 8c14d057d2e395..67a7b2bc7a18bd 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -2706,6 +2706,9 @@ Handle Map::ReconfigureProperty(Handle old_map, int modify_index, target_descriptors->GetFieldType(modify_index))); } #endif + if (*target_map != *old_map) { + old_map->NotifyLeafMapLayoutChange(); + } return target_map; } @@ -2959,13 +2962,6 @@ Handle Map::ReconfigureProperty(Handle old_map, int modify_index, split_kind, old_descriptors->GetKey(split_nof), split_attributes, *new_descriptors, *new_layout_descriptor); - if (from_kind != to_kind) { - // There was an elements kind change in the middle of transition tree and - // we reconstructed the tree so that all elements kind transitions are - // done at the beginning, therefore the |old_map| is no longer stable. - old_map->NotifyLeafMapLayoutChange(); - } - // If |transition_target_deprecated| is true then the transition array // already contains entry for given descriptor. This means that the transition // could be inserted regardless of whether transitions array is full or not. @@ -2976,6 +2972,8 @@ Handle Map::ReconfigureProperty(Handle old_map, int modify_index, "GenAll_CantHaveMoreTransitions"); } + old_map->NotifyLeafMapLayoutChange(); + if (FLAG_trace_generalization && modify_index >= 0) { PropertyDetails old_details = old_descriptors->GetDetails(modify_index); PropertyDetails new_details = new_descriptors->GetDetails(modify_index); diff --git a/deps/v8/src/runtime/runtime-test.cc b/deps/v8/src/runtime/runtime-test.cc index ddf2e9d6b46a6c..f590f81a2d87b2 100644 --- a/deps/v8/src/runtime/runtime-test.cc +++ b/deps/v8/src/runtime/runtime-test.cc @@ -179,7 +179,7 @@ RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) { base::OS::Sleep(base::TimeDelta::FromMilliseconds(50)); } } - if (FLAG_always_opt) { + if (FLAG_always_opt || FLAG_prepare_always_opt) { // With --always-opt, optimization status expectations might not // match up, so just return a sentinel. return Smi::FromInt(3); // 3 == "always". diff --git a/deps/v8/src/runtime/runtime-typedarray.cc b/deps/v8/src/runtime/runtime-typedarray.cc index 10aba0cc424686..fed6795509c834 100644 --- a/deps/v8/src/runtime/runtime-typedarray.cc +++ b/deps/v8/src/runtime/runtime-typedarray.cc @@ -27,15 +27,15 @@ void Runtime::SetupArrayBuffer(Isolate* isolate, array_buffer->set_is_external(is_external); array_buffer->set_is_neuterable(true); - Handle byte_length = - isolate->factory()->NewNumberFromSize(allocated_length); - CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber()); - array_buffer->set_byte_length(*byte_length); - if (data && !is_external) { isolate->heap()->RegisterNewArrayBuffer( isolate->heap()->InNewSpace(*array_buffer), data, allocated_length); } + + Handle byte_length = + isolate->factory()->NewNumberFromSize(allocated_length); + CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber()); + array_buffer->set_byte_length(*byte_length); } diff --git a/deps/v8/test/cctest/test-migrations.cc b/deps/v8/test/cctest/test-migrations.cc index 340e81d27ea521..14bdcea3c680db 100644 --- a/deps/v8/test/cctest/test-migrations.cc +++ b/deps/v8/test/cctest/test-migrations.cc @@ -437,9 +437,9 @@ TEST(ReconfigureAccessorToNonExistingDataField) { Handle new_map = Map::ReconfigureProperty( map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD); - // |map| did not change. + // |map| did not change except marked unstable. CHECK(!map->is_deprecated()); - CHECK(map->is_stable()); + CHECK(!map->is_stable()); CHECK(expectations.Check(*map)); expectations.SetDataField(0, NONE, Representation::None(), none_type); @@ -601,12 +601,14 @@ static void TestGeneralizeRepresentation( CHECK(expectations.Check(*new_map)); if (is_detached_map) { + CHECK(!map->is_stable()); CHECK(map->is_deprecated()); CHECK_NE(*map, *new_map); CHECK_EQ(expected_field_type_dependency && !field_owner->is_deprecated(), info.dependencies()->HasAborted()); } else if (expected_deprecation) { + CHECK(!map->is_stable()); CHECK(map->is_deprecated()); CHECK(field_owner->is_deprecated()); CHECK_NE(*map, *new_map); @@ -614,6 +616,7 @@ static void TestGeneralizeRepresentation( } else { CHECK(!field_owner->is_deprecated()); + CHECK(map->is_stable()); // Map did not change, must be left stable. CHECK_EQ(*map, *new_map); CHECK_EQ(expected_field_type_dependency, info.dependencies()->HasAborted()); @@ -654,6 +657,12 @@ static void TestGeneralizeRepresentation( to_type, expected_representation, expected_type, expected_deprecation, expected_field_type_dependency); } + + // Check that reconfiguration to the very same field works correctly. + Representation representation = from_representation; + Handle type = from_type; + TestGeneralizeRepresentation(-1, 2, representation, type, representation, + type, representation, type, false, false); } } @@ -877,6 +886,7 @@ TEST(GeneralizeRepresentationWithAccessorProperties) { expectations.SetDataField(i, Representation::Double(), any_type); + CHECK(!map->is_stable()); CHECK(map->is_deprecated()); CHECK_NE(*map, *new_map); CHECK(i == 0 || maps[i - 1]->is_deprecated()); @@ -962,7 +972,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation( Handle new_map = Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE); - // |map2| should be left unchanged. + // |map2| should be left unchanged but marked unstable. + CHECK(!map2->is_stable()); CHECK(!map2->is_deprecated()); CHECK_NE(*map2, *new_map); CHECK(expectations2.Check(*map2)); @@ -1047,7 +1058,8 @@ static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial( Handle new_map = Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE); - // |map2| should be left unchanged. + // |map2| should be left unchanged but marked unstable. + CHECK(!map2->is_stable()); CHECK(!map2->is_deprecated()); CHECK_NE(*map2, *new_map); CHECK(expectations2.Check(*map2)); @@ -1183,6 +1195,8 @@ struct CheckDeprecated { struct CheckSameMap { void Check(Handle map, Handle new_map, const Expectations& expectations) { + // |map| was not reconfigured, therefore it should stay stable. + CHECK(map->is_stable()); CHECK(!map->is_deprecated()); CHECK_EQ(*map, *new_map); @@ -1196,6 +1210,21 @@ struct CheckSameMap { }; +// Checks that given |map| is NOT deprecated and matches expectations. +// |new_map| is unrelated to |map|. +struct CheckUnrelated { + void Check(Handle map, Handle new_map, + const Expectations& expectations) { + CHECK(!map->is_deprecated()); + CHECK_NE(*map, *new_map); + CHECK(expectations.Check(*map)); + + CHECK(new_map->is_stable()); + CHECK(!new_map->is_deprecated()); + } +}; + + // Checks that given |map| is NOT deprecated, and |new_map| is a result of // copy-generalize-all-representations. struct CheckCopyGeneralizeAllRepresentations { @@ -1289,7 +1318,8 @@ static void TestReconfigureProperty_CustomPropertyAfterTargetMap( Handle new_map = Map::ReconfigureExistingProperty(map2, kSplitProp, kData, NONE); - // |map2| should be left unchanged. + // |map2| should be left unchanged but marked unstable. + CHECK(!map2->is_stable()); CHECK(!map2->is_deprecated()); CHECK_NE(*map2, *new_map); CHECK(expectations2.Check(*map2)); @@ -1366,6 +1396,40 @@ TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) { } +TEST(ReconfigureDataFieldAttribute_DataConstantToAccConstantAfterTargetMap) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + + struct TestConfig { + Handle js_func_; + Handle pair_; + TestConfig() { + Isolate* isolate = CcTest::i_isolate(); + Factory* factory = isolate->factory(); + js_func_ = factory->NewFunction(factory->empty_string()); + pair_ = CreateAccessorPair(true, true); + } + + Handle AddPropertyAtBranch(int branch_id, Expectations& expectations, + Handle map) { + CHECK(branch_id == 1 || branch_id == 2); + if (branch_id == 1) { + return expectations.AddDataConstant(map, NONE, js_func_); + } else { + return expectations.AddAccessorConstant(map, NONE, pair_); + } + } + + void UpdateExpectations(int property_index, Expectations& expectations) {} + }; + + TestConfig config; + // These are completely separate branches in transition tree. + CheckUnrelated checker; + TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker); +} + + TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -1382,9 +1446,8 @@ TEST(ReconfigureDataFieldAttribute_SameAccessorConstantAfterTargetMap) { return expectations.AddAccessorConstant(map, NONE, pair_); } - bool UpdateExpectations(int property_index, Expectations& expectations) { + void UpdateExpectations(int property_index, Expectations& expectations) { // Two branches are "compatible" so the |map1| should NOT be deprecated. - return false; } }; @@ -1436,6 +1499,37 @@ TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) { } +TEST(ReconfigureDataFieldAttribute_AccConstantToDataFieldAfterTargetMap) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + + struct TestConfig { + Handle pair_; + TestConfig() { pair_ = CreateAccessorPair(true, true); } + + Handle AddPropertyAtBranch(int branch_id, Expectations& expectations, + Handle map) { + CHECK(branch_id == 1 || branch_id == 2); + if (branch_id == 1) { + return expectations.AddAccessorConstant(map, NONE, pair_); + } else { + Isolate* isolate = CcTest::i_isolate(); + Handle any_type = HeapType::Any(isolate); + return expectations.AddDataField(map, NONE, Representation::Smi(), + any_type); + } + } + + void UpdateExpectations(int property_index, Expectations& expectations) {} + }; + + TestConfig config; + // These are completely separate branches in transition tree. + CheckUnrelated checker; + TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker); +} + + //////////////////////////////////////////////////////////////////////////////// // A set of tests checking split map deprecation. // @@ -1487,6 +1581,7 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { // transition tree. CHECK(map->is_deprecated()); CHECK(!split_map->is_deprecated()); + CHECK(map2->is_stable()); CHECK(!map2->is_deprecated()); // Fill in transition tree of |map2| so that it can't have more transitions. @@ -1932,7 +2027,8 @@ struct FieldGeneralizationChecker { Handle updated_map = Map::Update(map1); CHECK_EQ(*map2, *updated_map); - expectations2.SetDataField(descriptor_, representation_, heap_type_); + expectations2.SetDataField(descriptor_, attributes_, representation_, + heap_type_); CHECK(expectations2.Check(*map2)); } }; diff --git a/src/env-inl.h b/src/env-inl.h index 08d743fba1e950..369bc2f780eb90 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -172,7 +172,6 @@ inline Environment::Environment(v8::Local context, : isolate_(context->GetIsolate()), isolate_data_(IsolateData::GetOrCreate(context->GetIsolate(), loop)), timer_base_(uv_now(loop)), - using_smalloc_alloc_cb_(false), using_domains_(false), using_abort_on_uncaught_exc_(false), using_asyncwrap_(false), @@ -293,14 +292,6 @@ inline uint64_t Environment::timer_base() const { return timer_base_; } -inline bool Environment::using_smalloc_alloc_cb() const { - return using_smalloc_alloc_cb_; -} - -inline void Environment::set_using_smalloc_alloc_cb(bool value) { - using_smalloc_alloc_cb_ = value; -} - inline bool Environment::using_abort_on_uncaught_exc() const { return using_abort_on_uncaught_exc_; } diff --git a/src/node_buffer.cc b/src/node_buffer.cc index c4a0f67b787ea8..b09f7333ff9fb8 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -485,7 +485,6 @@ void StringSlice(const FunctionCallbackInfo& args) { Isolate* isolate = env->isolate(); THROW_AND_RETURN_UNLESS_BUFFER(env, args.This()); - SPREAD_ARG(args.This(), ts_obj); if (ts_obj_length == 0) @@ -503,9 +502,7 @@ void StringSlice(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); THROW_AND_RETURN_UNLESS_BUFFER(env, args.This()); - SPREAD_ARG(args.This(), ts_obj); - SLICE_START_END(args[0], args[1], ts_obj_length) if (ts_obj_length == 0) return args.GetReturnValue().SetEmptyString(); @@ -579,9 +576,7 @@ void Copy(const FunctionCallbackInfo &args) { THROW_AND_RETURN_UNLESS_BUFFER(env, args.This()); THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); - - Local target_obj = args[0]->ToObject(env->isolate()); - + Local target_obj = args[0].As(); SPREAD_ARG(args.This(), ts_obj); SPREAD_ARG(target_obj, target); @@ -834,7 +829,6 @@ void Compare(const FunctionCallbackInfo &args) { THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]); THROW_AND_RETURN_UNLESS_BUFFER(env, args[1]); - SPREAD_ARG(args[0], obj_a); SPREAD_ARG(args[1], obj_b);