diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index b2b01df888281e..dfd3eef878c097 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -136,7 +136,6 @@ Sanjoy Das Seo Sanghyeon Stefan Penner Sylvestre Ledru -Taketoshi Aono Tiancheng "Timothy" Gu Tobias Burnus Victor Costan diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 6cc98294ec5179..ee6ccec7cec195 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 6 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 254 -#define V8_PATCH_LEVEL 31 +#define V8_PATCH_LEVEL 38 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 399b705f00897f..2bc833fe296276 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -1508,9 +1508,9 @@ void Genesis::InitializeGlobal(Handle global_object, object_function, "keys", Builtins::kObjectKeys, 1, true); native_context()->set_object_keys(*object_keys); SimpleInstallFunction(object_function, factory->entries_string(), - Builtins::kObjectEntries, 1, true); + Builtins::kObjectEntries, 1, false); SimpleInstallFunction(object_function, factory->values_string(), - Builtins::kObjectValues, 1, true); + Builtins::kObjectValues, 1, false); SimpleInstallFunction(isolate->initial_object_prototype(), "__defineGetter__", Builtins::kObjectDefineGetter, 2, diff --git a/deps/v8/src/builtins/builtins-definitions.h b/deps/v8/src/builtins/builtins-definitions.h index 0ffd15df7c08fa..a4a0bb9e2cb192 100644 --- a/deps/v8/src/builtins/builtins-definitions.h +++ b/deps/v8/src/builtins/builtins-definitions.h @@ -755,7 +755,7 @@ namespace internal { CPP(ObjectDefineProperties) \ CPP(ObjectDefineProperty) \ CPP(ObjectDefineSetter) \ - TFJ(ObjectEntries, 1, kObject) \ + CPP(ObjectEntries) \ CPP(ObjectFreeze) \ TFJ(ObjectGetOwnPropertyDescriptor, \ SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ @@ -785,7 +785,7 @@ namespace internal { /* ES #sec-object.prototype.tolocalestring */ \ TFJ(ObjectPrototypeToLocaleString, 0) \ CPP(ObjectSeal) \ - TFJ(ObjectValues, 1, kObject) \ + CPP(ObjectValues) \ \ /* instanceof */ \ TFC(OrdinaryHasInstance, Compare, 1) \ diff --git a/deps/v8/src/builtins/builtins-object-gen.cc b/deps/v8/src/builtins/builtins-object-gen.cc index 9e344820dcca6d..4cd012e6f01b20 100644 --- a/deps/v8/src/builtins/builtins-object-gen.cc +++ b/deps/v8/src/builtins/builtins-object-gen.cc @@ -16,8 +16,6 @@ namespace internal { // ES6 section 19.1 Object Objects typedef compiler::Node Node; -template -using TNode = CodeStubAssembler::TNode; class ObjectBuiltinsAssembler : public CodeStubAssembler { public: @@ -36,46 +34,6 @@ class ObjectBuiltinsAssembler : public CodeStubAssembler { Node* ConstructDataDescriptor(Node* context, Node* value, Node* writable, Node* enumerable, Node* configurable); Node* GetAccessorOrUndefined(Node* accessor, Label* if_bailout); - - Node* IsSpecialReceiverMap(SloppyTNode map); -}; - -class ObjectEntriesValuesBuiltinsAssembler : public ObjectBuiltinsAssembler { - public: - explicit ObjectEntriesValuesBuiltinsAssembler( - compiler::CodeAssemblerState* state) - : ObjectBuiltinsAssembler(state) {} - - protected: - enum CollectType { kEntries, kValues }; - - TNode IsStringWrapperElementsKind(TNode map); - - TNode IsPropertyEnumerable(TNode details); - - TNode IsPropertyKindAccessor(TNode kind); - - TNode IsPropertyKindData(TNode kind); - - TNode HasHiddenPrototype(TNode map); - - TNode LoadPropertyKind(TNode details) { - return DecodeWord32(details); - } - - void GetOwnValuesOrEntries(TNode context, TNode maybe_object, - CollectType collect_type); - - void GotoIfMapHasSlowProperties(TNode map, Label* if_slow); - - TNode FastGetOwnValuesOrEntries( - TNode context, TNode object, - Label* if_call_runtime_with_fast_path, Label* if_no_properties, - CollectType collect_type); - - TNode FinalizeValuesOrEntriesJSArray( - TNode context, TNode values_or_entries, - TNode size, TNode array_map, Label* if_empty); }; void ObjectBuiltinsAssembler::ReturnToStringFormat(Node* context, @@ -139,249 +97,6 @@ Node* ObjectBuiltinsAssembler::ConstructDataDescriptor(Node* context, return js_desc; } -Node* ObjectBuiltinsAssembler::IsSpecialReceiverMap(SloppyTNode map) { - CSA_SLOW_ASSERT(this, IsMap(map)); - Node* is_special = IsSpecialReceiverInstanceType(LoadMapInstanceType(map)); - uint32_t mask = - Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask; - USE(mask); - // Interceptors or access checks imply special receiver. - CSA_ASSERT(this, - SelectConstant(IsSetWord32(LoadMapBitField(map), mask), is_special, - Int32Constant(1), MachineRepresentation::kWord32)); - return is_special; -} - -TNode -ObjectEntriesValuesBuiltinsAssembler::IsStringWrapperElementsKind( - TNode map) { - Node* kind = LoadMapElementsKind(map); - return Word32Or( - Word32Equal(kind, Int32Constant(FAST_STRING_WRAPPER_ELEMENTS)), - Word32Equal(kind, Int32Constant(SLOW_STRING_WRAPPER_ELEMENTS))); -} - -TNode ObjectEntriesValuesBuiltinsAssembler::IsPropertyEnumerable( - TNode details) { - TNode attributes = - DecodeWord32(details); - return IsNotSetWord32(attributes, PropertyAttributes::DONT_ENUM); -} - -TNode ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindAccessor( - TNode kind) { - return Word32Equal(kind, Int32Constant(PropertyKind::kAccessor)); -} - -TNode ObjectEntriesValuesBuiltinsAssembler::IsPropertyKindData( - TNode kind) { - return Word32Equal(kind, Int32Constant(PropertyKind::kData)); -} - -TNode ObjectEntriesValuesBuiltinsAssembler::HasHiddenPrototype( - TNode map) { - TNode bit_field3 = LoadMapBitField3(map); - return DecodeWord32(bit_field3); -} - -void ObjectEntriesValuesBuiltinsAssembler::GetOwnValuesOrEntries( - TNode context, TNode maybe_object, - CollectType collect_type) { - TNode object = TNode::UncheckedCast( - CallBuiltin(Builtins::kToObject, context, maybe_object)); - - Label if_call_runtime_with_fast_path(this, Label::kDeferred), - if_call_runtime(this, Label::kDeferred), - if_no_properties(this, Label::kDeferred); - - TNode map = LoadMap(object); - GotoIfNot(IsJSObjectMap(map), &if_call_runtime); - GotoIfMapHasSlowProperties(map, &if_call_runtime); - - TNode elements = LoadElements(object); - // If the object has elements, we treat it as slow case. - // So, we go to runtime call. - GotoIfNot(IsEmptyFixedArray(elements), &if_call_runtime_with_fast_path); - - TNode result = FastGetOwnValuesOrEntries( - context, object, &if_call_runtime_with_fast_path, &if_no_properties, - collect_type); - Return(result); - - BIND(&if_no_properties); - { - Node* native_context = LoadNativeContext(context); - Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); - Node* empty_array = AllocateJSArray(PACKED_ELEMENTS, array_map, - IntPtrConstant(0), SmiConstant(0)); - Return(empty_array); - } - - BIND(&if_call_runtime_with_fast_path); - { - // In slow case, we simply call runtime. - if (collect_type == CollectType::kEntries) { - Return(CallRuntime(Runtime::kObjectEntries, context, object)); - } else { - DCHECK(collect_type == CollectType::kValues); - Return(CallRuntime(Runtime::kObjectValues, context, object)); - } - } - - BIND(&if_call_runtime); - { - // In slow case, we simply call runtime. - if (collect_type == CollectType::kEntries) { - Return(CallRuntime(Runtime::kObjectEntriesSkipFastPath, context, object)); - } else { - DCHECK(collect_type == CollectType::kValues); - Return(CallRuntime(Runtime::kObjectValuesSkipFastPath, context, object)); - } - } -} - -void ObjectEntriesValuesBuiltinsAssembler::GotoIfMapHasSlowProperties( - TNode map, Label* if_slow) { - GotoIf(IsStringWrapperElementsKind(map), if_slow); - GotoIf(IsSpecialReceiverMap(map), if_slow); - GotoIf(HasHiddenPrototype(map), if_slow); - GotoIf(IsDictionaryMap(map), if_slow); -} - -TNode ObjectEntriesValuesBuiltinsAssembler::FastGetOwnValuesOrEntries( - TNode context, TNode object, - Label* if_call_runtime_with_fast_path, Label* if_no_properties, - CollectType collect_type) { - Node* native_context = LoadNativeContext(context); - TNode array_map = - LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context); - TNode map = LoadMap(object); - TNode bit_field3 = LoadMapBitField3(map); - - Label if_has_enum_cache(this), if_not_has_enum_cache(this), - collect_entries(this); - Node* object_enum_length = - DecodeWordFromWord32(bit_field3); - Node* has_enum_cache = WordNotEqual( - object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)); - - // In case, we found enum_cache in object, - // we use it as array_length becuase it has same size for - // Object.(entries/values) result array object length. - // So object_enum_length use less memory space than - // NumberOfOwnDescriptorsBits value. - // And in case, if enum_cache_not_found, - // we call runtime and initialize enum_cache for subsequent call of - // CSA fast path. - Branch(has_enum_cache, &if_has_enum_cache, if_call_runtime_with_fast_path); - - BIND(&if_has_enum_cache); - { - GotoIf(WordEqual(object_enum_length, IntPtrConstant(0)), if_no_properties); - TNode values_or_entries = TNode::UncheckedCast( - AllocateFixedArray(PACKED_ELEMENTS, object_enum_length, - INTPTR_PARAMETERS, kAllowLargeObjectAllocation)); - - // If in case we have enum_cache, - // we can't detect accessor of object until loop through descritpros. - // So if object might have accessor, - // we will remain invalid addresses of FixedArray. - // Because in that case, we need to jump to runtime call. - // So the array filled by the-hole even if enum_cache exists. - FillFixedArrayWithValue(PACKED_ELEMENTS, values_or_entries, - IntPtrConstant(0), object_enum_length, - Heap::kTheHoleValueRootIndex); - - TVARIABLE(IntPtrT, var_result_index, IntPtrConstant(0)); - TVARIABLE(IntPtrT, var_descriptor_index, IntPtrConstant(0)); - Variable* vars[] = {&var_descriptor_index, &var_result_index}; - // Let desc be ? O.[[GetOwnProperty]](key). - TNode descriptors = LoadMapDescriptors(map); - Label loop(this, 2, vars), after_loop(this), loop_condition(this); - Branch(IntPtrEqual(var_descriptor_index, object_enum_length), &after_loop, - &loop); - - // We dont use BuildFastLoop. - // Instead, we use hand-written loop - // because of we need to use 'continue' functionality. - BIND(&loop); - { - // Currently, we will not invoke getters, - // so, map will not be changed. - CSA_ASSERT(this, WordEqual(map, LoadMap(object))); - TNode descriptor_index = TNode::UncheckedCast( - TruncateWordToWord32(var_descriptor_index)); - Node* next_key = DescriptorArrayGetKey(descriptors, descriptor_index); - - // Skip Symbols. - GotoIf(IsSymbol(next_key), &loop_condition); - - TNode details = TNode::UncheckedCast( - DescriptorArrayGetDetails(descriptors, descriptor_index)); - TNode kind = LoadPropertyKind(details); - - // If property is accessor, we escape fast path and call runtime. - GotoIf(IsPropertyKindAccessor(kind), if_call_runtime_with_fast_path); - CSA_ASSERT(this, IsPropertyKindData(kind)); - - // If desc is not undefined and desc.[[Enumerable]] is true, then - GotoIfNot(IsPropertyEnumerable(details), &loop_condition); - - VARIABLE(var_property_value, MachineRepresentation::kTagged, - UndefinedConstant()); - Node* descriptor_name_index = DescriptorNumberToIndex(descriptor_index); - - // Let value be ? Get(O, key). - LoadPropertyFromFastObject(object, map, descriptors, - descriptor_name_index, details, - &var_property_value); - - // If kind is "value", append value to properties. - Node* value = var_property_value.value(); - - if (collect_type == CollectType::kEntries) { - // Let entry be CreateArrayFromList(« key, value »). - Node* array = nullptr; - Node* elements = nullptr; - std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( - PACKED_ELEMENTS, array_map, SmiConstant(2), nullptr, - IntPtrConstant(2)); - StoreFixedArrayElement(elements, 0, next_key, SKIP_WRITE_BARRIER); - StoreFixedArrayElement(elements, 1, value, SKIP_WRITE_BARRIER); - value = array; - } - - StoreFixedArrayElement(values_or_entries, var_result_index, value); - Increment(&var_result_index, 1); - Goto(&loop_condition); - - BIND(&loop_condition); - { - Increment(&var_descriptor_index, 1); - Branch(IntPtrEqual(var_descriptor_index, object_enum_length), - &after_loop, &loop); - } - } - BIND(&after_loop); - return FinalizeValuesOrEntriesJSArray(context, values_or_entries, - var_result_index, array_map, - if_no_properties); - } -} - -TNode -ObjectEntriesValuesBuiltinsAssembler::FinalizeValuesOrEntriesJSArray( - TNode context, TNode result, TNode size, - TNode array_map, Label* if_empty) { - CSA_ASSERT(this, IsJSArrayMap(array_map)); - - GotoIf(IntPtrEqual(size, IntPtrConstant(0)), if_empty); - Node* array = AllocateUninitializedJSArrayWithoutElements( - array_map, SmiTag(size), nullptr); - StoreObjectField(array, JSArray::kElementsOffset, result); - return TNode::UncheckedCast(array); -} - TF_BUILTIN(ObjectPrototypeToLocaleString, CodeStubAssembler) { TNode context = CAST(Parameter(Descriptor::kContext)); TNode receiver = CAST(Parameter(Descriptor::kReceiver)); @@ -551,22 +266,6 @@ TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { } } -TF_BUILTIN(ObjectValues, ObjectEntriesValuesBuiltinsAssembler) { - TNode object = - TNode::UncheckedCast(Parameter(Descriptor::kObject)); - TNode context = - TNode::UncheckedCast(Parameter(Descriptor::kContext)); - GetOwnValuesOrEntries(context, object, CollectType::kValues); -} - -TF_BUILTIN(ObjectEntries, ObjectEntriesValuesBuiltinsAssembler) { - TNode object = - TNode::UncheckedCast(Parameter(Descriptor::kObject)); - TNode context = - TNode::UncheckedCast(Parameter(Descriptor::kContext)); - GetOwnValuesOrEntries(context, object, CollectType::kEntries); -} - // ES #sec-object.prototype.isprototypeof TF_BUILTIN(ObjectPrototypeIsPrototypeOf, ObjectBuiltinsAssembler) { Node* receiver = Parameter(Descriptor::kReceiver); diff --git a/deps/v8/src/builtins/builtins-object.cc b/deps/v8/src/builtins/builtins-object.cc index 4e353b92600531..36f7ebfc0a87cb 100644 --- a/deps/v8/src/builtins/builtins-object.cc +++ b/deps/v8/src/builtins/builtins-object.cc @@ -395,6 +395,31 @@ BUILTIN(ObjectIsSealed) { return isolate->heap()->ToBoolean(result.FromJust()); } +BUILTIN(ObjectValues) { + HandleScope scope(isolate); + Handle object = args.atOrUndefined(isolate, 1); + Handle receiver; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, + Object::ToObject(isolate, object)); + Handle values; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS)); + return *isolate->factory()->NewJSArrayWithElements(values); +} + +BUILTIN(ObjectEntries) { + HandleScope scope(isolate); + Handle object = args.atOrUndefined(isolate, 1); + Handle receiver; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, + Object::ToObject(isolate, object)); + Handle entries; + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( + isolate, entries, + JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS)); + return *isolate->factory()->NewJSArrayWithElements(entries); +} + BUILTIN(ObjectGetOwnPropertyDescriptors) { HandleScope scope(isolate); Handle object = args.atOrUndefined(isolate, 1); diff --git a/deps/v8/src/code-stub-assembler.cc b/deps/v8/src/code-stub-assembler.cc index f98e7fe519297e..2027d208abc1d8 100644 --- a/deps/v8/src/code-stub-assembler.cc +++ b/deps/v8/src/code-stub-assembler.cc @@ -4019,6 +4019,19 @@ Node* CodeStubAssembler::InstanceTypeEqual(Node* instance_type, int type) { return Word32Equal(instance_type, Int32Constant(type)); } +Node* CodeStubAssembler::IsSpecialReceiverMap(Node* map) { + CSA_SLOW_ASSERT(this, IsMap(map)); + Node* is_special = IsSpecialReceiverInstanceType(LoadMapInstanceType(map)); + uint32_t mask = + Map::HasNamedInterceptorBit::kMask | Map::IsAccessCheckNeededBit::kMask; + USE(mask); + // Interceptors or access checks imply special receiver. + CSA_ASSERT(this, + SelectConstant(IsSetWord32(LoadMapBitField(map), mask), is_special, + Int32Constant(1), MachineRepresentation::kWord32)); + return is_special; +} + TNode CodeStubAssembler::IsDictionaryMap(SloppyTNode map) { CSA_SLOW_ASSERT(this, IsMap(map)); Node* bit_field3 = LoadMapBitField3(map); @@ -6369,38 +6382,36 @@ Node* CodeStubAssembler::DescriptorArrayNumberOfEntries(Node* descriptors) { descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex)); } -Node* CodeStubAssembler::DescriptorNumberToIndex( - SloppyTNode descriptor_number) { - Node* descriptor_size = Int32Constant(DescriptorArray::kEntrySize); - Node* index = Int32Mul(descriptor_number, descriptor_size); - return ChangeInt32ToIntPtr(index); +namespace { + +Node* DescriptorNumberToIndex(CodeStubAssembler* a, Node* descriptor_number) { + Node* descriptor_size = a->Int32Constant(DescriptorArray::kEntrySize); + Node* index = a->Int32Mul(descriptor_number, descriptor_size); + return a->ChangeInt32ToIntPtr(index); } +} // namespace + Node* CodeStubAssembler::DescriptorArrayToKeyIndex(Node* descriptor_number) { return IntPtrAdd(IntPtrConstant(DescriptorArray::ToKeyIndex(0)), - DescriptorNumberToIndex(descriptor_number)); + DescriptorNumberToIndex(this, descriptor_number)); } Node* CodeStubAssembler::DescriptorArrayGetSortedKeyIndex( Node* descriptors, Node* descriptor_number) { - Node* details = DescriptorArrayGetDetails( - TNode::UncheckedCast(descriptors), - TNode::UncheckedCast(descriptor_number)); + const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize; + Node* details = LoadAndUntagToWord32FixedArrayElement( + descriptors, DescriptorNumberToIndex(this, descriptor_number), + details_offset); return DecodeWord32(details); } Node* CodeStubAssembler::DescriptorArrayGetKey(Node* descriptors, Node* descriptor_number) { const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize; - return LoadFixedArrayElement( - descriptors, DescriptorNumberToIndex(descriptor_number), key_offset); -} - -TNode CodeStubAssembler::DescriptorArrayGetDetails( - TNode descriptors, TNode descriptor_number) { - const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize; - return TNode::UncheckedCast(LoadAndUntagToWord32FixedArrayElement( - descriptors, DescriptorNumberToIndex(descriptor_number), details_offset)); + return LoadFixedArrayElement(descriptors, + DescriptorNumberToIndex(this, descriptor_number), + key_offset); } void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name, @@ -6599,22 +6610,12 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, Variable* var_value) { DCHECK_EQ(MachineRepresentation::kWord32, var_details->rep()); DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep()); + Comment("[ LoadPropertyFromFastObject"); Node* details = LoadDetailsByKeyIndex(descriptors, name_index); var_details->Bind(details); - LoadPropertyFromFastObject(object, map, descriptors, name_index, details, - var_value); -} - -void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map, - Node* descriptors, - Node* name_index, - Node* details, - Variable* var_value) { - Comment("[ LoadPropertyFromFastObject"); - Node* location = DecodeWord32(details); Label if_in_field(this), if_in_descriptor(this), done(this); diff --git a/deps/v8/src/code-stub-assembler.h b/deps/v8/src/code-stub-assembler.h index 4a72b203a78c0d..0dd7a35c4a057a 100644 --- a/deps/v8/src/code-stub-assembler.h +++ b/deps/v8/src/code-stub-assembler.h @@ -1125,6 +1125,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { Node* IsSequentialStringInstanceType(Node* instance_type); Node* IsShortExternalStringInstanceType(Node* instance_type); Node* IsSpecialReceiverInstanceType(Node* instance_type); + Node* IsSpecialReceiverMap(Node* map); Node* IsSpeciesProtectorCellInvalid(); Node* IsStringInstanceType(Node* instance_type); Node* IsString(Node* object); @@ -1583,10 +1584,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { Node* name_index, Variable* var_details, Variable* var_value); - void LoadPropertyFromFastObject(Node* object, Node* map, Node* descriptors, - Node* name_index, Node* details, - Variable* var_value); - void LoadPropertyFromNameDictionary(Node* dictionary, Node* entry, Variable* var_details, Variable* var_value); @@ -1909,15 +1906,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { void DescriptorLookupBinary(Node* unique_name, Node* descriptors, Node* nof, Label* if_found, Variable* var_name_index, Label* if_not_found); - Node* DescriptorNumberToIndex(SloppyTNode descriptor_number); // Implements DescriptorArray::ToKeyIndex. // Returns an untagged IntPtr. Node* DescriptorArrayToKeyIndex(Node* descriptor_number); // Implements DescriptorArray::GetKey. Node* DescriptorArrayGetKey(Node* descriptors, Node* descriptor_number); - // Implements DescriptorArray::GetKey. - TNode DescriptorArrayGetDetails(TNode descriptors, - TNode descriptor_number); Node* CallGetterIfAccessor(Node* value, Node* details, Node* context, Node* receiver, Label* if_bailout, diff --git a/deps/v8/src/debug/debug-evaluate.cc b/deps/v8/src/debug/debug-evaluate.cc index 33bc81e5f74120..e5865e639c3028 100644 --- a/deps/v8/src/debug/debug-evaluate.cc +++ b/deps/v8/src/debug/debug-evaluate.cc @@ -343,11 +343,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { V(AllocateSeqOneByteString) \ V(AllocateSeqTwoByteString) \ V(ObjectCreate) \ - V(ObjectEntries) \ - V(ObjectEntriesSkipFastPath) \ V(ObjectHasOwnProperty) \ - V(ObjectValues) \ - V(ObjectValuesSkipFastPath) \ V(ArrayIndexOf) \ V(ArrayIncludes_Slow) \ V(ArrayIsArray) \ diff --git a/deps/v8/src/field-index.h b/deps/v8/src/field-index.h index 428ad52cc2d106..9e390e3d4658e4 100644 --- a/deps/v8/src/field-index.h +++ b/deps/v8/src/field-index.h @@ -123,7 +123,8 @@ class FieldIndex final { }; // Offset of first inobject property from beginning of object. class FirstInobjectPropertyOffsetBits - : public BitField64 {}; + : public BitField64 {}; class IsHiddenField : public BitField64 {}; STATIC_ASSERT(IsHiddenField::kNext <= 64); diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index c3841aa63e7ad5..1cbc2ca418ea7a 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -2431,6 +2431,7 @@ int ObjectTemplateInfo::embedder_field_count() const { } void ObjectTemplateInfo::set_embedder_field_count(int count) { + DCHECK_LE(count, JSObject::kMaxEmbedderFields); return set_data( Smi::FromInt(EmbedderFieldCount::update(Smi::ToInt(data()), count))); } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index f8c55e57a632d6..af2e3eccb37004 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -8791,10 +8791,9 @@ MUST_USE_RESULT Maybe FastGetOwnValuesOrEntries( MaybeHandle GetOwnValuesOrEntries(Isolate* isolate, Handle object, PropertyFilter filter, - bool try_fast_path, bool get_entries) { Handle values_or_entries; - if (try_fast_path && filter == ENUMERABLE_STRINGS) { + if (filter == ENUMERABLE_STRINGS) { Maybe fast_values_or_entries = FastGetOwnValuesOrEntries( isolate, object, get_entries, &values_or_entries); if (fast_values_or_entries.IsNothing()) return MaybeHandle(); @@ -8847,17 +8846,13 @@ MaybeHandle GetOwnValuesOrEntries(Isolate* isolate, } MaybeHandle JSReceiver::GetOwnValues(Handle object, - PropertyFilter filter, - bool try_fast_path) { - return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, - try_fast_path, false); + PropertyFilter filter) { + return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, false); } MaybeHandle JSReceiver::GetOwnEntries(Handle object, - PropertyFilter filter, - bool try_fast_path) { - return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, - try_fast_path, true); + PropertyFilter filter) { + return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, true); } bool Map::DictionaryElementsInPrototypeChainOnly() { @@ -13783,18 +13778,24 @@ void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type, int requested_in_object_properties, int* instance_size, int* in_object_properties) { + DCHECK_LE(static_cast(requested_embedder_fields), + JSObject::kMaxEmbedderFields); int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot); int max_nof_fields = (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2; CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties); - *in_object_properties = Min(requested_in_object_properties, max_nof_fields); - CHECK_LE(requested_embedder_fields, max_nof_fields - *in_object_properties); + CHECK_LE(static_cast(requested_embedder_fields), + static_cast(max_nof_fields)); + *in_object_properties = Min(requested_in_object_properties, + max_nof_fields - requested_embedder_fields); *instance_size = header_size + ((requested_embedder_fields + *in_object_properties) << kPointerSizeLog2); CHECK_EQ(*in_object_properties, ((*instance_size - header_size) >> kPointerSizeLog2) - requested_embedder_fields); + CHECK_LE(static_cast(*instance_size), + static_cast(JSObject::kMaxInstanceSize)); } // static diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 93f4a4eb95b583..c4e3d972e111a9 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -2182,12 +2182,10 @@ class JSReceiver: public HeapObject { Handle object); MUST_USE_RESULT static MaybeHandle GetOwnValues( - Handle object, PropertyFilter filter, - bool try_fast_path = true); + Handle object, PropertyFilter filter); MUST_USE_RESULT static MaybeHandle GetOwnEntries( - Handle object, PropertyFilter filter, - bool try_fast_path = true); + Handle object, PropertyFilter filter); static const int kHashMask = PropertyArray::HashField::kMask; @@ -2673,6 +2671,11 @@ class JSObject: public JSReceiver { static const int kMaxInObjectProperties = (kMaxInstanceSize - kHeaderSize) >> kPointerSizeLog2; STATIC_ASSERT(kMaxInObjectProperties <= kMaxNumberOfDescriptors); + // TODO(cbruni): Revisit calculation of the max supported embedder fields. + static const int kMaxEmbedderFields = + ((1 << kFirstInobjectPropertyOffsetBitCount) - 1 - kHeaderSize) >> + kPointerSizeLog2; + STATIC_ASSERT(kMaxEmbedderFields <= kMaxInObjectProperties); class BodyDescriptor; // No weak fields. diff --git a/deps/v8/src/profiler/cpu-profiler.cc b/deps/v8/src/profiler/cpu-profiler.cc index ac8f55a89b5545..a915ebd5119e56 100644 --- a/deps/v8/src/profiler/cpu-profiler.cc +++ b/deps/v8/src/profiler/cpu-profiler.cc @@ -165,13 +165,16 @@ void ProfilerEventsProcessor::Run() { if (nextSampleTime > now) { #if V8_OS_WIN - // Do not use Sleep on Windows as it is very imprecise. - // Could be up to 16ms jitter, which is unacceptable for the purpose. - while (base::TimeTicks::HighResolutionNow() < nextSampleTime) { - } -#else - base::OS::Sleep(nextSampleTime - now); + if (nextSampleTime - now < base::TimeDelta::FromMilliseconds(100)) { + // Do not use Sleep on Windows as it is very imprecise, with up to 16ms + // jitter, which is unacceptable for short profile intervals. + while (base::TimeTicks::HighResolutionNow() < nextSampleTime) { + } + } else // NOLINT #endif + { + base::OS::Sleep(nextSampleTime - now); + } } // Schedule next sample. sampler_ is nullptr in tests. diff --git a/deps/v8/src/property-details.h b/deps/v8/src/property-details.h index 34c43047f84e2f..dbd4f93acd282f 100644 --- a/deps/v8/src/property-details.h +++ b/deps/v8/src/property-details.h @@ -197,6 +197,7 @@ class Representation { static const int kDescriptorIndexBitCount = 10; +static const int kFirstInobjectPropertyOffsetBitCount = 7; // The maximum number of descriptors we want in a descriptor array. It should // fit in a page and also the following should hold: // kMaxNumberOfDescriptors + kFieldsAdded <= PropertyArray::kMaxLength. diff --git a/deps/v8/src/runtime/runtime-object.cc b/deps/v8/src/runtime/runtime-object.cc index 379472bdbea4da..057ead94078359 100644 --- a/deps/v8/src/runtime/runtime-object.cc +++ b/deps/v8/src/runtime/runtime-object.cc @@ -439,61 +439,6 @@ RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) { return *object; } -RUNTIME_FUNCTION(Runtime_ObjectValues) { - HandleScope scope(isolate); - DCHECK_EQ(1, args.length()); - - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); - - Handle values; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, values, - JSReceiver::GetOwnValues(receiver, PropertyFilter::ENUMERABLE_STRINGS, - true)); - return *isolate->factory()->NewJSArrayWithElements(values); -} - -RUNTIME_FUNCTION(Runtime_ObjectValuesSkipFastPath) { - HandleScope scope(isolate); - DCHECK_EQ(1, args.length()); - - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); - - Handle value; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, value, - JSReceiver::GetOwnValues(receiver, PropertyFilter::ENUMERABLE_STRINGS, - false)); - return *isolate->factory()->NewJSArrayWithElements(value); -} - -RUNTIME_FUNCTION(Runtime_ObjectEntries) { - HandleScope scope(isolate); - DCHECK_EQ(1, args.length()); - - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); - - Handle entries; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, entries, - JSReceiver::GetOwnEntries(receiver, PropertyFilter::ENUMERABLE_STRINGS, - true)); - return *isolate->factory()->NewJSArrayWithElements(entries); -} - -RUNTIME_FUNCTION(Runtime_ObjectEntriesSkipFastPath) { - HandleScope scope(isolate); - DCHECK_EQ(1, args.length()); - - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); - - Handle entries; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, entries, - JSReceiver::GetOwnEntries(receiver, PropertyFilter::ENUMERABLE_STRINGS, - false)); - return *isolate->factory()->NewJSArrayWithElements(entries); -} RUNTIME_FUNCTION(Runtime_GetProperty) { HandleScope scope(isolate); diff --git a/deps/v8/src/runtime/runtime.h b/deps/v8/src/runtime/runtime.h index 487ee675ad381a..d05f4984c6af7a 100644 --- a/deps/v8/src/runtime/runtime.h +++ b/deps/v8/src/runtime/runtime.h @@ -391,10 +391,6 @@ namespace internal { F(ObjectCreate, 2, 1) \ F(InternalSetPrototype, 2, 1) \ F(OptimizeObjectForAddingMultipleProperties, 2, 1) \ - F(ObjectValues, 1, 1) \ - F(ObjectValuesSkipFastPath, 1, 1) \ - F(ObjectEntries, 1, 1) \ - F(ObjectEntriesSkipFastPath, 1, 1) \ F(GetProperty, 2, 1) \ F(KeyedGetProperty, 2, 1) \ F(AddNamedProperty, 4, 1) \ diff --git a/deps/v8/src/simulator-base.h b/deps/v8/src/simulator-base.h index 27dc87d050322a..84c1f2fd5b876e 100644 --- a/deps/v8/src/simulator-base.h +++ b/deps/v8/src/simulator-base.h @@ -43,6 +43,26 @@ class SimulatorBase { return ConvertReturn(ret); } + // Convert back integral return types. + template + static typename std::enable_if::value, T>::type + ConvertReturn(intptr_t ret) { + static_assert(sizeof(T) <= sizeof(intptr_t), "type bigger than ptrsize"); + return static_cast(ret); + } + + // Convert back pointer-typed return types. + template + static typename std::enable_if::value, T>::type + ConvertReturn(intptr_t ret) { + return reinterpret_cast(ret); + } + + // Convert back void return type (i.e. no return). + template + static typename std::enable_if::value, T>::type ConvertReturn( + intptr_t ret) {} + private: // Runtime call support. Uses the isolate in a thread-safe way. static void* RedirectExternalReference(Isolate* isolate, @@ -69,26 +89,6 @@ class SimulatorBase { ConvertArg(T arg) { return reinterpret_cast(arg); } - - // Convert back integral return types. - template - static typename std::enable_if::value, T>::type - ConvertReturn(intptr_t ret) { - static_assert(sizeof(T) <= sizeof(intptr_t), "type bigger than ptrsize"); - return static_cast(ret); - } - - // Convert back pointer-typed return types. - template - static typename std::enable_if::value, T>::type - ConvertReturn(intptr_t ret) { - return reinterpret_cast(ret); - } - - // Convert back void return type (i.e. no return). - template - static typename std::enable_if::value, T>::type ConvertReturn( - intptr_t ret) {} }; // When the generated code calls an external reference we need to catch that in diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 73dc19aa66a359..b3937382da0841 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -2699,6 +2699,110 @@ THREADED_TEST(InternalFields) { CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust()); } +TEST(InternalFieldsSubclassing) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + for (int nof_embedder_fields = 0; + nof_embedder_fields < i::JSObject::kMaxEmbedderFields; + nof_embedder_fields++) { + Local templ = v8::FunctionTemplate::New(isolate); + Local instance_templ = templ->InstanceTemplate(); + instance_templ->SetInternalFieldCount(nof_embedder_fields); + Local constructor = + templ->GetFunction(env.local()).ToLocalChecked(); + // Check that instances have the correct NOF properties. + Local obj = + constructor->NewInstance(env.local()).ToLocalChecked(); + + i::Handle i_obj = + i::Handle::cast(v8::Utils::OpenHandle(*obj)); + CHECK_EQ(nof_embedder_fields, obj->InternalFieldCount()); + CHECK_EQ(0, i_obj->map()->GetInObjectProperties()); + // Check writing and reading internal fields. + for (int j = 0; j < nof_embedder_fields; j++) { + CHECK(obj->GetInternalField(j)->IsUndefined()); + int value = 17 + j; + obj->SetInternalField(j, v8_num(value)); + } + for (int j = 0; j < nof_embedder_fields; j++) { + int value = 17 + j; + CHECK_EQ(value, + obj->GetInternalField(j)->Int32Value(env.local()).FromJust()); + } + CHECK(env->Global() + ->Set(env.local(), v8_str("BaseClass"), constructor) + .FromJust()); + // Create various levels of subclasses to stress instance size calculation. + const int kMaxNofProperties = + i::JSObject::kMaxInObjectProperties - nof_embedder_fields; + // Select only a few values to speed up the test. + int sizes[] = {0, + 1, + 2, + 3, + 4, + 5, + 6, + kMaxNofProperties / 4, + kMaxNofProperties / 2, + kMaxNofProperties - 2, + kMaxNofProperties - 1, + kMaxNofProperties + 1, + kMaxNofProperties + 2, + kMaxNofProperties * 2, + kMaxNofProperties * 2}; + for (size_t i = 0; i < arraysize(sizes); i++) { + int nof_properties = sizes[i]; + bool in_object_only = nof_properties <= kMaxNofProperties; + std::ostringstream src; + // Assembler source string for a subclass with {nof_properties} + // in-object properties. + src << "(function() {\n" + << " class SubClass extends BaseClass {\n" + << " constructor() {\n" + << " super();\n"; + // Set {nof_properties} instance properties in the constructor. + for (int j = 0; j < nof_properties; j++) { + src << " this.property" << j << " = " << j << ";\n"; + } + src << " }\n" + << " };\n" + << " let instance;\n" + << " for (let i = 0; i < 3; i++) {\n" + << " instance = new SubClass();\n" + << " }" + << " return instance;\n" + << "})();"; + Local value = CompileRun(src.str().c_str()).As(); + + i::Handle i_value = + i::Handle::cast(v8::Utils::OpenHandle(*value)); +#ifdef VERIFY_HEAP + i_value->HeapObjectVerify(); + i_value->map()->HeapObjectVerify(); + i_value->map()->FindRootMap()->HeapObjectVerify(); +#endif + CHECK_EQ(nof_embedder_fields, value->InternalFieldCount()); + if (in_object_only) { + CHECK_LE(nof_properties, i_value->map()->GetInObjectProperties()); + } else { + CHECK_LE(kMaxNofProperties, i_value->map()->GetInObjectProperties()); + } + + // Make Sure we get the precise property count. + i_value->map()->FindRootMap()->CompleteInobjectSlackTracking(); + // TODO(cbruni): fix accounting to make this condition true. + // CHECK_EQ(0, i_value->map()->UnusedPropertyFields()); + if (in_object_only) { + CHECK_EQ(nof_properties, i_value->map()->GetInObjectProperties()); + } else { + CHECK_LE(kMaxNofProperties, i_value->map()->GetInObjectProperties()); + } + } + } +} + THREADED_TEST(InternalFieldsOfRegularObjects) { LocalContext env; v8::Isolate* isolate = env->GetIsolate();