diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/src/objects | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/v8/src/objects')
99 files changed, 1197 insertions, 1068 deletions
diff --git a/chromium/v8/src/objects/api-callbacks.tq b/chromium/v8/src/objects/api-callbacks.tq index 8a8aab59f8d..102ffd7ab21 100644 --- a/chromium/v8/src/objects/api-callbacks.tq +++ b/chromium/v8/src/objects/api-callbacks.tq @@ -40,7 +40,6 @@ extern class AccessCheckInfo extends Struct { data: Object; } -type PropertyAttributes extends int32 constexpr 'PropertyAttributes'; type SideEffectType extends int32 constexpr 'SideEffectType'; bitfield struct AccessorInfoFlags extends uint31 { diff --git a/chromium/v8/src/objects/arguments-inl.h b/chromium/v8/src/objects/arguments-inl.h index 8c49d909d2f..494a8960bd8 100644 --- a/chromium/v8/src/objects/arguments-inl.h +++ b/chromium/v8/src/objects/arguments-inl.h @@ -5,9 +5,8 @@ #ifndef V8_OBJECTS_ARGUMENTS_INL_H_ #define V8_OBJECTS_ARGUMENTS_INL_H_ -#include "src/objects/arguments.h" - #include "src/execution/isolate-inl.h" +#include "src/objects/arguments.h" #include "src/objects/contexts-inl.h" #include "src/objects/fixed-array-inl.h" #include "src/objects/objects-inl.h" @@ -18,38 +17,9 @@ namespace v8 { namespace internal { -OBJECT_CONSTRUCTORS_IMPL(SloppyArgumentsElements, FixedArray) TQ_OBJECT_CONSTRUCTORS_IMPL(JSArgumentsObject) TQ_OBJECT_CONSTRUCTORS_IMPL(AliasedArgumentsEntry) -CAST_ACCESSOR(SloppyArgumentsElements) - -DEF_GETTER(SloppyArgumentsElements, context, Context) { - return TaggedField<Context>::load(isolate, *this, - OffsetOfElementAt(kContextIndex)); -} - -DEF_GETTER(SloppyArgumentsElements, arguments, FixedArray) { - return TaggedField<FixedArray>::load(isolate, *this, - OffsetOfElementAt(kArgumentsIndex)); -} - -void SloppyArgumentsElements::set_arguments(FixedArray arguments) { - set(kArgumentsIndex, arguments); -} - -uint32_t SloppyArgumentsElements::parameter_map_length() { - return length() - kParameterMapStart; -} - -Object SloppyArgumentsElements::get_mapped_entry(uint32_t entry) { - return get(entry + kParameterMapStart); -} - -void SloppyArgumentsElements::set_mapped_entry(uint32_t entry, Object object) { - set(entry + kParameterMapStart, object); -} - } // namespace internal } // namespace v8 diff --git a/chromium/v8/src/objects/arguments.h b/chromium/v8/src/objects/arguments.h index ed2d31d1dd4..41eaaed1a17 100644 --- a/chromium/v8/src/objects/arguments.h +++ b/chromium/v8/src/objects/arguments.h @@ -58,49 +58,6 @@ class JSStrictArgumentsObject : public JSArgumentsObject { DISALLOW_IMPLICIT_CONSTRUCTORS(JSStrictArgumentsObject); }; -// Helper class to access FAST_ and SLOW_SLOPPY_ARGUMENTS_ELEMENTS -// -// +---+-----------------------+ -// | 0 | Context context | -// +---------------------------+ -// | 1 | FixedArray arguments +----+ HOLEY_ELEMENTS -// +---------------------------+ v-----+-----------+ -// | 2 | Object param_1_map | | 0 | the_hole | -// |...| ... | | ... | ... | -// |n+1| Object param_n_map | | n-1 | the_hole | -// +---------------------------+ | n | element_1 | -// | ... | ... | -// |n+m-1| element_m | -// +-----------------+ -// -// Parameter maps give the index into the provided context. If a map entry is -// the_hole it means that the given entry has been deleted from the arguments -// object. -// The arguments backing store kind depends on the ElementsKind of the outer -// JSArgumentsObject: -// - FAST_SLOPPY_ARGUMENTS_ELEMENTS: HOLEY_ELEMENTS -// - SLOW_SLOPPY_ARGUMENTS_ELEMENTS: DICTIONARY_ELEMENTS -class SloppyArgumentsElements : public FixedArray { - public: - static const int kContextIndex = 0; - static const int kArgumentsIndex = 1; - static const uint32_t kParameterMapStart = 2; - - DECL_GETTER(context, Context) - DECL_GETTER(arguments, FixedArray) - inline void set_arguments(FixedArray arguments); - inline uint32_t parameter_map_length(); - inline Object get_mapped_entry(uint32_t entry); - inline void set_mapped_entry(uint32_t entry, Object object); - - DECL_CAST(SloppyArgumentsElements) -#ifdef VERIFY_HEAP - void SloppyArgumentsElementsVerify(Isolate* isolate, JSObject holder); -#endif - - OBJECT_CONSTRUCTORS(SloppyArgumentsElements, FixedArray); -}; - // Representation of a slow alias as part of a sloppy arguments objects. // For fast aliases (if HasSloppyArgumentsElements()): // - the parameter map contains an index into the context diff --git a/chromium/v8/src/objects/arguments.tq b/chromium/v8/src/objects/arguments.tq index 5211707eae9..e1637056f7f 100644 --- a/chromium/v8/src/objects/arguments.tq +++ b/chromium/v8/src/objects/arguments.tq @@ -26,7 +26,69 @@ extern shape JSStrictArgumentsObject extends JSArgumentsObject { length: JSAny; } -type SloppyArgumentsElements extends FixedArray; +// Helper class to access FAST_ and SLOW_SLOPPY_ARGUMENTS_ELEMENTS, dividing +// arguments into two types for a given SloppyArgumentsElements object: +// mapped and unmapped. +// +// For clarity SloppyArgumentsElements fields are qualified with "elements." +// below. +// +// Mapped arguments are actual arguments. Unmapped arguments are values added +// to the arguments object after it was created for the call. Mapped arguments +// are stored in the context at indexes given by elements.mapped_entries[key]. +// Unmapped arguments are stored as regular indexed properties in the arguments +// array which can be accessed from elements.arguments. +// +// elements.length is min(number_of_actual_arguments, +// number_of_formal_arguments) for a concrete call to a function. +// +// Once a SloppyArgumentsElements is generated, lookup of an argument with index +// |key| in |elements| works as follows: +// +// If key >= elements.length then attempt to look in the unmapped arguments +// array and return the value at key, missing to the runtime if the unmapped +// arguments array is not a fixed array or if key >= elements.arguments.length. +// +// Otherwise, t = elements.mapped_entries[key]. If t is the hole, then the +// entry has been deleted fron the arguments object, and value is looked up in +// the unmapped arguments array, as described above. Otherwise, t is a Smi +// index into the context array specified at elements.context, and the return +// value is elements.context[t]. +// +// A graphic representation of a SloppyArgumentsElements object and a +// corresponding unmapped arguments FixedArray: +// +// SloppyArgumentsElements +// +---+-----------------------+ +// | Context context | +// +---------------------------+ +// | FixedArray arguments +----+ HOLEY_ELEMENTS +// +---------------------------+ v-----+-----------+ +// | 0 | Object mapped_entries | | 0 | the_hole | +// |...| ... | | ... | ... | +// |n-1| Object mapped_entries | | n-1 | the_hole | +// +---------------------------+ | n | element_1 | +// | ... | ... | +// |n+m-1| element_m | +// +-----------------+ +// +// The elements.arguments backing store kind depends on the ElementsKind of +// the outer JSArgumentsObject: +// - FAST_SLOPPY_ARGUMENTS_ELEMENTS: HOLEY_ELEMENTS +// - SLOW_SLOPPY_ARGUMENTS_ELEMENTS: DICTIONARY_ELEMENTS +@export +class SloppyArgumentsElements extends FixedArrayBase { + context: Context; + arguments: FixedArray; + mapped_entries[length]: Smi|TheHole; +} + +macro NewSloppyArgumentsElements<Iterator: type>( + length: Smi, context: Context, arguments: FixedArray, + it: Iterator): SloppyArgumentsElements { + return new + SloppyArgumentsElements{length, context, arguments, mapped_entries: ...it}; +} @generateCppClass @generatePrint @@ -49,7 +111,7 @@ macro NewJSStrictArgumentsObject(implicit context: Context)( } macro NewJSSloppyArgumentsObject(implicit context: Context)( - elements: FixedArray, callee: JSFunction): JSSloppyArgumentsObject { + elements: FixedArrayBase, callee: JSFunction): JSSloppyArgumentsObject { const map = GetSloppyArgumentsMap(); return new JSSloppyArgumentsObject{ map, @@ -61,7 +123,7 @@ macro NewJSSloppyArgumentsObject(implicit context: Context)( } macro NewJSFastAliasedArgumentsObject(implicit context: Context)( - elements: FixedArray, length: Smi, + elements: FixedArrayBase, length: Smi, callee: JSFunction): JSSloppyArgumentsObject { // TODO(danno): FastAliasedArguments should really be a type for itself const map = GetFastAliasedArgumentsMap(); @@ -75,28 +137,17 @@ macro NewJSFastAliasedArgumentsObject(implicit context: Context)( } struct ParameterMapIterator { - macro Next(): Object labels NoMore { - const currentMapSlotCopy = this.currentMapSlot++; - if (currentMapSlotCopy > 1) { - if (this.currentIndex == this.endInterationIndex) goto NoMore; - this.currentIndex--; - return Convert<Smi>(this.currentIndex); - } else if (currentMapSlotCopy == 0) { - return this.context; - } else { - assert(currentMapSlotCopy == 1); - return this.elements; - } + macro Next(): Smi labels NoMore { + if (this.currentIndex == this.endInterationIndex) goto NoMore; + this.currentIndex--; + return Convert<Smi>(this.currentIndex); } - const context: Context; - const elements: FixedArray; currentIndex: intptr; const endInterationIndex: intptr; - currentMapSlot: intptr; } macro NewParameterMapIterator( - context: Context, elements: FixedArray, formalParameterCount: intptr, + context: Context, formalParameterCount: intptr, mappedCount: intptr): ParameterMapIterator { const flags = context.scope_info.flags; let contextHeaderSize: intptr = MIN_CONTEXT_SLOTS; @@ -112,11 +163,8 @@ macro NewParameterMapIterator( const afterLastContextIndex = contextHeaderSize + formalParameterCount; const firstContextIndex = afterLastContextIndex - mappedCount; return ParameterMapIterator{ - context, - elements, currentIndex: afterLastContextIndex, - endInterationIndex: firstContextIndex, - currentMapSlot: 0 + endInterationIndex: firstContextIndex }; } @@ -188,17 +236,16 @@ macro NewSloppyArguments(implicit context: Context)( const mappedCount = IntPtrMin(formalParameterCount, argumentCount); const it = NewParameterValueIterator(mappedCount, arguments); const parameterValues = NewFixedArray(argumentCount, it); - let paramIter = NewParameterMapIterator( - context, parameterValues, formalParameterCount, mappedCount); - const elementsLength = - Convert<Smi>(mappedCount + kSloppyArgumentsParameterMapStart); - const map = kSloppyArgumentsElementsMap; - const elements = new - FixedArray{map, length: elementsLength, objects: ...paramIter}; + let paramIter = + NewParameterMapIterator(context, formalParameterCount, mappedCount); + const elementsLength = Convert<Smi>(mappedCount); + const elements = NewSloppyArgumentsElements( + elementsLength, context, parameterValues, paramIter); const length = Convert<Smi>(argumentCount); return NewJSFastAliasedArgumentsObject(elements, length, callee); } -} + +} // namespace arguments @export macro EmitFastNewAllArguments(implicit context: Context)( diff --git a/chromium/v8/src/objects/backing-store.cc b/chromium/v8/src/objects/backing-store.cc index bd9f39b7d3a..0913d829937 100644 --- a/chromium/v8/src/objects/backing-store.cc +++ b/chromium/v8/src/objects/backing-store.cc @@ -428,10 +428,20 @@ std::unique_ptr<BackingStore> BackingStore::AllocateWasmMemory( auto backing_store = TryAllocateWasmMemory(isolate, initial_pages, maximum_pages, shared); - if (!backing_store && maximum_pages > initial_pages) { - // If reserving {maximum_pages} failed, try with maximum = initial. + if (maximum_pages == initial_pages) { + // If initial pages, and maximum are equal, nothing more to do return early. + return backing_store; + } + + // Retry with smaller maximum pages at each retry. + const int kAllocationTries = 3; + auto delta = (maximum_pages - initial_pages) / (kAllocationTries + 1); + size_t sizes[] = {maximum_pages - delta, maximum_pages - 2 * delta, + maximum_pages - 3 * delta, initial_pages}; + + for (size_t i = 0; i < arraysize(sizes) && !backing_store; i++) { backing_store = - TryAllocateWasmMemory(isolate, initial_pages, initial_pages, shared); + TryAllocateWasmMemory(isolate, initial_pages, sizes[i], shared); } return backing_store; } @@ -646,7 +656,7 @@ SharedWasmMemoryData* BackingStore::get_shared_wasm_memory_data() { namespace { // Implementation details of GlobalBackingStoreRegistry. struct GlobalBackingStoreRegistryImpl { - GlobalBackingStoreRegistryImpl() {} + GlobalBackingStoreRegistryImpl() = default; base::Mutex mutex_; std::unordered_map<const void*, std::weak_ptr<BackingStore>> map_; }; diff --git a/chromium/v8/src/objects/bigint.cc b/chromium/v8/src/objects/bigint.cc index dfc302e77c8..2f8337db979 100644 --- a/chromium/v8/src/objects/bigint.cc +++ b/chromium/v8/src/objects/bigint.cc @@ -1125,7 +1125,7 @@ double MutableBigInt::ToDouble(Handle<BigIntBase> x) { return bit_cast<double>(double_bits); } -// This is its own function to keep control flow sane. The meaning of the +// This is its own function to simplify control flow. The meaning of the // parameters is defined by {ToDouble}'s local variable usage. MutableBigInt::Rounding MutableBigInt::DecideRounding(Handle<BigIntBase> x, int mantissa_bits_unset, diff --git a/chromium/v8/src/objects/class-definitions-tq-deps-inl.h b/chromium/v8/src/objects/class-definitions-tq-deps-inl.h index de81ccfeb6a..dafba941ea4 100644 --- a/chromium/v8/src/objects/class-definitions-tq-deps-inl.h +++ b/chromium/v8/src/objects/class-definitions-tq-deps-inl.h @@ -12,7 +12,6 @@ #include "src/objects/arguments-inl.h" #include "src/objects/embedder-data-array-inl.h" #include "src/objects/free-space-inl.h" -#include "src/objects/js-aggregate-error-inl.h" #include "src/objects/js-collection-inl.h" #include "src/objects/js-generator-inl.h" #include "src/objects/js-regexp-inl.h" diff --git a/chromium/v8/src/objects/code.cc b/chromium/v8/src/objects/code.cc index 2e8f808262e..cb95761d2d8 100644 --- a/chromium/v8/src/objects/code.cc +++ b/chromium/v8/src/objects/code.cc @@ -239,7 +239,8 @@ const char* AbstractCode::Kind2String(Kind kind) { bool Code::IsIsolateIndependent(Isolate* isolate) { constexpr int all_real_modes_mask = - (1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - 1; + (1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - + (1 << (RelocInfo::FIRST_REAL_RELOC_MODE - 1)) - 1; constexpr int mode_mask = all_real_modes_mask & ~RelocInfo::ModeMask(RelocInfo::CONST_POOL) & ~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) & diff --git a/chromium/v8/src/objects/compilation-cache.h b/chromium/v8/src/objects/compilation-cache.h index dd507f3c2d9..0074fc7b147 100644 --- a/chromium/v8/src/objects/compilation-cache.h +++ b/chromium/v8/src/objects/compilation-cache.h @@ -42,7 +42,7 @@ class CompilationCacheShape : public BaseShape<HashTableKey*> { class InfoCellPair { public: - InfoCellPair() {} + InfoCellPair() = default; inline InfoCellPair(SharedFunctionInfo shared, FeedbackCell feedback_cell); FeedbackCell feedback_cell() const { diff --git a/chromium/v8/src/objects/contexts.cc b/chromium/v8/src/objects/contexts.cc index 686a3c689ef..76c52b27135 100644 --- a/chromium/v8/src/objects/contexts.cc +++ b/chromium/v8/src/objects/contexts.cc @@ -159,13 +159,13 @@ static Maybe<bool> UnscopableLookup(LookupIterator* it, bool is_with_context) { isolate->factory()->unscopables_symbol()), Nothing<bool>()); if (!unscopables->IsJSReceiver()) return Just(true); - Handle<Object> blacklist; + Handle<Object> blocklist; ASSIGN_RETURN_ON_EXCEPTION_VALUE( - isolate, blacklist, + isolate, blocklist, JSReceiver::GetProperty(isolate, Handle<JSReceiver>::cast(unscopables), it->name()), Nothing<bool>()); - return Just(!blacklist->BooleanValue(isolate)); + return Just(!blocklist->BooleanValue(isolate)); } static PropertyAttributes GetAttributesForMode(VariableMode mode) { @@ -377,12 +377,12 @@ Handle<Object> Context::Lookup(Handle<Context> context, Handle<String> name, } } - // Check blacklist. Names that are listed, cannot be resolved further. - Object blacklist = context->get(BLACK_LIST_INDEX); - if (blacklist.IsStringSet() && - StringSet::cast(blacklist).Has(isolate, name)) { + // Check blocklist. Names that are listed, cannot be resolved further. + Object blocklist = context->get(BLOCK_LIST_INDEX); + if (blocklist.IsStringSet() && + StringSet::cast(blocklist).Has(isolate, name)) { if (FLAG_trace_contexts) { - PrintF(" - name is blacklisted. Aborting.\n"); + PrintF(" - name is blocklisted. Aborting.\n"); } break; } diff --git a/chromium/v8/src/objects/contexts.h b/chromium/v8/src/objects/contexts.h index 06f742281ad..d6386f3c49f 100644 --- a/chromium/v8/src/objects/contexts.h +++ b/chromium/v8/src/objects/contexts.h @@ -309,6 +309,7 @@ enum ContextLookupFlags { V(OBJECT_TO_STRING, JSFunction, object_to_string) \ V(OBJECT_VALUE_OF_FUNCTION_INDEX, JSFunction, object_value_of_function) \ V(PROMISE_ALL_INDEX, JSFunction, promise_all) \ + V(PROMISE_ANY_INDEX, JSFunction, promise_any) \ V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \ V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \ V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \ @@ -508,7 +509,7 @@ class Context : public HeapObject { // These slots hold values in debug evaluate contexts. WRAPPED_CONTEXT_INDEX = MIN_CONTEXT_EXTENDED_SLOTS, - BLACK_LIST_INDEX = MIN_CONTEXT_EXTENDED_SLOTS + 1 + BLOCK_LIST_INDEX = MIN_CONTEXT_EXTENDED_SLOTS + 1 }; static const int kExtensionSize = diff --git a/chromium/v8/src/objects/contexts.tq b/chromium/v8/src/objects/contexts.tq index bae4fd60df9..1b0ae080c3e 100644 --- a/chromium/v8/src/objects/contexts.tq +++ b/chromium/v8/src/objects/contexts.tq @@ -36,11 +36,13 @@ extern enum NativeContextSlot extends intptr constexpr 'Context::Field' { JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX, MATH_RANDOM_CACHE_INDEX, MATH_RANDOM_INDEX_INDEX, + NUMBER_FUNCTION_INDEX, PROXY_REVOCABLE_RESULT_MAP_INDEX, REFLECT_APPLY_INDEX, REGEXP_FUNCTION_INDEX, REGEXP_LAST_MATCH_INFO_INDEX, INITIAL_STRING_ITERATOR_MAP_INDEX, + INITIAL_ARRAY_ITERATOR_MAP_INDEX, SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP, STRICT_ARGUMENTS_MAP_INDEX, SLOPPY_ARGUMENTS_MAP_INDEX, @@ -52,6 +54,9 @@ extern enum NativeContextSlot extends intptr constexpr 'Context::Field' { STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX, + + BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX, + BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX, ... } diff --git a/chromium/v8/src/objects/debug-objects.cc b/chromium/v8/src/objects/debug-objects.cc index 48dc2d5b8d4..839bc097d13 100644 --- a/chromium/v8/src/objects/debug-objects.cc +++ b/chromium/v8/src/objects/debug-objects.cc @@ -274,10 +274,13 @@ void BreakPointInfo::SetBreakPoint(Isolate* isolate, break_point_info->set_break_points(*break_point); return; } - // If the break point object is the same as before just ignore. - if (break_point_info->break_points() == *break_point) return; // If there was one break point object before replace with array. if (!break_point_info->break_points().IsFixedArray()) { + if (IsEqual(BreakPoint::cast(break_point_info->break_points()), + *break_point)) { + return; + } + Handle<FixedArray> array = isolate->factory()->NewFixedArray(2); array->set(0, break_point_info->break_points()); array->set(1, *break_point); diff --git a/chromium/v8/src/objects/debug-objects.h b/chromium/v8/src/objects/debug-objects.h index 415f456b1b4..22eea25481b 100644 --- a/chromium/v8/src/objects/debug-objects.h +++ b/chromium/v8/src/objects/debug-objects.h @@ -28,7 +28,6 @@ class DebugInfo : public TorqueGeneratedDebugInfo<DebugInfo, Struct> { public: NEVER_READ_ONLY_SPACE DEFINE_TORQUE_GENERATED_DEBUG_INFO_FLAGS() - using Flags = base::Flags<Flag>; // DebugInfo can be detached from the SharedFunctionInfo iff it is empty. bool IsEmpty() const; diff --git a/chromium/v8/src/objects/debug-objects.tq b/chromium/v8/src/objects/debug-objects.tq index 8544e793664..ee8201e615c 100644 --- a/chromium/v8/src/objects/debug-objects.tq +++ b/chromium/v8/src/objects/debug-objects.tq @@ -74,11 +74,13 @@ extern class CoverageInfo extends HeapObject { @generateCppClass @generatePrint extern class WasmValue extends Struct { + // TODO(7748): Name and comment are outdated. // The type, should map to ValueType::Kind values in value-type.h. value_type: SmiTagged<WasmValueType>; // Holds the actual value. For example, if this holds a Wasm i32, this will // be of length 4, for s128, it will have length 16. These values are // represented by the respective C++ types, and memcpy-ed in. - // When value_type is a anyref, it holds the object that anyref points to. + // When value_type is a externref, it holds the object that externref points + // to. bytes_or_ref: Object|ByteArray; } diff --git a/chromium/v8/src/objects/descriptor-array-inl.h b/chromium/v8/src/objects/descriptor-array-inl.h index 357a6732e22..d9e3408dd96 100644 --- a/chromium/v8/src/objects/descriptor-array-inl.h +++ b/chromium/v8/src/objects/descriptor-array-inl.h @@ -55,17 +55,19 @@ void DescriptorArray::CopyEnumCacheFrom(DescriptorArray array) { set_enum_cache(array.enum_cache()); } -InternalIndex DescriptorArray::Search(Name name, int valid_descriptors) { +InternalIndex DescriptorArray::Search(Name name, int valid_descriptors, + bool concurrent_search) { DCHECK(name.IsUniqueName()); - return InternalIndex( - internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, nullptr)); + return InternalIndex(internal::Search<VALID_ENTRIES>( + this, name, valid_descriptors, nullptr, concurrent_search)); } -InternalIndex DescriptorArray::Search(Name name, Map map) { +InternalIndex DescriptorArray::Search(Name name, Map map, + bool concurrent_search) { DCHECK(name.IsUniqueName()); int number_of_own_descriptors = map.NumberOfOwnDescriptors(); if (number_of_own_descriptors == 0) return InternalIndex::NotFound(); - return Search(name, number_of_own_descriptors); + return Search(name, number_of_own_descriptors, concurrent_search); } InternalIndex DescriptorArray::SearchWithCache(Isolate* isolate, Name name, diff --git a/chromium/v8/src/objects/descriptor-array.h b/chromium/v8/src/objects/descriptor-array.h index 61da8dc240c..f6894819290 100644 --- a/chromium/v8/src/objects/descriptor-array.h +++ b/chromium/v8/src/objects/descriptor-array.h @@ -115,9 +115,13 @@ class DescriptorArray // Sort the instance descriptors by the hash codes of their keys. void Sort(); - // Search the instance descriptors for given name. - V8_INLINE InternalIndex Search(Name name, int number_of_own_descriptors); - V8_INLINE InternalIndex Search(Name name, Map map); + // Search the instance descriptors for given name. {concurrent_search} signals + // if we are doing the search on a background thread. If so, we will sacrifice + // speed for thread-safety. + V8_INLINE InternalIndex Search(Name name, int number_of_own_descriptors, + bool concurrent_search = false); + V8_INLINE InternalIndex Search(Name name, Map map, + bool concurrent_search = false); // As the above, but uses DescriptorLookupCache and updates it when // necessary. @@ -189,7 +193,7 @@ class DescriptorArray #ifdef DEBUG // Is the descriptor array sorted and without duplicates? - V8_EXPORT_PRIVATE bool IsSortedNoDuplicates(int valid_descriptors = -1); + V8_EXPORT_PRIVATE bool IsSortedNoDuplicates(); // Are two DescriptorArrays equal? bool IsEqualTo(DescriptorArray other); diff --git a/chromium/v8/src/objects/elements.cc b/chromium/v8/src/objects/elements.cc index d0c680d287d..7994c12ec1a 100644 --- a/chromium/v8/src/objects/elements.cc +++ b/chromium/v8/src/objects/elements.cc @@ -22,6 +22,8 @@ #include "src/objects/slots-atomic-inl.h" #include "src/objects/slots.h" #include "src/utils/utils.h" +#include "torque-generated/exported-class-definitions-tq-inl.h" +#include "torque-generated/exported-class-definitions-tq.h" // Each concrete ElementsAccessor can handle exactly one ElementsKind, // several abstract ElementsAccessor classes are used to allow sharing @@ -443,6 +445,8 @@ void CopyDictionaryToDoubleElements(Isolate* isolate, FixedArrayBase from_base, void SortIndices(Isolate* isolate, Handle<FixedArray> indices, uint32_t sort_size) { + if (sort_size == 0) return; + // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and // store operations that are safe for concurrent marking. AtomicSlot start(indices->GetFirstElementAddress()); @@ -3882,11 +3886,11 @@ class SloppyArgumentsElementsAccessor InternalIndex entry) { Handle<SloppyArgumentsElements> elements( SloppyArgumentsElements::cast(parameters), isolate); - uint32_t length = elements->parameter_map_length(); + uint32_t length = elements->length(); if (entry.as_uint32() < length) { // Read context mapped entry. DisallowHeapAllocation no_gc; - Object probe = elements->get_mapped_entry(entry.as_uint32()); + Object probe = elements->mapped_entries(entry.as_uint32()); DCHECK(!probe.IsTheHole(isolate)); Context context = elements->context(); int context_entry = Smi::ToInt(probe); @@ -3918,13 +3922,13 @@ class SloppyArgumentsElementsAccessor static inline void SetImpl(FixedArrayBase store, InternalIndex entry, Object value) { SloppyArgumentsElements elements = SloppyArgumentsElements::cast(store); - uint32_t length = elements.parameter_map_length(); + uint32_t length = elements.length(); if (entry.as_uint32() < length) { // Store context mapped entry. DisallowHeapAllocation no_gc; - Object probe = elements.get_mapped_entry(entry.as_uint32()); + Object probe = elements.mapped_entries(entry.as_uint32()); DCHECK(!probe.IsTheHole()); - Context context = elements.context(); + Context context = Context::cast(elements.context()); int context_entry = Smi::ToInt(probe); DCHECK(!context.get(context_entry).IsTheHole()); context.set(context_entry, value); @@ -3935,7 +3939,7 @@ class SloppyArgumentsElementsAccessor ArgumentsAccessor::GetRaw(arguments, entry.adjust_down(length)); if (current.IsAliasedArgumentsEntry()) { AliasedArgumentsEntry alias = AliasedArgumentsEntry::cast(current); - Context context = elements.context(); + Context context = Context::cast(elements.context()); int context_entry = alias.aliased_context_slot(); DCHECK(!context.get(context_entry).IsTheHole()); context.set(context_entry, value); @@ -3955,7 +3959,7 @@ class SloppyArgumentsElementsAccessor static uint32_t GetCapacityImpl(JSObject holder, FixedArrayBase store) { SloppyArgumentsElements elements = SloppyArgumentsElements::cast(store); FixedArray arguments = elements.arguments(); - return elements.parameter_map_length() + + return elements.length() + ArgumentsAccessor::GetCapacityImpl(holder, arguments); } @@ -3967,7 +3971,7 @@ class SloppyArgumentsElementsAccessor size_t max_entries = ArgumentsAccessor::GetMaxNumberOfEntries(holder, arguments); DCHECK_LE(max_entries, std::numeric_limits<uint32_t>::max()); - return elements.parameter_map_length() + static_cast<uint32_t>(max_entries); + return elements.length() + static_cast<uint32_t>(max_entries); } static uint32_t NumberOfElementsImpl(JSObject receiver, @@ -3977,7 +3981,7 @@ class SloppyArgumentsElementsAccessor SloppyArgumentsElements::cast(backing_store); FixedArrayBase arguments = elements.arguments(); uint32_t nof_elements = 0; - uint32_t length = elements.parameter_map_length(); + uint32_t length = elements.length(); for (uint32_t index = 0; index < length; index++) { if (HasParameterMapArg(isolate, elements, index)) nof_elements++; } @@ -4004,7 +4008,7 @@ class SloppyArgumentsElementsAccessor InternalIndex entry) { SloppyArgumentsElements elements = SloppyArgumentsElements::cast(parameters); - uint32_t length = elements.parameter_map_length(); + uint32_t length = elements.length(); if (entry.raw_value() < length) { return HasParameterMapArg(isolate, elements, entry.raw_value()); } @@ -4035,13 +4039,13 @@ class SloppyArgumentsElementsAccessor if (entry.is_not_found()) return entry; // Arguments entries could overlap with the dictionary entries, hence offset // them by the number of context mapped entries. - return entry.adjust_up(elements.parameter_map_length()); + return entry.adjust_up(elements.length()); } static PropertyDetails GetDetailsImpl(JSObject holder, InternalIndex entry) { SloppyArgumentsElements elements = SloppyArgumentsElements::cast(holder.elements()); - uint32_t length = elements.parameter_map_length(); + uint32_t length = elements.length(); if (entry.as_uint32() < length) { return PropertyDetails(kData, NONE, PropertyCellType::kNoCell); } @@ -4053,16 +4057,16 @@ class SloppyArgumentsElementsAccessor static bool HasParameterMapArg(Isolate* isolate, SloppyArgumentsElements elements, size_t index) { - uint32_t length = elements.parameter_map_length(); + uint32_t length = elements.length(); if (index >= length) return false; - return !elements.get_mapped_entry(static_cast<uint32_t>(index)) + return !elements.mapped_entries(static_cast<uint32_t>(index)) .IsTheHole(isolate); } static void DeleteImpl(Handle<JSObject> obj, InternalIndex entry) { Handle<SloppyArgumentsElements> elements( SloppyArgumentsElements::cast(obj->elements()), obj->GetIsolate()); - uint32_t length = elements->parameter_map_length(); + uint32_t length = elements->length(); InternalIndex delete_or_entry = entry; if (entry.as_uint32() < length) { delete_or_entry = InternalIndex::NotFound(); @@ -4071,8 +4075,8 @@ class SloppyArgumentsElementsAccessor // SloppyDeleteImpl allocates a new dictionary elements store. For making // heap verification happy we postpone clearing out the mapped entry. if (entry.as_uint32() < length) { - elements->set_mapped_entry(entry.as_uint32(), - obj->GetReadOnlyRoots().the_hole_value()); + elements->set_mapped_entries(entry.as_uint32(), + obj->GetReadOnlyRoots().the_hole_value()); } } @@ -4107,10 +4111,10 @@ class SloppyArgumentsElementsAccessor uint32_t insertion_index = 0) { Handle<SloppyArgumentsElements> elements = Handle<SloppyArgumentsElements>::cast(backing_store); - uint32_t length = elements->parameter_map_length(); + uint32_t length = elements->length(); for (uint32_t i = 0; i < length; ++i) { - if (elements->get_mapped_entry(i).IsTheHole(isolate)) continue; + if (elements->mapped_entries(i).IsTheHole(isolate)) continue; if (convert == GetKeysConversion::kConvertToString) { Handle<String> index_string = isolate->factory()->Uint32ToString(i); list->set(insertion_index, *index_string); @@ -4238,7 +4242,7 @@ class SlowSloppyArgumentsElementsAccessor Isolate* isolate = obj->GetIsolate(); Handle<NumberDictionary> dict(NumberDictionary::cast(elements->arguments()), isolate); - uint32_t length = elements->parameter_map_length(); + uint32_t length = elements->length(); dict = NumberDictionary::DeleteEntry(isolate, dict, entry.adjust_down(length)); elements->set_arguments(*dict); @@ -4271,9 +4275,9 @@ class SlowSloppyArgumentsElementsAccessor Isolate* isolate = object->GetIsolate(); Handle<SloppyArgumentsElements> elements = Handle<SloppyArgumentsElements>::cast(store); - uint32_t length = elements->parameter_map_length(); + uint32_t length = elements->length(); if (entry.as_uint32() < length) { - Object probe = elements->get_mapped_entry(entry.as_uint32()); + Object probe = elements->mapped_entries(entry.as_uint32()); DCHECK(!probe.IsTheHole(isolate)); Context context = elements->context(); int context_entry = Smi::ToInt(probe); @@ -4281,8 +4285,8 @@ class SlowSloppyArgumentsElementsAccessor context.set(context_entry, *value); // Redefining attributes of an aliased element destroys fast aliasing. - elements->set_mapped_entry(entry.as_uint32(), - ReadOnlyRoots(isolate).the_hole_value()); + elements->set_mapped_entries(entry.as_uint32(), + ReadOnlyRoots(isolate).the_hole_value()); // For elements that are still writable we re-establish slow aliasing. if ((attributes & READ_ONLY) == 0) { value = isolate->factory()->NewAliasedArgumentsEntry(context_entry); @@ -4339,7 +4343,7 @@ class FastSloppyArgumentsElementsAccessor // kMaxUInt32 indicates that a context mapped element got deleted. In this // case we only normalize the elements (aka. migrate to SLOW_SLOPPY). if (entry->is_not_found()) return dictionary; - uint32_t length = elements->parameter_map_length(); + uint32_t length = elements->length(); if (entry->as_uint32() >= length) { *entry = dictionary diff --git a/chromium/v8/src/objects/feedback-vector-inl.h b/chromium/v8/src/objects/feedback-vector-inl.h index 72b6e14883a..42c2fa51530 100644 --- a/chromium/v8/src/objects/feedback-vector-inl.h +++ b/chromium/v8/src/objects/feedback-vector-inl.h @@ -233,32 +233,47 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) { } // Helper function to transform the feedback to CompareOperationHint. +template <CompareOperationFeedback::Type Feedback> +bool Is(int type_feedback) { + return !(type_feedback & ~Feedback); +} + CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) { - switch (type_feedback) { - case CompareOperationFeedback::kNone: - return CompareOperationHint::kNone; - case CompareOperationFeedback::kSignedSmall: - return CompareOperationHint::kSignedSmall; - case CompareOperationFeedback::kNumber: - return CompareOperationHint::kNumber; - case CompareOperationFeedback::kNumberOrOddball: - return CompareOperationHint::kNumberOrOddball; - case CompareOperationFeedback::kInternalizedString: - return CompareOperationHint::kInternalizedString; - case CompareOperationFeedback::kString: - return CompareOperationHint::kString; - case CompareOperationFeedback::kSymbol: - return CompareOperationHint::kSymbol; - case CompareOperationFeedback::kBigInt: - return CompareOperationHint::kBigInt; - case CompareOperationFeedback::kReceiver: - return CompareOperationHint::kReceiver; - case CompareOperationFeedback::kReceiverOrNullOrUndefined: - return CompareOperationHint::kReceiverOrNullOrUndefined; - default: - return CompareOperationHint::kAny; + if (Is<CompareOperationFeedback::kNone>(type_feedback)) { + return CompareOperationHint::kNone; } - UNREACHABLE(); + + if (Is<CompareOperationFeedback::kSignedSmall>(type_feedback)) { + return CompareOperationHint::kSignedSmall; + } else if (Is<CompareOperationFeedback::kNumber>(type_feedback)) { + return CompareOperationHint::kNumber; + } else if (Is<CompareOperationFeedback::kNumberOrBoolean>(type_feedback)) { + return CompareOperationHint::kNumberOrBoolean; + } + + if (Is<CompareOperationFeedback::kInternalizedString>(type_feedback)) { + return CompareOperationHint::kInternalizedString; + } else if (Is<CompareOperationFeedback::kString>(type_feedback)) { + return CompareOperationHint::kString; + } + + if (Is<CompareOperationFeedback::kReceiver>(type_feedback)) { + return CompareOperationHint::kReceiver; + } else if (Is<CompareOperationFeedback::kReceiverOrNullOrUndefined>( + type_feedback)) { + return CompareOperationHint::kReceiverOrNullOrUndefined; + } + + if (Is<CompareOperationFeedback::kBigInt>(type_feedback)) { + return CompareOperationHint::kBigInt; + } + + if (Is<CompareOperationFeedback::kSymbol>(type_feedback)) { + return CompareOperationHint::kSymbol; + } + + DCHECK(Is<CompareOperationFeedback::kAny>(type_feedback)); + return CompareOperationHint::kAny; } // Helper function to transform the feedback to ForInHint. diff --git a/chromium/v8/src/objects/feedback-vector.cc b/chromium/v8/src/objects/feedback-vector.cc index dc4581f40ee..ce638b23399 100644 --- a/chromium/v8/src/objects/feedback-vector.cc +++ b/chromium/v8/src/objects/feedback-vector.cc @@ -235,10 +235,14 @@ Handle<ClosureFeedbackCellArray> ClosureFeedbackCellArray::New( // static Handle<FeedbackVector> FeedbackVector::New( Isolate* isolate, Handle<SharedFunctionInfo> shared, - Handle<ClosureFeedbackCellArray> closure_feedback_cell_array) { + Handle<ClosureFeedbackCellArray> closure_feedback_cell_array, + IsCompiledScope* is_compiled_scope) { + DCHECK(is_compiled_scope->is_compiled()); Factory* factory = isolate->factory(); - const int slot_count = shared->feedback_metadata().slot_count(); + Handle<FeedbackMetadata> feedback_metadata(shared->feedback_metadata(), + isolate); + const int slot_count = feedback_metadata->slot_count(); Handle<FeedbackVector> vector = factory->NewFeedbackVector(shared, closure_feedback_cell_array); @@ -260,7 +264,7 @@ Handle<FeedbackVector> FeedbackVector::New( *uninitialized_sentinel); for (int i = 0; i < slot_count;) { FeedbackSlot slot(i); - FeedbackSlotKind kind = shared->feedback_metadata().GetKind(slot); + FeedbackSlotKind kind = feedback_metadata->GetKind(slot); int index = FeedbackVector::GetIndex(slot); int entry_size = FeedbackMetadata::GetSlotSize(kind); @@ -320,6 +324,43 @@ Handle<FeedbackVector> FeedbackVector::New( return result; } +namespace { + +Handle<FeedbackVector> NewFeedbackVectorForTesting( + Isolate* isolate, const FeedbackVectorSpec* spec) { + Handle<FeedbackMetadata> metadata = FeedbackMetadata::New(isolate, spec); + Handle<SharedFunctionInfo> shared = + isolate->factory()->NewSharedFunctionInfoForBuiltin( + isolate->factory()->empty_string(), Builtins::kIllegal); + // Set the raw feedback metadata to circumvent checks that we are not + // overwriting existing metadata. + shared->set_raw_outer_scope_info_or_feedback_metadata(*metadata); + Handle<ClosureFeedbackCellArray> closure_feedback_cell_array = + ClosureFeedbackCellArray::New(isolate, shared); + + IsCompiledScope is_compiled_scope(shared->is_compiled_scope()); + return FeedbackVector::New(isolate, shared, closure_feedback_cell_array, + &is_compiled_scope); +} + +} // namespace + +// static +Handle<FeedbackVector> FeedbackVector::NewWithOneBinarySlotForTesting( + Zone* zone, Isolate* isolate) { + FeedbackVectorSpec one_slot(zone); + one_slot.AddBinaryOpICSlot(); + return NewFeedbackVectorForTesting(isolate, &one_slot); +} + +// static +Handle<FeedbackVector> FeedbackVector::NewWithOneCompareSlotForTesting( + Zone* zone, Isolate* isolate) { + FeedbackVectorSpec one_slot(zone); + one_slot.AddCompareICSlot(); + return NewFeedbackVectorForTesting(isolate, &one_slot); +} + // static void FeedbackVector::AddToVectorsForProfilingTools( Isolate* isolate, Handle<FeedbackVector> vector) { diff --git a/chromium/v8/src/objects/feedback-vector.h b/chromium/v8/src/objects/feedback-vector.h index 24025ad16a4..4789206102a 100644 --- a/chromium/v8/src/objects/feedback-vector.h +++ b/chromium/v8/src/objects/feedback-vector.h @@ -23,6 +23,8 @@ namespace v8 { namespace internal { +class IsCompiledScope; + enum class FeedbackSlotKind { // This kind means that the slot points to the middle of other slot // which occupies more than one feedback vector element. @@ -149,11 +151,9 @@ using MaybeObjectHandles = std::vector<MaybeObjectHandle>; class FeedbackMetadata; // ClosureFeedbackCellArray is a FixedArray that contains feedback cells used -// when creating closures from a function. Along with the feedback -// cells, the first slot (slot 0) is used to hold a budget to measure the -// hotness of the function. This is created once the function is compiled and is -// either held by the feedback vector (if allocated) or by the FeedbackCell of -// the closure. +// when creating closures from a function. This is created once the function is +// compiled and is either held by the feedback vector (if allocated) or by the +// FeedbackCell of the closure. class ClosureFeedbackCellArray : public FixedArray { public: NEVER_READ_ONLY_SPACE @@ -262,7 +262,13 @@ class FeedbackVector : public HeapObject { V8_EXPORT_PRIVATE static Handle<FeedbackVector> New( Isolate* isolate, Handle<SharedFunctionInfo> shared, - Handle<ClosureFeedbackCellArray> closure_feedback_cell_array); + Handle<ClosureFeedbackCellArray> closure_feedback_cell_array, + IsCompiledScope* is_compiled_scope); + + V8_EXPORT_PRIVATE static Handle<FeedbackVector> + NewWithOneBinarySlotForTesting(Zone* zone, Isolate* isolate); + V8_EXPORT_PRIVATE static Handle<FeedbackVector> + NewWithOneCompareSlotForTesting(Zone* zone, Isolate* isolate); #define DEFINE_SLOT_KIND_PREDICATE(Name) \ bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); } diff --git a/chromium/v8/src/objects/fixed-array-inl.h b/chromium/v8/src/objects/fixed-array-inl.h index 174d4abc5b4..a49483ebc64 100644 --- a/chromium/v8/src/objects/fixed-array-inl.h +++ b/chromium/v8/src/objects/fixed-array-inl.h @@ -209,8 +209,13 @@ inline int WeakArrayList::AllocatedSize() { template <SearchMode search_mode, typename T> int BinarySearch(T* array, Name name, int valid_entries, int* out_insertion_index) { - DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr); + DCHECK_IMPLIES(search_mode == VALID_ENTRIES, out_insertion_index == nullptr); int low = 0; + // We have to search on all entries, even when search_mode == VALID_ENTRIES. + // This is because the InternalIndex might be different from the SortedIndex + // (i.e the first added item in {array} could be the last in the sorted + // index). After doing the binary search and getting the correct internal + // index we check to have the index lower than valid_entries, if needed. int high = array->number_of_entries() - 1; uint32_t hash = name.hash_field(); int limit = high; @@ -234,6 +239,11 @@ int BinarySearch(T* array, Name name, int valid_entries, Name entry = array->GetKey(InternalIndex(sort_index)); uint32_t current_hash = entry.hash_field(); if (current_hash != hash) { + // 'search_mode == ALL_ENTRIES' here and below is not needed since + // 'out_insertion_index != nullptr' implies 'search_mode == ALL_ENTRIES'. + // Having said that, when creating the template for <VALID_ENTRIES> these + // ifs can be elided by the C++ compiler if we add 'search_mode == + // ALL_ENTRIES'. if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1); } @@ -284,8 +294,9 @@ int LinearSearch(T* array, Name name, int valid_entries, } template <SearchMode search_mode, typename T> -int Search(T* array, Name name, int valid_entries, int* out_insertion_index) { - SLOW_DCHECK(array->IsSortedNoDuplicates()); +int Search(T* array, Name name, int valid_entries, int* out_insertion_index, + bool concurrent_search) { + SLOW_DCHECK_IMPLIES(!concurrent_search, array->IsSortedNoDuplicates()); if (valid_entries == 0) { if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { @@ -294,14 +305,14 @@ int Search(T* array, Name name, int valid_entries, int* out_insertion_index) { return T::kNotFound; } - // Fast case: do linear search for small arrays. + // Do linear search for small arrays, and for searches in the background + // thread. const int kMaxElementsForLinearSearch = 8; - if (valid_entries <= kMaxElementsForLinearSearch) { + if (valid_entries <= kMaxElementsForLinearSearch || concurrent_search) { return LinearSearch<search_mode>(array, name, valid_entries, out_insertion_index); } - // Slow case: perform binary search. return BinarySearch<search_mode>(array, name, valid_entries, out_insertion_index); } diff --git a/chromium/v8/src/objects/fixed-array.h b/chromium/v8/src/objects/fixed-array.h index 63c3c5360b9..ccb954c6e25 100644 --- a/chromium/v8/src/objects/fixed-array.h +++ b/chromium/v8/src/objects/fixed-array.h @@ -465,7 +465,8 @@ enum SearchMode { ALL_ENTRIES, VALID_ENTRIES }; template <SearchMode search_mode, typename T> inline int Search(T* array, Name name, int valid_entries = 0, - int* out_insertion_index = nullptr); + int* out_insertion_index = nullptr, + bool concurrent_search = false); // ByteArray represents fixed sized byte arrays. Used for the relocation info // that is attached to code objects. diff --git a/chromium/v8/src/objects/fixed-array.tq b/chromium/v8/src/objects/fixed-array.tq index 5c22149ebb8..5e206cb5afe 100644 --- a/chromium/v8/src/objects/fixed-array.tq +++ b/chromium/v8/src/objects/fixed-array.tq @@ -36,11 +36,13 @@ extern class ByteArray extends FixedArrayBase { @hasSameInstanceTypeAsParent @generateCppClass +@doNotGenerateCast extern class ArrayList extends FixedArray { } @hasSameInstanceTypeAsParent @generateCppClass +@doNotGenerateCast extern class TemplateList extends FixedArray { } @@ -101,6 +103,9 @@ operator '[]=' macro StoreFixedArrayDirect(a: FixedArray, i: Smi, v: Object) { a.objects[i] = v; } +extern macro AllocateFixedArray( + constexpr ElementsKind, intptr, constexpr AllocationFlag): FixedArrayBase; + extern macro AllocateZeroedFixedArray(intptr): FixedArray; extern macro AllocateZeroedFixedDoubleArray(intptr): FixedDoubleArray; extern macro CalculateNewElementsCapacity(Smi): Smi; diff --git a/chromium/v8/src/objects/frame-array.h b/chromium/v8/src/objects/frame-array.h index 9ad4fb96a9f..bc4676fc7b8 100644 --- a/chromium/v8/src/objects/frame-array.h +++ b/chromium/v8/src/objects/frame-array.h @@ -52,7 +52,8 @@ class FrameArray : public FixedArray { kIsConstructor = 1 << 3, kAsmJsAtNumberConversion = 1 << 4, kIsAsync = 1 << 5, - kIsPromiseAll = 1 << 6 + kIsPromiseAll = 1 << 6, + kIsPromiseAny = 1 << 7 }; static Handle<FrameArray> AppendJSFrame(Handle<FrameArray> in, diff --git a/chromium/v8/src/objects/heap-object.h b/chromium/v8/src/objects/heap-object.h index b19d429320b..0f8efb5c78f 100644 --- a/chromium/v8/src/objects/heap-object.h +++ b/chromium/v8/src/objects/heap-object.h @@ -191,7 +191,7 @@ class HeapObject : public Object { bool CanBeRehashed() const; // Rehash the object based on the layout inferred from its map. - void RehashBasedOnMap(ReadOnlyRoots root); + void RehashBasedOnMap(LocalIsolateWrapper isolate); // Layout description. #define HEAP_OBJECT_FIELDS(V) \ diff --git a/chromium/v8/src/objects/heap-object.tq b/chromium/v8/src/objects/heap-object.tq index e2f1fe4240e..ca794032f39 100644 --- a/chromium/v8/src/objects/heap-object.tq +++ b/chromium/v8/src/objects/heap-object.tq @@ -3,6 +3,7 @@ // found in the LICENSE file. @abstract +@doNotGenerateCast extern class HeapObject extends StrongTagged { const map: Map; } diff --git a/chromium/v8/src/objects/instance-type-inl.h b/chromium/v8/src/objects/instance-type-inl.h index 45b858209d3..dc41ed6b32d 100644 --- a/chromium/v8/src/objects/instance-type-inl.h +++ b/chromium/v8/src/objects/instance-type-inl.h @@ -30,18 +30,14 @@ struct InstanceRangeChecker { template <InstanceType upper_limit> struct InstanceRangeChecker<FIRST_TYPE, upper_limit> { static constexpr bool Check(InstanceType value) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK_LE(FIRST_TYPE, value); -#endif + CONSTEXPR_DCHECK(FIRST_TYPE <= value); return value <= upper_limit; } }; template <InstanceType lower_limit> struct InstanceRangeChecker<lower_limit, LAST_TYPE> { static constexpr bool Check(InstanceType value) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK_GE(LAST_TYPE, value); -#endif + CONSTEXPR_DCHECK(LAST_TYPE >= value); return value >= lower_limit; } }; diff --git a/chromium/v8/src/objects/instance-type.h b/chromium/v8/src/objects/instance-type.h index 5de264b1de4..077eb307012 100644 --- a/chromium/v8/src/objects/instance-type.h +++ b/chromium/v8/src/objects/instance-type.h @@ -243,6 +243,11 @@ TYPED_ARRAYS(TYPED_ARRAY_IS_TYPE_FUNCTION_DECL) #undef IS_TYPE_FUNCTION_DECL } // namespace InstanceTypeChecker +// This list must contain only maps that are shared by all objects of their +// instance type. +#define UNIQUE_INSTANCE_TYPE_MAP_LIST_GENERATOR(V, _) \ + TORQUE_DEFINED_MAP_CSA_LIST_GENERATOR(V, _) + } // namespace internal } // namespace v8 diff --git a/chromium/v8/src/objects/internal-index.h b/chromium/v8/src/objects/internal-index.h index f00c65bbdd7..7cc9fa67387 100644 --- a/chromium/v8/src/objects/internal-index.h +++ b/chromium/v8/src/objects/internal-index.h @@ -40,9 +40,7 @@ class InternalIndex { return static_cast<uint32_t>(entry_); } constexpr int as_int() const { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK_LE(entry_, std::numeric_limits<int>::max()); -#endif + CONSTEXPR_DCHECK(entry_ <= std::numeric_limits<int>::max()); return static_cast<int>(entry_); } diff --git a/chromium/v8/src/objects/intl-objects.cc b/chromium/v8/src/objects/intl-objects.cc index d358e2780e2..b58dc83264a 100644 --- a/chromium/v8/src/objects/intl-objects.cc +++ b/chromium/v8/src/objects/intl-objects.cc @@ -89,9 +89,7 @@ inline constexpr uint16_t ToLatin1Lower(uint16_t ch) { // Does not work for U+00DF (sharp-s), U+00B5 (micron), U+00FF. inline constexpr uint16_t ToLatin1Upper(uint16_t ch) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK(ch != 0xDF && ch != 0xB5 && ch != 0xFF); -#endif + CONSTEXPR_DCHECK(ch != 0xDF && ch != 0xB5 && ch != 0xFF); return ch & ~((IsAsciiLower(ch) || (((ch & 0xE0) == 0xE0) && ch != 0xF7)) << 5); } @@ -1471,7 +1469,7 @@ class Iterator : public icu::Locale::Iterator { Iterator(std::vector<std::string>::const_iterator begin, std::vector<std::string>::const_iterator end) : iter_(begin), end_(end) {} - virtual ~Iterator() {} + ~Iterator() override = default; UBool hasNext() const override { return iter_ != end_; } @@ -1893,8 +1891,8 @@ Maybe<Intl::ResolvedLocale> Intl::ResolveLocale( Handle<Managed<icu::UnicodeString>> Intl::SetTextToBreakIterator( Isolate* isolate, Handle<String> text, icu::BreakIterator* break_iterator) { text = String::Flatten(isolate, text); - icu::UnicodeString* u_text = - (icu::UnicodeString*)(Intl::ToICUUnicodeString(isolate, text).clone()); + icu::UnicodeString* u_text = static_cast<icu::UnicodeString*>( + Intl::ToICUUnicodeString(isolate, text).clone()); Handle<Managed<icu::UnicodeString>> new_u_text = Managed<icu::UnicodeString>::FromRawPtr(isolate, 0, u_text); diff --git a/chromium/v8/src/objects/intl-objects.h b/chromium/v8/src/objects/intl-objects.h index 944a1f103ed..494b576364c 100644 --- a/chromium/v8/src/objects/intl-objects.h +++ b/chromium/v8/src/objects/intl-objects.h @@ -21,7 +21,7 @@ #include "unicode/locid.h" #include "unicode/uversion.h" -#define V8_MINIMUM_ICU_VERSION 65 +#define V8_MINIMUM_ICU_VERSION 67 namespace U_ICU_NAMESPACE { class BreakIterator; @@ -287,7 +287,7 @@ class Intl { std::vector<std::string> all_locales; const char* loc; - while ((loc = uenum_next(uenum, NULL, &status)) != nullptr) { + while ((loc = uenum_next(uenum, nullptr, &status)) != nullptr) { DCHECK(U_SUCCESS(status)); std::string locstr(loc); std::replace(locstr.begin(), locstr.end(), '_', '-'); @@ -299,7 +299,6 @@ class Intl { set_ = Intl::BuildLocaleSet(all_locales, C::path(), C::key()); } - virtual ~AvailableLocales() {} const std::set<std::string>& Get() const { return set_; } private: diff --git a/chromium/v8/src/objects/js-aggregate-error-inl.h b/chromium/v8/src/objects/js-aggregate-error-inl.h deleted file mode 100644 index 552012c37fe..00000000000 --- a/chromium/v8/src/objects/js-aggregate-error-inl.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 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. - -#ifndef V8_OBJECTS_JS_AGGREGATE_ERROR_INL_H_ -#define V8_OBJECTS_JS_AGGREGATE_ERROR_INL_H_ - -#include "src/objects/js-aggregate-error.h" - -#include "src/objects/objects-inl.h" // Needed for write barriers - -// Has to be the last include (doesn't have include guards): -#include "src/objects/object-macros.h" - -namespace v8 { -namespace internal { - -TQ_OBJECT_CONSTRUCTORS_IMPL(JSAggregateError) - -} // namespace internal -} // namespace v8 - -#include "src/objects/object-macros-undef.h" - -#endif // V8_OBJECTS_JS_AGGREGATE_ERROR_INL_H_ diff --git a/chromium/v8/src/objects/js-aggregate-error.h b/chromium/v8/src/objects/js-aggregate-error.h deleted file mode 100644 index c77633d44ed..00000000000 --- a/chromium/v8/src/objects/js-aggregate-error.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2020 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. - -#ifndef V8_OBJECTS_JS_AGGREGATE_ERROR_H_ -#define V8_OBJECTS_JS_AGGREGATE_ERROR_H_ - -#include "src/objects/js-objects.h" -#include "torque-generated/builtin-definitions-tq.h" - -// Has to be the last include (doesn't have include guards): -#include "src/objects/object-macros.h" - -namespace v8 { -namespace internal { - -class JSAggregateError - : public TorqueGeneratedJSAggregateError<JSAggregateError, JSObject> { - public: - DECL_PRINTER(JSAggregateError) - TQ_OBJECT_CONSTRUCTORS(JSAggregateError) -}; - -} // namespace internal -} // namespace v8 - -#endif // V8_OBJECTS_JS_AGGREGATE_ERROR_H_ diff --git a/chromium/v8/src/objects/js-aggregate-error.tq b/chromium/v8/src/objects/js-aggregate-error.tq deleted file mode 100644 index efa416e9fb4..00000000000 --- a/chromium/v8/src/objects/js-aggregate-error.tq +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2020 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. - -#include 'src/objects/js-aggregate-error.h' - -@generateCppClass -extern class JSAggregateError extends JSObject { - // Only Undefined during AggregateError object creation. In order to make the - // field type FixedArray, we'd need to initialize it in ErrorUtils::Construct - // (after it, it's too late) which we don't want. - errors: FixedArray|Undefined; -} - -namespace error { - -transitioning javascript builtin AggregateErrorConstructor( - js-implicit context: NativeContext, target: JSFunction, - newTarget: JSAny)(...arguments): JSAny { - // This function is implementing the spec as suggested by - // https://github.com/tc39/proposal-promise-any/pull/59 . FIXME(marja): - // change this if the PR is declined. - - // 1. If NewTarget is undefined, let newTarget be the active function - // object, else let newTarget be NewTarget. - // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, - // "%AggregateError.prototype%", « [[ErrorData]], [[AggregateErrors]] »). - // 3. If _message_ is not _undefined_, then - // a. Let msg be ? ToString(_message_). - // b. Let msgDesc be the PropertyDescriptor { [[Value]]: _msg_, - // [[Writable]]: *true*, [[Enumerable]]: *false*, [[Configurable]]: *true* - // c. Perform ! DefinePropertyOrThrow(_O_, *"message"*, _msgDesc_). - const message: JSAny = arguments[1]; - const obj: JSAggregateError = - ConstructAggregateErrorHelper(context, target, newTarget, message); - - // 4. Let errorsList be ? IterableToList(errors). - const errors: JSAny = arguments[0]; - const errorsArray = - iterator::IterableToFixedArrayWithSymbolLookupSlow(errors); - // errorsArray must be marked copy-on-write, since the "errors" getter - // creates a thin JSArray wrapper around it. - MakeFixedArrayCOW(errorsArray); - - // 5. Set O.[[AggregateErrors]] to errorsList. - obj.errors = errorsArray; - - // 6. Return O. - return obj; -} - -transitioning javascript builtin AggregateErrorPrototypeErrorsGetter( - js-implicit context: NativeContext, receiver: JSAny)(): JSAny { - // 1. Let E be the this value. - // 2. If Type(E) is not Object, throw a TypeError exception. - // 3. If E does not have an [[ErrorData]] internal slot, throw a TypeError - // exception. - // 4. If E does not have an [[AggregateErrors]] internal slot, throw a - // TypeError exception. - // 5. Return ! CreateArrayFromList(E.[[AggregateErrors]]). - typeswitch (receiver) { - case (receiver: JSAggregateError): { - return array::CreateJSArrayWithElements( - UnsafeCast<FixedArray>(receiver.errors)); - } - case (Object): { - ThrowTypeError( - MessageTemplate::kNotGeneric, 'JSAggregateError.prototype.errors.get', - 'AggregateError'); - } - } -} - -extern runtime ConstructAggregateErrorHelper( - Context, JSFunction, JSAny, Object): JSAggregateError; - -extern runtime ConstructInternalAggregateErrorHelper( - Context, Object): JSAggregateError; - -extern macro MakeFixedArrayCOW(FixedArray); -} diff --git a/chromium/v8/src/objects/js-array.h b/chromium/v8/src/objects/js-array.h index 86d14f1924b..6cf54df896f 100644 --- a/chromium/v8/src/objects/js-array.h +++ b/chromium/v8/src/objects/js-array.h @@ -30,6 +30,7 @@ class JSArray : public JSObject { // is set to a smi. This matches the set function on FixedArray. inline void set_length(Smi length); + static bool MayHaveReadOnlyLength(Map js_array_map); static bool HasReadOnlyLength(Handle<JSArray> array); static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index); diff --git a/chromium/v8/src/objects/js-array.tq b/chromium/v8/src/objects/js-array.tq index 0cba7203a5c..dcffc68cba0 100644 --- a/chromium/v8/src/objects/js-array.tq +++ b/chromium/v8/src/objects/js-array.tq @@ -2,10 +2,28 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +extern enum IterationKind extends uint31 +constexpr 'IterationKind' { kKeys, kValues, kEntries } + extern class JSArrayIterator extends JSObject { iterated_object: JSReceiver; next_index: Number; - kind: Smi; + kind: SmiTagged<IterationKind>; +} + +// Perform CreateArrayIterator (ES #sec-createarrayiterator). +@export +macro CreateArrayIterator(implicit context: NativeContext)( + array: JSReceiver, kind: constexpr IterationKind): JSArrayIterator { + return new JSArrayIterator{ + map: UnsafeCast<Map>( + context[NativeContextSlot::INITIAL_ARRAY_ITERATOR_MAP_INDEX]), + properties_or_hash: kEmptyFixedArray, + elements: kEmptyFixedArray, + iterated_object: array, + next_index: 0, + kind: SmiTag<IterationKind>(kind) + }; } extern class JSArray extends JSObject { diff --git a/chromium/v8/src/objects/js-collator.cc b/chromium/v8/src/objects/js-collator.cc index ea9120cbed9..4cc7ce3f217 100644 --- a/chromium/v8/src/objects/js-collator.cc +++ b/chromium/v8/src/objects/js-collator.cc @@ -508,7 +508,7 @@ class CollatorAvailableLocales { set_ = Intl::BuildLocaleSet(locales, U_ICUDATA_COLL, nullptr); #undef U_ICUDATA_COLL } - virtual ~CollatorAvailableLocales() {} + virtual ~CollatorAvailableLocales() = default; const std::set<std::string>& Get() const { return set_; } private: diff --git a/chromium/v8/src/objects/js-collection.h b/chromium/v8/src/objects/js-collection.h index 17f9c3e198b..a0350726c02 100644 --- a/chromium/v8/src/objects/js-collection.h +++ b/chromium/v8/src/objects/js-collection.h @@ -30,6 +30,7 @@ class JSSet : public TorqueGeneratedJSSet<JSSet, JSCollection> { public: static void Initialize(Handle<JSSet> set, Isolate* isolate); static void Clear(Isolate* isolate, Handle<JSSet> set); + void Rehash(Isolate* isolate); // Dispatched behavior. DECL_PRINTER(JSSet) @@ -56,6 +57,7 @@ class JSMap : public TorqueGeneratedJSMap<JSMap, JSCollection> { public: static void Initialize(Handle<JSMap> map, Isolate* isolate); static void Clear(Isolate* isolate, Handle<JSMap> map); + void Rehash(Isolate* isolate); // Dispatched behavior. DECL_PRINTER(JSMap) diff --git a/chromium/v8/src/objects/js-date-time-format.cc b/chromium/v8/src/objects/js-date-time-format.cc index 669dfd88ab2..7a2c9036ad2 100644 --- a/chromium/v8/src/objects/js-date-time-format.cc +++ b/chromium/v8/src/objects/js-date-time-format.cc @@ -59,6 +59,21 @@ JSDateTimeFormat::HourCycle ToHourCycle(const std::string& hc) { return JSDateTimeFormat::HourCycle::kUndefined; } +JSDateTimeFormat::HourCycle ToHourCycle(UDateFormatHourCycle hc) { + switch (hc) { + case UDAT_HOUR_CYCLE_11: + return JSDateTimeFormat::HourCycle::kH11; + case UDAT_HOUR_CYCLE_12: + return JSDateTimeFormat::HourCycle::kH12; + case UDAT_HOUR_CYCLE_23: + return JSDateTimeFormat::HourCycle::kH23; + case UDAT_HOUR_CYCLE_24: + return JSDateTimeFormat::HourCycle::kH24; + default: + return JSDateTimeFormat::HourCycle::kUndefined; + } +} + Maybe<JSDateTimeFormat::HourCycle> GetHourCycle(Isolate* isolate, Handle<JSReceiver> options, const char* method) { @@ -161,7 +176,7 @@ static std::vector<PatternItem> BuildPatternItems() { class PatternItems { public: PatternItems() : data(BuildPatternItems()) {} - virtual ~PatternItems() {} + virtual ~PatternItems() = default; const std::vector<PatternItem>& Get() const { return data; } private: @@ -225,7 +240,7 @@ const std::vector<PatternData> CreateData(const char* digit2, class Pattern { public: Pattern(const char* d1, const char* d2) : data(CreateData(d1, d2)) {} - virtual ~Pattern() {} + virtual ~Pattern() = default; virtual const std::vector<PatternData>& Get() const { return data; } private: @@ -892,21 +907,58 @@ MaybeHandle<JSObject> JSDateTimeFormat::ToDateTimeOptions( needs_default &= maybe_needs_default.FromJust(); } - // 6. If needDefaults is true and defaults is either "date" or "all", then + // 6. Let dateStyle be ? Get(options, "dateStyle"). + Maybe<bool> maybe_datestyle_undefined = + IsPropertyUndefined(isolate, options, factory->dateStyle_string()); + MAYBE_RETURN(maybe_datestyle_undefined, Handle<JSObject>()); + // 7. Let timeStyle be ? Get(options, "timeStyle"). + Maybe<bool> maybe_timestyle_undefined = + IsPropertyUndefined(isolate, options, factory->timeStyle_string()); + MAYBE_RETURN(maybe_timestyle_undefined, Handle<JSObject>()); + // 8. If dateStyle is not undefined or timeStyle is not undefined, let + // needDefaults be false. + if (!maybe_datestyle_undefined.FromJust() || + !maybe_timestyle_undefined.FromJust()) { + needs_default = false; + } + // 9. If required is "date" and timeStyle is not undefined, + if (required == RequiredOption::kDate && + !maybe_timestyle_undefined.FromJust()) { + // a. Throw a TypeError exception. + THROW_NEW_ERROR( + isolate, + NewTypeError(MessageTemplate::kInvalid, + factory->NewStringFromStaticChars("option"), + factory->NewStringFromStaticChars("timeStyle")), + JSObject); + } + // 10. If required is "time" and dateStyle is not undefined, + if (required == RequiredOption::kTime && + !maybe_datestyle_undefined.FromJust()) { + // a. Throw a TypeError exception. + THROW_NEW_ERROR( + isolate, + NewTypeError(MessageTemplate::kInvalid, + factory->NewStringFromStaticChars("option"), + factory->NewStringFromStaticChars("dateStyle")), + JSObject); + } + + // 11. If needDefaults is true and defaults is either "date" or "all", then if (needs_default) { if (defaults == DefaultsOption::kAll || defaults == DefaultsOption::kDate) { // a. For each of the property names "year", "month", "day", do) const std::vector<std::string> list({"year", "month", "day"}); MAYBE_RETURN(CreateDefault(isolate, options, list), Handle<JSObject>()); } - // 7. If needDefaults is true and defaults is either "time" or "all", then + // 12. If needDefaults is true and defaults is either "time" or "all", then if (defaults == DefaultsOption::kAll || defaults == DefaultsOption::kTime) { // a. For each of the property names "hour", "minute", "second", do const std::vector<std::string> list({"hour", "minute", "second"}); MAYBE_RETURN(CreateDefault(isolate, options, list), Handle<JSObject>()); } } - // 8. Return options. + // 13. Return options. return options; } @@ -1275,7 +1327,7 @@ icu::UnicodeString ReplaceSkeleton(const icu::UnicodeString input, std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern( JSDateTimeFormat::DateTimeStyle date_style, - JSDateTimeFormat::DateTimeStyle time_style, const icu::Locale& icu_locale, + JSDateTimeFormat::DateTimeStyle time_style, icu::Locale& icu_locale, JSDateTimeFormat::HourCycle hc, icu::DateTimePatternGenerator* generator) { std::unique_ptr<icu::SimpleDateFormat> result; if (date_style != JSDateTimeFormat::DateTimeStyle::kUndefined) { @@ -1290,7 +1342,9 @@ std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern( icu_locale))); // For instance without time, we do not need to worry about the hour cycle // impact so we can return directly. - return result; + if (result.get() != nullptr) { + return result; + } } } else { if (time_style != JSDateTimeFormat::DateTimeStyle::kUndefined) { @@ -1305,28 +1359,27 @@ std::unique_ptr<icu::SimpleDateFormat> DateTimeStylePattern( UErrorCode status = U_ZERO_ERROR; // Somehow we fail to create the instance. if (result.get() == nullptr) { - icu::Locale modified_locale(icu_locale); // Fallback to the locale without "nu". if (!icu_locale.getUnicodeKeywordValue<std::string>("nu", status).empty()) { status = U_ZERO_ERROR; - modified_locale.setUnicodeKeywordValue("nu", nullptr, status); - return DateTimeStylePattern(date_style, time_style, modified_locale, hc, + icu_locale.setUnicodeKeywordValue("nu", nullptr, status); + return DateTimeStylePattern(date_style, time_style, icu_locale, hc, generator); } status = U_ZERO_ERROR; // Fallback to the locale without "hc". if (!icu_locale.getUnicodeKeywordValue<std::string>("hc", status).empty()) { status = U_ZERO_ERROR; - modified_locale.setUnicodeKeywordValue("hc", nullptr, status); - return DateTimeStylePattern(date_style, time_style, modified_locale, hc, + icu_locale.setUnicodeKeywordValue("hc", nullptr, status); + return DateTimeStylePattern(date_style, time_style, icu_locale, hc, generator); } status = U_ZERO_ERROR; // Fallback to the locale without "ca". if (!icu_locale.getUnicodeKeywordValue<std::string>("ca", status).empty()) { status = U_ZERO_ERROR; - modified_locale.setUnicodeKeywordValue("ca", nullptr, status); - return DateTimeStylePattern(date_style, time_style, modified_locale, hc, + icu_locale.setUnicodeKeywordValue("ca", nullptr, status); + return DateTimeStylePattern(date_style, time_style, icu_locale, hc, generator); } return nullptr; @@ -1508,34 +1561,6 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New( CHECK(U_SUCCESS(status)); } - // 17. Let timeZone be ? Get(options, "timeZone"). - std::unique_ptr<char[]> timezone = nullptr; - Maybe<bool> maybe_timezone = Intl::GetStringOption( - isolate, options, "timeZone", empty_values, service, &timezone); - MAYBE_RETURN(maybe_timezone, Handle<JSDateTimeFormat>()); - - std::unique_ptr<icu::TimeZone> tz = CreateTimeZone(timezone.get()); - if (tz.get() == nullptr) { - THROW_NEW_ERROR( - isolate, - NewRangeError(MessageTemplate::kInvalidTimeZone, - factory->NewStringFromAsciiChecked(timezone.get())), - JSDateTimeFormat); - } - - std::unique_ptr<icu::Calendar> calendar( - CreateCalendar(isolate, icu_locale, tz.release())); - - // 18.b If the result of IsValidTimeZoneName(timeZone) is false, then - // i. Throw a RangeError exception. - if (calendar.get() == nullptr) { - THROW_NEW_ERROR( - isolate, - NewRangeError(MessageTemplate::kInvalidTimeZone, - factory->NewStringFromAsciiChecked(timezone.get())), - JSDateTimeFormat); - } - static base::LazyInstance<DateTimePatternGeneratorCache>::type generator_cache = LAZY_INSTANCE_INITIALIZER; @@ -1543,9 +1568,8 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New( generator_cache.Pointer()->CreateGenerator(icu_locale)); // 15.Let hcDefault be dataLocaleData.[[hourCycle]]. - icu::UnicodeString hour_pattern = generator->getBestPattern("jjmm", status); + HourCycle hc_default = ToHourCycle(generator->getDefaultHourCycle(status)); CHECK(U_SUCCESS(status)); - HourCycle hc_default = HourCycleFromPattern(hour_pattern); // 16.Let hc be r.[[hc]]. HourCycle hc = HourCycle::kUndefined; @@ -1590,11 +1614,87 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New( } } + // 17. Let timeZone be ? Get(options, "timeZone"). + std::unique_ptr<char[]> timezone = nullptr; + Maybe<bool> maybe_timezone = Intl::GetStringOption( + isolate, options, "timeZone", empty_values, service, &timezone); + MAYBE_RETURN(maybe_timezone, Handle<JSDateTimeFormat>()); + + std::unique_ptr<icu::TimeZone> tz = CreateTimeZone(timezone.get()); + if (tz.get() == nullptr) { + THROW_NEW_ERROR( + isolate, + NewRangeError(MessageTemplate::kInvalidTimeZone, + factory->NewStringFromAsciiChecked(timezone.get())), + JSDateTimeFormat); + } + + std::unique_ptr<icu::Calendar> calendar( + CreateCalendar(isolate, icu_locale, tz.release())); + + // 18.b If the result of IsValidTimeZoneName(timeZone) is false, then + // i. Throw a RangeError exception. + if (calendar.get() == nullptr) { + THROW_NEW_ERROR( + isolate, + NewRangeError(MessageTemplate::kInvalidTimeZone, + factory->NewStringFromAsciiChecked(timezone.get())), + JSDateTimeFormat); + } + DateTimeStyle date_style = DateTimeStyle::kUndefined; DateTimeStyle time_style = DateTimeStyle::kUndefined; std::unique_ptr<icu::SimpleDateFormat> icu_date_format; - // 28. Let dateStyle be ? GetOption(options, "dateStyle", "string", « + // 28. For each row of Table 1, except the header row, do + bool has_hour_option = false; + std::string skeleton; + for (const PatternData& item : GetPatternData(hc)) { + std::unique_ptr<char[]> input; + // i. Let prop be the name given in the Property column of the row. + // ii. Let value be ? GetOption(options, prop, "string", « the strings + // given in the Values column of the row », undefined). + Maybe<bool> maybe_get_option = + Intl::GetStringOption(isolate, options, item.property.c_str(), + item.allowed_values, service, &input); + MAYBE_RETURN(maybe_get_option, Handle<JSDateTimeFormat>()); + if (maybe_get_option.FromJust()) { + if (item.property == "hour") { + has_hour_option = true; + } + DCHECK_NOT_NULL(input.get()); + // iii. Set opt.[[<prop>]] to value. + skeleton += item.map.find(input.get())->second; + } + } + if (FLAG_harmony_intl_dateformat_fractional_second_digits) { + Maybe<int> maybe_fsd = Intl::GetNumberOption( + isolate, options, factory->fractionalSecondDigits_string(), 0, 3, 0); + MAYBE_RETURN(maybe_fsd, MaybeHandle<JSDateTimeFormat>()); + // Convert fractionalSecondDigits to skeleton. + int fsd = maybe_fsd.FromJust(); + for (int i = 0; i < fsd; i++) { + skeleton += "S"; + } + } + + // 29. Let matcher be ? GetOption(options, "formatMatcher", "string", « + // "basic", "best fit" », "best fit"). + enum FormatMatcherOption { kBestFit, kBasic }; + // We implement only best fit algorithm, but still need to check + // if the formatMatcher values are in range. + // c. Let matcher be ? GetOption(options, "formatMatcher", "string", + // « "basic", "best fit" », "best fit"). + Maybe<FormatMatcherOption> maybe_format_matcher = + Intl::GetStringOption<FormatMatcherOption>( + isolate, options, "formatMatcher", service, {"best fit", "basic"}, + {FormatMatcherOption::kBestFit, FormatMatcherOption::kBasic}, + FormatMatcherOption::kBestFit); + MAYBE_RETURN(maybe_format_matcher, MaybeHandle<JSDateTimeFormat>()); + // TODO(ftang): uncomment the following line and handle format_matcher. + // FormatMatcherOption format_matcher = maybe_format_matcher.FromJust(); + + // 32. Let dateStyle be ? GetOption(options, "dateStyle", "string", « // "full", "long", "medium", "short" », undefined). Maybe<DateTimeStyle> maybe_date_style = Intl::GetStringOption<DateTimeStyle>( isolate, options, "dateStyle", service, @@ -1603,11 +1703,10 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New( DateTimeStyle::kShort}, DateTimeStyle::kUndefined); MAYBE_RETURN(maybe_date_style, MaybeHandle<JSDateTimeFormat>()); - // 29. If dateStyle is not undefined, set dateTimeFormat.[[DateStyle]] to - // dateStyle. + // 33. Set dateTimeFormat.[[DateStyle]] to dateStyle. date_style = maybe_date_style.FromJust(); - // 30. Let timeStyle be ? GetOption(options, "timeStyle", "string", « + // 34. Let timeStyle be ? GetOption(options, "timeStyle", "string", « // "full", "long", "medium", "short" »). Maybe<DateTimeStyle> maybe_time_style = Intl::GetStringOption<DateTimeStyle>( isolate, options, "timeStyle", service, @@ -1617,88 +1716,68 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New( DateTimeStyle::kUndefined); MAYBE_RETURN(maybe_time_style, MaybeHandle<JSDateTimeFormat>()); - // 31. If timeStyle is not undefined, set dateTimeFormat.[[TimeStyle]] to - // timeStyle. + // 35. Set dateTimeFormat.[[TimeStyle]] to timeStyle. time_style = maybe_time_style.FromJust(); - // 32. If dateStyle or timeStyle are not undefined, then + // 36. If timeStyle is not undefined, then + HourCycle dateTimeFormatHourCycle = HourCycle::kUndefined; + if (time_style != DateTimeStyle::kUndefined) { + // a. Set dateTimeFormat.[[HourCycle]] to hc. + dateTimeFormatHourCycle = hc; + } + + // 37. If dateStyle or timeStyle are not undefined, then if (date_style != DateTimeStyle::kUndefined || time_style != DateTimeStyle::kUndefined) { - // Track newer feature dateStyle/timeStyle option. + // a. For each row in Table 1, except the header row, do + // i. Let prop be the name given in the Property column of the row. + // ii. Let p be opt.[[<prop>]]. + // iii. If p is not undefined, then + // 1. Throw a TypeError exception. + if (skeleton.length() > 0) { + THROW_NEW_ERROR(isolate, + NewTypeError(MessageTemplate::kInvalid, + factory->NewStringFromStaticChars("option"), + date_style != DateTimeStyle::kUndefined + ? factory->dateStyle_string() + : factory->timeStyle_string()), + JSDateTimeFormat); + } + // b. Let pattern be DateTimeStylePattern(dateStyle, timeStyle, + // dataLocaleData, hc). isolate->CountUsage( v8::Isolate::UseCounterFeature::kDateTimeFormatDateTimeStyle); - icu_date_format = DateTimeStylePattern(date_style, time_style, icu_locale, - hc, generator.get()); - } - - // 33. Else, - if (icu_date_format.get() == nullptr) { - bool has_hour_option = false; - // b. For each row of Table 5, except the header row, do - std::string skeleton; - for (const PatternData& item : GetPatternData(hc)) { - std::unique_ptr<char[]> input; - // i. Let prop be the name given in the Property column of the row. - // ii. Let value be ? GetOption(options, prop, "string", « the strings - // given in the Values column of the row », undefined). - Maybe<bool> maybe_get_option = - Intl::GetStringOption(isolate, options, item.property.c_str(), - item.allowed_values, service, &input); - MAYBE_RETURN(maybe_get_option, Handle<JSDateTimeFormat>()); - if (maybe_get_option.FromJust()) { - if (item.property == "hour") { - has_hour_option = true; - } - DCHECK_NOT_NULL(input.get()); - // iii. Set opt.[[<prop>]] to value. - skeleton += item.map.find(input.get())->second; - } + icu_date_format = + DateTimeStylePattern(date_style, time_style, icu_locale, + dateTimeFormatHourCycle, generator.get()); + if (icu_date_format.get() == nullptr) { + THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError), + JSDateTimeFormat); } - if (FLAG_harmony_intl_dateformat_fractional_second_digits) { - Maybe<int> maybe_fsd = Intl::GetNumberOption( - isolate, options, factory->fractionalSecondDigits_string(), 0, 3, 0); - MAYBE_RETURN(maybe_fsd, MaybeHandle<JSDateTimeFormat>()); - // Convert fractionalSecondDigits to skeleton. - int fsd = maybe_fsd.FromJust(); - for (int i = 0; i < fsd; i++) { - skeleton += "S"; - } + } else { + // e. If dateTimeFormat.[[Hour]] is not undefined, then + if (has_hour_option) { + // v. Set dateTimeFormat.[[HourCycle]] to hc. + dateTimeFormatHourCycle = hc; + } else { + // f. Else, + // Set dateTimeFormat.[[HourCycle]] to undefined. + dateTimeFormatHourCycle = HourCycle::kUndefined; } - - enum FormatMatcherOption { kBestFit, kBasic }; - // We implement only best fit algorithm, but still need to check - // if the formatMatcher values are in range. - // c. Let matcher be ? GetOption(options, "formatMatcher", "string", - // « "basic", "best fit" », "best fit"). - Maybe<FormatMatcherOption> maybe_format_matcher = - Intl::GetStringOption<FormatMatcherOption>( - isolate, options, "formatMatcher", service, {"best fit", "basic"}, - {FormatMatcherOption::kBestFit, FormatMatcherOption::kBasic}, - FormatMatcherOption::kBestFit); - MAYBE_RETURN(maybe_format_matcher, MaybeHandle<JSDateTimeFormat>()); - // TODO(ftang): uncomment the following line and handle format_matcher. - // FormatMatcherOption format_matcher = maybe_format_matcher.FromJust(); - icu::UnicodeString skeleton_ustr(skeleton.c_str()); - icu_date_format = CreateICUDateFormatFromCache(icu_locale, skeleton_ustr, - generator.get(), hc); + icu_date_format = CreateICUDateFormatFromCache( + icu_locale, skeleton_ustr, generator.get(), dateTimeFormatHourCycle); if (icu_date_format.get() == nullptr) { // Remove extensions and try again. icu_locale = icu::Locale(icu_locale.getBaseName()); - icu_date_format = CreateICUDateFormatFromCache(icu_locale, skeleton_ustr, - generator.get(), hc); + icu_date_format = CreateICUDateFormatFromCache( + icu_locale, skeleton_ustr, generator.get(), dateTimeFormatHourCycle); if (icu_date_format.get() == nullptr) { THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kIcuError), JSDateTimeFormat); } } - - // g. If dateTimeFormat.[[Hour]] is not undefined, then - if (!has_hour_option) { - // h. Else, i. Set dateTimeFormat.[[HourCycle]] to undefined. - hc = HourCycle::kUndefined; - } } // The creation of Calendar depends on timeZone so we have to put 13 after 17. @@ -1723,7 +1802,8 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New( maybe_hour_cycle.FromJust() != HourCycle::kUndefined) { auto hc_extension_it = r.extensions.find("hc"); if (hc_extension_it != r.extensions.end()) { - if (hc != ToHourCycle(hc_extension_it->second.c_str())) { + if (dateTimeFormatHourCycle != + ToHourCycle(hc_extension_it->second.c_str())) { // Remove -hc- if it does not agree with what we used. UErrorCode status = U_ZERO_ERROR; resolved_locale.setUnicodeKeywordValue("hc", nullptr, status); @@ -1757,12 +1837,8 @@ MaybeHandle<JSDateTimeFormat> JSDateTimeFormat::New( } if (time_style != DateTimeStyle::kUndefined) { date_time_format->set_time_style(time_style); - date_time_format->set_hour_cycle(hc); - } - if ((date_style == DateTimeStyle::kUndefined) && - (time_style == DateTimeStyle::kUndefined)) { - date_time_format->set_hour_cycle(hc); } + date_time_format->set_hour_cycle(dateTimeFormatHourCycle); date_time_format->set_locale(*locale_str); date_time_format->set_icu_locale(*managed_locale); date_time_format->set_icu_simple_date_format(*managed_format); diff --git a/chromium/v8/src/objects/js-number-format.cc b/chromium/v8/src/objects/js-number-format.cc index c5b3d06fcaf..0abcd0cbcfc 100644 --- a/chromium/v8/src/objects/js-number-format.cc +++ b/chromium/v8/src/objects/js-number-format.cc @@ -207,7 +207,7 @@ std::map<const std::string, icu::MeasureUnit> CreateUnitMap() { class UnitFactory { public: UnitFactory() : map_(CreateUnitMap()) {} - virtual ~UnitFactory() {} + virtual ~UnitFactory() = default; // ecma402 #sec-issanctionedsimpleunitidentifier icu::MeasureUnit create(const std::string& unitIdentifier) { @@ -482,16 +482,16 @@ Handle<String> SignDisplayString(Isolate* isolate, } // anonymous namespace // Return the minimum integer digits by counting the number of '0' after -// "integer-width/+" in the skeleton. +// "integer-width/*" in the skeleton. // Ex: Return 15 for skeleton as -// “currency/TWD .00 rounding-mode-half-up integer-width/+000000000000000” +// “currency/TWD .00 rounding-mode-half-up integer-width/*000000000000000” // 1 // 123456789012345 -// Return default value as 1 if there are no "integer-width/+". +// Return default value as 1 if there are no "integer-width/*". int32_t JSNumberFormat::MinimumIntegerDigitsFromSkeleton( const icu::UnicodeString& skeleton) { - // count the number of 0 after "integer-width/+" - icu::UnicodeString search("integer-width/+"); + // count the number of 0 after "integer-width/*" + icu::UnicodeString search("integer-width/*"); int32_t index = skeleton.indexOf(search); if (index < 0) return 1; // return 1 if cannot find it. index += search.length(); diff --git a/chromium/v8/src/objects/js-objects-inl.h b/chromium/v8/src/objects/js-objects-inl.h index 300b40d9d74..192d0ed61d1 100644 --- a/chromium/v8/src/objects/js-objects-inl.h +++ b/chromium/v8/src/objects/js-objects-inl.h @@ -5,8 +5,6 @@ #ifndef V8_OBJECTS_JS_OBJECTS_INL_H_ #define V8_OBJECTS_JS_OBJECTS_INL_H_ -#include "src/objects/js-objects.h" - #include "src/diagnostics/code-tracer.h" #include "src/heap/heap-write-barrier.h" #include "src/objects/elements.h" @@ -16,6 +14,7 @@ #include "src/objects/field-index-inl.h" #include "src/objects/hash-table-inl.h" #include "src/objects/heap-number-inl.h" +#include "src/objects/js-objects.h" #include "src/objects/keys.h" #include "src/objects/lookup-inl.h" #include "src/objects/property-array-inl.h" @@ -775,9 +774,8 @@ DEF_GETTER(JSObject, GetElementsKind, ElementsKind) { DCHECK(kind > DICTIONARY_ELEMENTS || IsAnyNonextensibleElementsKind(kind)); } - DCHECK( - !IsSloppyArgumentsElementsKind(kind) || - (elements(isolate).IsFixedArray() && elements(isolate).length() >= 2)); + DCHECK(!IsSloppyArgumentsElementsKind(kind) || + elements(isolate).IsSloppyArgumentsElements()); } #endif return kind; diff --git a/chromium/v8/src/objects/js-objects.cc b/chromium/v8/src/objects/js-objects.cc index a77d2dadfc8..77254ff9979 100644 --- a/chromium/v8/src/objects/js-objects.cc +++ b/chromium/v8/src/objects/js-objects.cc @@ -27,7 +27,6 @@ #include "src/objects/field-type.h" #include "src/objects/fixed-array.h" #include "src/objects/heap-number.h" -#include "src/objects/js-aggregate-error.h" #include "src/objects/js-array-buffer.h" #include "src/objects/js-array-inl.h" #include "src/objects/layout-descriptor.h" @@ -72,6 +71,8 @@ #include "src/strings/string-stream.h" #include "src/utils/ostreams.h" #include "src/wasm/wasm-objects.h" +#include "torque-generated/exported-class-definitions-tq-inl.h" +#include "torque-generated/exported-class-definitions-tq.h" namespace v8 { namespace internal { @@ -2080,8 +2081,6 @@ int JSObject::GetHeaderSize(InstanceType type, return JSObject::kHeaderSize; case JS_GENERATOR_OBJECT_TYPE: return JSGeneratorObject::kHeaderSize; - case JS_AGGREGATE_ERROR_TYPE: - return JSAggregateError::kHeaderSize; case JS_ASYNC_FUNCTION_OBJECT_TYPE: return JSAsyncFunctionObject::kHeaderSize; case JS_ASYNC_GENERATOR_OBJECT_TYPE: @@ -4995,9 +4994,10 @@ void JSFunction::EnsureClosureFeedbackCellArray(Handle<JSFunction> function) { } // static -void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) { +void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function, + IsCompiledScope* is_compiled_scope) { Isolate* const isolate = function->GetIsolate(); - DCHECK(function->shared().is_compiled()); + DCHECK(is_compiled_scope->is_compiled()); DCHECK(function->shared().HasFeedbackMetadata()); if (function->has_feedback_vector()) return; if (function->shared().HasAsmWasmData()) return; @@ -5008,8 +5008,8 @@ void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) { EnsureClosureFeedbackCellArray(function); Handle<ClosureFeedbackCellArray> closure_feedback_cell_array = handle(function->closure_feedback_cell_array(), isolate); - Handle<HeapObject> feedback_vector = - FeedbackVector::New(isolate, shared, closure_feedback_cell_array); + Handle<HeapObject> feedback_vector = FeedbackVector::New( + isolate, shared, closure_feedback_cell_array, is_compiled_scope); // EnsureClosureFeedbackCellArray should handle the special case where we need // to allocate a new feedback cell. Please look at comment in that function // for more details. @@ -5020,7 +5020,8 @@ void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) { } // static -void JSFunction::InitializeFeedbackCell(Handle<JSFunction> function) { +void JSFunction::InitializeFeedbackCell(Handle<JSFunction> function, + IsCompiledScope* is_compiled_scope) { Isolate* const isolate = function->GetIsolate(); if (function->has_feedback_vector()) { @@ -5038,7 +5039,7 @@ void JSFunction::InitializeFeedbackCell(Handle<JSFunction> function) { if (FLAG_always_opt) needs_feedback_vector = true; if (needs_feedback_vector) { - EnsureFeedbackVector(function); + EnsureFeedbackVector(function, is_compiled_scope); } else { EnsureClosureFeedbackCellArray(function); } @@ -5160,8 +5161,16 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { if (function->has_initial_map()) return; Isolate* isolate = function->GetIsolate(); - // First create a new map with the size and number of in-object properties - // suggested by the function. + int expected_nof_properties = + CalculateExpectedNofProperties(isolate, function); + + // {CalculateExpectedNofProperties} can have had the side effect of creating + // the initial map (e.g. it could have triggered an optimized compilation + // whose dependency installation reentered {EnsureHasInitialMap}). + if (function->has_initial_map()) return; + + // Create a new map with the size and number of in-object properties suggested + // by the function. InstanceType instance_type; if (IsResumableFunction(function->shared().kind())) { instance_type = IsAsyncGeneratorFunction(function->shared().kind()) @@ -5173,8 +5182,6 @@ void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { int instance_size; int inobject_properties; - int expected_nof_properties = - CalculateExpectedNofProperties(isolate, function); CalculateInstanceSizeHelper(instance_type, false, 0, expected_nof_properties, &instance_size, &inobject_properties); @@ -5202,7 +5209,6 @@ namespace { bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { switch (instance_type) { - case JS_AGGREGATE_ERROR_TYPE: case JS_API_OBJECT_TYPE: case JS_ARRAY_BUFFER_TYPE: case JS_ARRAY_TYPE: @@ -5577,7 +5583,7 @@ int JSFunction::CalculateExpectedNofProperties(Isolate* isolate, &is_compiled_scope)) { DCHECK(shared->is_compiled()); int count = shared->expected_nof_properties(); - // Check that the estimate is sane. + // Check that the estimate is sensible. if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) { expected_nof_properties += count; } else { diff --git a/chromium/v8/src/objects/js-objects.h b/chromium/v8/src/objects/js-objects.h index 9e9f8e31283..41f371cd0bf 100644 --- a/chromium/v8/src/objects/js-objects.h +++ b/chromium/v8/src/objects/js-objects.h @@ -27,6 +27,7 @@ enum InstanceType : uint16_t; class JSGlobalObject; class JSGlobalProxy; class NativeContext; +class IsCompiledScope; // JSReceiver includes types on which properties can be defined, i.e., // JSObject and JSProxy. @@ -973,6 +974,8 @@ class JSFunction : public JSFunctionOrBoundFunction { static const int kNameDescriptorIndex = 1; // Home object descriptor index when function has a [[HomeObject]] slot. static const int kMaybeHomeObjectDescriptorIndex = 2; + // Fast binding requires length and name accessors. + static const int kMinDescriptorsForFastBind = 2; // [context]: The context for this function. inline Context context(); @@ -1062,7 +1065,7 @@ class JSFunction : public JSFunctionOrBoundFunction { inline FeedbackVector feedback_vector() const; inline bool has_feedback_vector() const; V8_EXPORT_PRIVATE static void EnsureFeedbackVector( - Handle<JSFunction> function); + Handle<JSFunction> function, IsCompiledScope* compiled_scope); // Functions related to clousre feedback cell array that holds feedback cells // used to create closures from this function. We allocate closure feedback @@ -1076,7 +1079,8 @@ class JSFunction : public JSFunctionOrBoundFunction { // initialized to the closure feedback cell array that holds the feedback // cells for create closure calls from this function. In the regular mode, // this allocates feedback vector. - static void InitializeFeedbackCell(Handle<JSFunction> function); + static void InitializeFeedbackCell(Handle<JSFunction> function, + IsCompiledScope* compiled_scope); // Unconditionally clear the type feedback vector. void ClearTypeFeedbackInfo(); @@ -1132,6 +1136,7 @@ class JSFunction : public JSFunctionOrBoundFunction { DECL_CAST(JSFunction) // Calculate the instance size and in-object properties count. + // {CalculateExpectedNofProperties} can trigger compilation. static V8_WARN_UNUSED_RESULT int CalculateExpectedNofProperties( Isolate* isolate, Handle<JSFunction> function); static void CalculateInstanceSizeHelper(InstanceType instance_type, diff --git a/chromium/v8/src/objects/js-regexp.h b/chromium/v8/src/objects/js-regexp.h index 3d584b9f1ab..b32ea4d9402 100644 --- a/chromium/v8/src/objects/js-regexp.h +++ b/chromium/v8/src/objects/js-regexp.h @@ -6,6 +6,7 @@ #define V8_OBJECTS_JS_REGEXP_H_ #include "src/objects/js-array.h" +#include "torque-generated/bit-fields-tq.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -36,40 +37,18 @@ class JSRegExp : public TorqueGeneratedJSRegExp<JSRegExp, JSObject> { // ATOM: A simple string to match against using an indexOf operation. // IRREGEXP: Compiled with Irregexp. enum Type { NOT_COMPILED, ATOM, IRREGEXP }; - struct FlagShiftBit { - static constexpr int kGlobal = 0; - static constexpr int kIgnoreCase = 1; - static constexpr int kMultiline = 2; - static constexpr int kSticky = 3; - static constexpr int kUnicode = 4; - static constexpr int kDotAll = 5; - static constexpr int kInvalid = 6; - }; - enum Flag : uint8_t { - kNone = 0, - kGlobal = 1 << FlagShiftBit::kGlobal, - kIgnoreCase = 1 << FlagShiftBit::kIgnoreCase, - kMultiline = 1 << FlagShiftBit::kMultiline, - kSticky = 1 << FlagShiftBit::kSticky, - kUnicode = 1 << FlagShiftBit::kUnicode, - kDotAll = 1 << FlagShiftBit::kDotAll, - // Update FlagCount when adding new flags. - kInvalid = 1 << FlagShiftBit::kInvalid, // Not included in FlagCount. - }; - using Flags = base::Flags<Flag>; - - static constexpr int kFlagCount = 6; - - static constexpr Flag FlagFromChar(char c) { + DEFINE_TORQUE_GENERATED_JS_REG_EXP_FLAGS() + + static constexpr base::Optional<Flag> FlagFromChar(char c) { STATIC_ASSERT(kFlagCount == 6); // clang-format off - return c == 'g' ? kGlobal - : c == 'i' ? kIgnoreCase - : c == 'm' ? kMultiline - : c == 'y' ? kSticky - : c == 'u' ? kUnicode - : c == 's' ? kDotAll - : kInvalid; + return c == 'g' ? base::Optional<Flag>(kGlobal) + : c == 'i' ? base::Optional<Flag>(kIgnoreCase) + : c == 'm' ? base::Optional<Flag>(kMultiline) + : c == 'y' ? base::Optional<Flag>(kSticky) + : c == 'u' ? base::Optional<Flag>(kUnicode) + : c == 's' ? base::Optional<Flag>(kDotAll) + : base::Optional<Flag>(); // clang-format on } diff --git a/chromium/v8/src/objects/js-regexp.tq b/chromium/v8/src/objects/js-regexp.tq index f2e216f282d..35e77114ba0 100644 --- a/chromium/v8/src/objects/js-regexp.tq +++ b/chromium/v8/src/objects/js-regexp.tq @@ -2,11 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +bitfield struct JSRegExpFlags extends uint31 { + global: bool: 1 bit; + ignore_case: bool: 1 bit; + multiline: bool: 1 bit; + sticky: bool: 1 bit; + unicode: bool: 1 bit; + dot_all: bool: 1 bit; +} + @generateCppClass extern class JSRegExp extends JSObject { data: FixedArray|Undefined; source: String|Undefined; - flags: Smi|Undefined; + flags: SmiTagged<JSRegExpFlags>|Undefined; } // Note: Although a condition for a FastJSRegExp is having a positive smi diff --git a/chromium/v8/src/objects/js-relative-time-format.cc b/chromium/v8/src/objects/js-relative-time-format.cc index 0cb6b117dff..a6fe9a5864c 100644 --- a/chromium/v8/src/objects/js-relative-time-format.cc +++ b/chromium/v8/src/objects/js-relative-time-format.cc @@ -18,8 +18,10 @@ #include "src/objects/js-number-format.h" #include "src/objects/js-relative-time-format-inl.h" #include "src/objects/objects-inl.h" +#include "unicode/decimfmt.h" #include "unicode/numfmt.h" #include "unicode/reldatefmt.h" +#include "unicode/unum.h" namespace v8 { namespace internal { @@ -193,6 +195,10 @@ MaybeHandle<JSRelativeTimeFormat> JSRelativeTimeFormat::New( } } + icu::DecimalFormat* decimal_format = + static_cast<icu::DecimalFormat*>(number_format); + decimal_format->setMinimumGroupingDigits(-2); + // Change UDISPCTX_CAPITALIZATION_NONE to other values if // ECMA402 later include option to change capitalization. // Ref: https://github.com/tc39/proposal-intl-relative-time/issues/11 diff --git a/chromium/v8/src/objects/keys.cc b/chromium/v8/src/objects/keys.cc index 16008e39d87..66373f3a546 100644 --- a/chromium/v8/src/objects/keys.cc +++ b/chromium/v8/src/objects/keys.cc @@ -949,7 +949,7 @@ Maybe<bool> KeyAccumulator::CollectOwnKeys(Handle<JSReceiver> receiver, if (mode_ == KeyCollectionMode::kIncludePrototypes) { return Just(false); } - // ...whereas [[OwnPropertyKeys]] shall return whitelisted properties. + // ...whereas [[OwnPropertyKeys]] shall return allowlisted properties. DCHECK_EQ(KeyCollectionMode::kOwnOnly, mode_); Handle<AccessCheckInfo> access_check_info; { diff --git a/chromium/v8/src/objects/lookup.cc b/chromium/v8/src/objects/lookup.cc index d5fbf7c894a..0361b6dfd78 100644 --- a/chromium/v8/src/objects/lookup.cc +++ b/chromium/v8/src/objects/lookup.cc @@ -14,6 +14,8 @@ #include "src/objects/hash-table-inl.h" #include "src/objects/heap-number-inl.h" #include "src/objects/struct-inl.h" +#include "torque-generated/exported-class-definitions-tq-inl.h" +#include "torque-generated/exported-class-definitions-tq.h" namespace v8 { namespace internal { @@ -763,13 +765,14 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair, receiver->RequireSlowElements(*dictionary); if (receiver->HasSlowArgumentsElements(isolate_)) { - FixedArray parameter_map = FixedArray::cast(receiver->elements(isolate_)); - uint32_t length = parameter_map.length() - 2; + SloppyArgumentsElements parameter_map = + SloppyArgumentsElements::cast(receiver->elements(isolate_)); + uint32_t length = parameter_map.length(); if (number_.is_found() && number_.as_uint32() < length) { - parameter_map.set(number_.as_int() + 2, - ReadOnlyRoots(isolate_).the_hole_value()); + parameter_map.set_mapped_entries( + number_.as_int(), ReadOnlyRoots(isolate_).the_hole_value()); } - FixedArray::cast(receiver->elements(isolate_)).set(1, *dictionary); + parameter_map.set_arguments(*dictionary); } else { receiver->set_elements(*dictionary); } diff --git a/chromium/v8/src/objects/map-inl.h b/chromium/v8/src/objects/map-inl.h index d529a8bbc97..04ac97c8dbd 100644 --- a/chromium/v8/src/objects/map-inl.h +++ b/chromium/v8/src/objects/map-inl.h @@ -55,7 +55,7 @@ ACCESSORS_CHECKED(Map, prototype_info, Object, // |bit_field| fields. // Concurrent access to |has_prototype_slot| and |has_non_instance_prototype| -// is explicitly whitelisted here. The former is never modified after the map +// is explicitly allowlisted here. The former is never modified after the map // is setup but it's being read by concurrent marker when pointer compression // is enabled. The latter bit can be modified on a live objects. BIT_FIELD_ACCESSORS(Map, relaxed_bit_field, has_non_instance_prototype, @@ -227,8 +227,6 @@ FixedArrayBase Map::GetInitialElements() const { if (has_fast_elements() || has_fast_string_wrapper_elements() || has_any_nonextensible_elements()) { result = GetReadOnlyRoots().empty_fixed_array(); - } else if (has_fast_sloppy_arguments_elements()) { - result = GetReadOnlyRoots().empty_sloppy_arguments_elements(); } else if (has_typed_array_elements()) { result = GetReadOnlyRoots().empty_byte_array(); } else if (has_dictionary_elements()) { diff --git a/chromium/v8/src/objects/map-updater.cc b/chromium/v8/src/objects/map-updater.cc index 8c9b94014f8..e51bcfc7601 100644 --- a/chromium/v8/src/objects/map-updater.cc +++ b/chromium/v8/src/objects/map-updater.cc @@ -713,16 +713,18 @@ MapUpdater::State MapUpdater::ConstructNewMap() { TransitionsAccessor transitions(isolate_, split_map); // Invalidate a transition target at |key|. - Map maybe_transition = transitions.SearchTransition( - GetKey(split_index), split_details.kind(), split_details.attributes()); - if (!maybe_transition.is_null()) { - maybe_transition.DeprecateTransitionTree(isolate_); + Handle<Map> maybe_transition( + transitions.SearchTransition(GetKey(split_index), split_details.kind(), + split_details.attributes()), + isolate_); + if (!maybe_transition->is_null()) { + maybe_transition->DeprecateTransitionTree(isolate_); } // If |maybe_transition| is not nullptr 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. - if (maybe_transition.is_null() && !transitions.CanHaveMoreTransitions()) { + if (maybe_transition->is_null() && !transitions.CanHaveMoreTransitions()) { return Normalize("Normalize_CantHaveMoreTransitions"); } diff --git a/chromium/v8/src/objects/map.cc b/chromium/v8/src/objects/map.cc index bb13ace4bb0..d85d5893c43 100644 --- a/chromium/v8/src/objects/map.cc +++ b/chromium/v8/src/objects/map.cc @@ -25,6 +25,8 @@ #include "src/roots/roots.h" #include "src/utils/ostreams.h" #include "src/zone/zone-containers.h" +#include "torque-generated/exported-class-definitions-tq-inl.h" +#include "torque-generated/exported-class-definitions-tq.h" #include "torque-generated/field-offsets-tq.h" namespace v8 { @@ -89,7 +91,7 @@ Map Map::GetInstanceTypeMap(ReadOnlyRoots roots, InstanceType type) { case TYPE: \ map = roots.name##_map(); \ break; - TORQUE_INTERNAL_INSTANCE_TYPE_LIST(MAKE_CASE) + TORQUE_DEFINED_INSTANCE_TYPE_LIST(MAKE_CASE) #undef MAKE_CASE default: UNREACHABLE(); @@ -268,7 +270,6 @@ VisitorId Map::GetVisitorId(Map map) { case JS_OBJECT_TYPE: case JS_ERROR_TYPE: - case JS_AGGREGATE_ERROR_TYPE: case JS_ARGUMENTS_OBJECT_TYPE: case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE: case JS_CONTEXT_EXTENSION_OBJECT_TYPE: @@ -1437,8 +1438,9 @@ bool Map::MayHaveReadOnlyElementsInPrototypeChain(Isolate* isolate) { } if (IsSlowArgumentsElementsKind(elements_kind)) { - FixedArray parameter_map = FixedArray::cast(current.elements(isolate)); - Object arguments = parameter_map.get(isolate, 1); + SloppyArgumentsElements elements = + SloppyArgumentsElements::cast(current.elements(isolate)); + Object arguments = elements.arguments(); if (NumberDictionary::cast(arguments).requires_slow_elements()) { return true; } diff --git a/chromium/v8/src/objects/map.h b/chromium/v8/src/objects/map.h index 9876d85d3ec..5e1298461d8 100644 --- a/chromium/v8/src/objects/map.h +++ b/chromium/v8/src/objects/map.h @@ -252,7 +252,7 @@ class Map : public HeapObject { // Bit field. // DECL_PRIMITIVE_ACCESSORS(bit_field, byte) - // Atomic accessors, used for whitelisting legitimate concurrent accesses. + // Atomic accessors, used for allowlisting legitimate concurrent accesses. DECL_PRIMITIVE_ACCESSORS(relaxed_bit_field, byte) // Bit positions for |bit_field|. @@ -594,6 +594,7 @@ class Map : public HeapObject { WriteBarrierMode mode = UPDATE_WRITE_BARRIER); // [instance descriptors]: describes the object. + DECL_GETTER(synchronized_instance_descriptors, DescriptorArray) DECL_GETTER(instance_descriptors, DescriptorArray) V8_EXPORT_PRIVATE void SetInstanceDescriptors(Isolate* isolate, DescriptorArray descriptors, @@ -976,7 +977,8 @@ class Map : public HeapObject { MaybeHandle<Object> new_value); // Use the high-level instance_descriptors/SetInstanceDescriptors instead. - DECL_ACCESSORS(synchronized_instance_descriptors, DescriptorArray) + inline void set_synchronized_instance_descriptors( + DescriptorArray value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); static const int kFastPropertiesSoftLimit = 12; static const int kMaxFastProperties = 128; diff --git a/chromium/v8/src/objects/map.tq b/chromium/v8/src/objects/map.tq index 93c56278955..e7333a38634 100644 --- a/chromium/v8/src/objects/map.tq +++ b/chromium/v8/src/objects/map.tq @@ -80,3 +80,16 @@ extern class Map extends HeapObject { macro LoadMapPrototypeInfo(m: Map): PrototypeInfo labels HasNoPrototypeInfo { return m.PrototypeInfo() otherwise HasNoPrototypeInfo; } + +// Returns true if the map corresponds to non-special fast or dictionary +// object. +@export +macro IsSimpleObjectMap(map: Map): bool { + if (IsSpecialReceiverInstanceType(map.instance_type)) { + return false; + } + const bitField = map.bit_field; + return !bitField.has_named_interceptor & !bitField.is_access_check_needed; +} + +extern macro IsSpecialReceiverInstanceType(InstanceType): bool; diff --git a/chromium/v8/src/objects/maybe-object-inl.h b/chromium/v8/src/objects/maybe-object-inl.h index 7c236a8ff94..05ef21c3dfc 100644 --- a/chromium/v8/src/objects/maybe-object-inl.h +++ b/chromium/v8/src/objects/maybe-object-inl.h @@ -6,6 +6,7 @@ #define V8_OBJECTS_MAYBE_OBJECT_INL_H_ #include "src/common/ptr-compr-inl.h" +#include "src/execution/local-isolate-wrapper.h" #include "src/objects/maybe-object.h" #include "src/objects/smi-inl.h" #include "src/objects/tagged-impl-inl.h" @@ -88,6 +89,13 @@ HeapObjectReference HeapObjectReference::ClearedValue( return HeapObjectReference(raw_value); } +// static +HeapObjectReference HeapObjectReference::ClearedValue( + LocalIsolateWrapper isolate) { + return isolate.is_off_thread() ? ClearedValue(isolate.off_thread()) + : ClearedValue(isolate.main_thread()); +} + template <typename THeapObjectSlot> void HeapObjectReference::Update(THeapObjectSlot slot, HeapObject value) { static_assert(std::is_same<THeapObjectSlot, FullHeapObjectSlot>::value || diff --git a/chromium/v8/src/objects/maybe-object.h b/chromium/v8/src/objects/maybe-object.h index 0bb312692a4..92f68204138 100644 --- a/chromium/v8/src/objects/maybe-object.h +++ b/chromium/v8/src/objects/maybe-object.h @@ -5,6 +5,7 @@ #ifndef V8_OBJECTS_MAYBE_OBJECT_H_ #define V8_OBJECTS_MAYBE_OBJECT_H_ +#include "src/execution/local-isolate-wrapper.h" #include "src/objects/tagged-impl.h" namespace v8 { @@ -52,6 +53,9 @@ class HeapObjectReference : public MaybeObject { V8_INLINE static HeapObjectReference ClearedValue( const OffThreadIsolate* isolate); + V8_INLINE static HeapObjectReference ClearedValue( + LocalIsolateWrapper isolate); + template <typename THeapObjectSlot> V8_INLINE static void Update(THeapObjectSlot slot, HeapObject value); }; diff --git a/chromium/v8/src/objects/module-inl.h b/chromium/v8/src/objects/module-inl.h index ce03c395005..e627aedf18a 100644 --- a/chromium/v8/src/objects/module-inl.h +++ b/chromium/v8/src/objects/module-inl.h @@ -36,8 +36,9 @@ ACCESSORS(Module, exception, Object, kExceptionOffset) SMI_ACCESSORS(Module, status, kStatusOffset) SMI_ACCESSORS(Module, hash, kHashOffset) -BOOL_ACCESSORS(SourceTextModule, flags, async, kAsyncBit) -BOOL_ACCESSORS(SourceTextModule, flags, async_evaluating, kAsyncEvaluatingBit) +BOOL_ACCESSORS(SourceTextModule, flags, async, AsyncBit::kShift) +BOOL_ACCESSORS(SourceTextModule, flags, async_evaluating, + AsyncEvaluatingBit::kShift) ACCESSORS(SourceTextModule, async_parent_modules, ArrayList, kAsyncParentModulesOffset) ACCESSORS(SourceTextModule, top_level_capability, HeapObject, diff --git a/chromium/v8/src/objects/name.tq b/chromium/v8/src/objects/name.tq index 70bb6aea184..4870e2a3f7a 100644 --- a/chromium/v8/src/objects/name.tq +++ b/chromium/v8/src/objects/name.tq @@ -5,8 +5,16 @@ @abstract @generateCppClass extern class Name extends PrimitiveHeapObject { - hash_field: uint32; + hash_field: NameHash; } + +bitfield struct NameHash extends uint32 { + hash_not_commputed: bool: 1 bit; + is_not_integer_index_mask: bool: 1 bit; + array_index_value: uint32: 24 bit; + array_index_length: uint32: 6 bit; +} + // This is the same as Name, but with the information that there are no other // kinds of names. type AnyName = PrivateSymbol|PublicSymbol|String; @@ -29,5 +37,12 @@ extern class Symbol extends Name { type PublicSymbol extends Symbol; type PrivateSymbol extends Symbol; -const kNameEmptyHashField: - constexpr uint32 generates 'Name::kEmptyHashField'; +const kNameEmptyHashField: NameHash = NameHash{ + hash_not_commputed: true, + is_not_integer_index_mask: true, + array_index_value: 0, + array_index_length: 0 +}; + +const kMaxCachedArrayIndexLength: constexpr uint32 + generates 'Name::kMaxCachedArrayIndexLength'; diff --git a/chromium/v8/src/objects/object-list-macros.h b/chromium/v8/src/objects/object-list-macros.h index 34b3ae26efc..2b779955dcb 100644 --- a/chromium/v8/src/objects/object-list-macros.h +++ b/chromium/v8/src/objects/object-list-macros.h @@ -126,7 +126,6 @@ class ZoneForwardList; V(HandlerTable) \ V(HeapNumber) \ V(InternalizedString) \ - V(JSAggregateError) \ V(JSArgumentsObject) \ V(JSArray) \ V(JSArrayBuffer) \ @@ -202,7 +201,6 @@ class ZoneForwardList; V(SharedFunctionInfo) \ V(SimpleNumberDictionary) \ V(SlicedString) \ - V(SloppyArgumentsElements) \ V(SmallOrderedHashMap) \ V(SmallOrderedHashSet) \ V(SmallOrderedNameDictionary) \ @@ -238,7 +236,7 @@ class ZoneForwardList; V(WeakFixedArray) \ V(WeakArrayList) \ V(WeakCell) \ - TORQUE_INTERNAL_CLASS_LIST(V) + TORQUE_DEFINED_CLASS_LIST(V) #ifdef V8_INTL_SUPPORT #define HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \ diff --git a/chromium/v8/src/objects/objects-body-descriptors-inl.h b/chromium/v8/src/objects/objects-body-descriptors-inl.h index 58b4106e882..bb25adaa353 100644 --- a/chromium/v8/src/objects/objects-body-descriptors-inl.h +++ b/chromium/v8/src/objects/objects-body-descriptors-inl.h @@ -811,7 +811,7 @@ class WasmArray::BodyDescriptor final : public BodyDescriptorBase { template <typename ObjectVisitor> static inline void IterateBody(Map map, HeapObject obj, int object_size, ObjectVisitor* v) { - if (!WasmArray::type(map)->element_type().IsReferenceType()) return; + if (!WasmArray::type(map)->element_type().is_reference_type()) return; IteratePointers(obj, WasmArray::kHeaderSize, object_size, v); } @@ -835,7 +835,7 @@ class WasmStruct::BodyDescriptor final : public BodyDescriptorBase { WasmStruct wasm_struct = WasmStruct::cast(obj); wasm::StructType* type = WasmStruct::GcSafeType(map); for (uint32_t i = 0; i < type->field_count(); i++) { - if (!type->field(i).IsReferenceType()) continue; + if (!type->field(i).is_reference_type()) continue; int offset = WasmStruct::kHeaderSize + static_cast<int>(type->field_offset(i)); v->VisitPointer(wasm_struct, wasm_struct.RawField(offset)); @@ -981,7 +981,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) { case JS_ASYNC_GENERATOR_OBJECT_TYPE: case JS_PRIMITIVE_WRAPPER_TYPE: case JS_DATE_TYPE: - case JS_AGGREGATE_ERROR_TYPE: case JS_ARRAY_TYPE: case JS_ARRAY_ITERATOR_TYPE: case JS_MODULE_NAMESPACE_TYPE: diff --git a/chromium/v8/src/objects/objects-definitions.h b/chromium/v8/src/objects/objects-definitions.h index 8a990cbc631..eaa3d9e9cc2 100644 --- a/chromium/v8/src/objects/objects-definitions.h +++ b/chromium/v8/src/objects/objects-definitions.h @@ -151,7 +151,6 @@ namespace internal { V(_, TUPLE2_TYPE, Tuple2, tuple2) \ V(_, WASM_CAPI_FUNCTION_DATA_TYPE, WasmCapiFunctionData, \ wasm_capi_function_data) \ - V(_, WASM_DEBUG_INFO_TYPE, WasmDebugInfo, wasm_debug_info) \ V(_, WASM_EXCEPTION_TAG_TYPE, WasmExceptionTag, wasm_exception_tag) \ V(_, WASM_EXPORTED_FUNCTION_DATA_TYPE, WasmExportedFunctionData, \ wasm_exported_function_data) \ diff --git a/chromium/v8/src/objects/objects-inl.h b/chromium/v8/src/objects/objects-inl.h index 9877b67c19d..56465b179ee 100644 --- a/chromium/v8/src/objects/objects-inl.h +++ b/chromium/v8/src/objects/objects-inl.h @@ -67,10 +67,6 @@ int PropertyDetails::field_width_in_words() const { return representation().IsDouble() ? kDoubleSize / kTaggedSize : 1; } -DEF_GETTER(HeapObject, IsSloppyArgumentsElements, bool) { - return IsFixedArrayExact(isolate); -} - DEF_GETTER(HeapObject, IsClassBoilerplate, bool) { return IsFixedArrayExact(isolate); } diff --git a/chromium/v8/src/objects/objects.cc b/chromium/v8/src/objects/objects.cc index 53693149e14..3ef1067d9f9 100644 --- a/chromium/v8/src/objects/objects.cc +++ b/chromium/v8/src/objects/objects.cc @@ -2306,9 +2306,8 @@ bool HeapObject::NeedsRehashing() const { case TRANSITION_ARRAY_TYPE: return TransitionArray::cast(*this).number_of_entries() > 1; case ORDERED_HASH_MAP_TYPE: - return OrderedHashMap::cast(*this).NumberOfElements() > 0; case ORDERED_HASH_SET_TYPE: - return OrderedHashSet::cast(*this).NumberOfElements() > 0; + return false; // We'll rehash from the JSMap or JSSet referencing them. case NAME_DICTIONARY_TYPE: case GLOBAL_DICTIONARY_TYPE: case NUMBER_DICTIONARY_TYPE: @@ -2318,6 +2317,8 @@ bool HeapObject::NeedsRehashing() const { case SMALL_ORDERED_HASH_MAP_TYPE: case SMALL_ORDERED_HASH_SET_TYPE: case SMALL_ORDERED_NAME_DICTIONARY_TYPE: + case JS_MAP_TYPE: + case JS_SET_TYPE: return true; default: return false; @@ -2327,10 +2328,13 @@ bool HeapObject::NeedsRehashing() const { bool HeapObject::CanBeRehashed() const { DCHECK(NeedsRehashing()); switch (map().instance_type()) { + case JS_MAP_TYPE: + case JS_SET_TYPE: + return true; case ORDERED_HASH_MAP_TYPE: case ORDERED_HASH_SET_TYPE: + UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them. case ORDERED_NAME_DICTIONARY_TYPE: - // TODO(yangguo): actually support rehashing OrderedHash{Map,Set}. return false; case NAME_DICTIONARY_TYPE: case GLOBAL_DICTIONARY_TYPE: @@ -2354,7 +2358,8 @@ bool HeapObject::CanBeRehashed() const { return false; } -void HeapObject::RehashBasedOnMap(ReadOnlyRoots roots) { +void HeapObject::RehashBasedOnMap(LocalIsolateWrapper isolate) { + ReadOnlyRoots roots = ReadOnlyRoots(isolate); switch (map().instance_type()) { case HASH_TABLE_TYPE: UNREACHABLE(); @@ -2386,6 +2391,19 @@ void HeapObject::RehashBasedOnMap(ReadOnlyRoots roots) { case SMALL_ORDERED_HASH_SET_TYPE: DCHECK_EQ(0, SmallOrderedHashSet::cast(*this).NumberOfElements()); break; + case ORDERED_HASH_MAP_TYPE: + case ORDERED_HASH_SET_TYPE: + UNREACHABLE(); // We'll rehash from the JSMap or JSSet referencing them. + case JS_MAP_TYPE: { + DCHECK(isolate.is_main_thread()); + JSMap::cast(*this).Rehash(isolate.main_thread()); + break; + } + case JS_SET_TYPE: { + DCHECK(isolate.is_main_thread()); + JSSet::cast(*this).Rehash(isolate.main_thread()); + break; + } case SMALL_ORDERED_NAME_DICTIONARY_TYPE: DCHECK_EQ(0, SmallOrderedNameDictionary::cast(*this).NumberOfElements()); break; @@ -5509,13 +5527,21 @@ int SharedFunctionInfo::StartPosition() const { if (info.HasPositionInfo()) { return info.StartPosition(); } - } else if (HasUncompiledData()) { + } + if (HasUncompiledData()) { // Works with or without scope. return uncompiled_data().start_position(); - } else if (IsApiFunction() || HasBuiltinId()) { + } + if (IsApiFunction() || HasBuiltinId()) { DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy); return 0; } + if (HasWasmExportedFunctionData()) { + WasmInstanceObject instance = wasm_exported_function_data().instance(); + int func_index = wasm_exported_function_data().function_index(); + auto& function = instance.module()->functions[func_index]; + return static_cast<int>(function.code.offset()); + } return kNoSourcePosition; } @@ -5526,13 +5552,21 @@ int SharedFunctionInfo::EndPosition() const { if (info.HasPositionInfo()) { return info.EndPosition(); } - } else if (HasUncompiledData()) { + } + if (HasUncompiledData()) { // Works with or without scope. return uncompiled_data().end_position(); - } else if (IsApiFunction() || HasBuiltinId()) { + } + if (IsApiFunction() || HasBuiltinId()) { DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy); return 0; } + if (HasWasmExportedFunctionData()) { + WasmInstanceObject instance = wasm_exported_function_data().instance(); + int func_index = wasm_exported_function_data().function_index(); + auto& function = instance.module()->functions[func_index]; + return static_cast<int>(function.code.end_offset()); + } return kNoSourcePosition; } @@ -5717,17 +5751,27 @@ const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) { return nullptr; } +// static +bool JSArray::MayHaveReadOnlyLength(Map js_array_map) { + DCHECK(js_array_map.IsJSArrayMap()); + if (js_array_map.is_dictionary_map()) return true; + + // Fast path: "length" is the first fast property of arrays with non + // dictionary properties. Since it's not configurable, it's guaranteed to be + // the first in the descriptor array. + InternalIndex first(0); + DCHECK(js_array_map.instance_descriptors().GetKey(first) == + js_array_map.GetReadOnlyRoots().length_string()); + return js_array_map.instance_descriptors().GetDetails(first).IsReadOnly(); +} + bool JSArray::HasReadOnlyLength(Handle<JSArray> array) { Map map = array->map(); - // Fast path: "length" is the first fast property of arrays. Since it's not - // configurable, it's guaranteed to be the first in the descriptor array. - if (!map.is_dictionary_map()) { - InternalIndex first(0); - DCHECK(map.instance_descriptors().GetKey(first) == - array->GetReadOnlyRoots().length_string()); - return map.instance_descriptors().GetDetails(first).IsReadOnly(); - } + // If map guarantees that there can't be a read-only length, we are done. + if (!MayHaveReadOnlyLength(map)) return false; + + // Look at the object. Isolate* isolate = array->GetIsolate(); LookupIterator it(isolate, array, isolate->factory()->length_string(), array, LookupIterator::OWN_SKIP_INTERCEPTOR); @@ -5758,7 +5802,7 @@ void Dictionary<Derived, Shape>::Print(std::ostream& os) { if (!dictionary.ToKey(roots, i, &k)) continue; os << "\n "; if (k.IsString()) { - String::cast(k).StringPrint(os); + String::cast(k).PrintUC16(os); } else { os << Brief(k); } @@ -5796,10 +5840,8 @@ void Symbol::SymbolShortPrint(std::ostream& os) { os << "<Symbol:"; if (!description().IsUndefined()) { os << " "; - HeapStringAllocator allocator; - StringStream accumulator(&allocator); - String::cast(description()).StringShortPrint(&accumulator, false); - os << accumulator.ToCString().get(); + String description_as_string = String::cast(description()); + description_as_string.PrintUC16(os, 0, description_as_string.length()); } else { os << " (" << PrivateSymbolToName() << ")"; } @@ -6176,12 +6218,12 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate, // static JSRegExp::Flags JSRegExp::FlagsFromString(Isolate* isolate, Handle<String> flags, bool* success) { - STATIC_ASSERT(JSRegExp::FlagFromChar('g') == JSRegExp::kGlobal); - STATIC_ASSERT(JSRegExp::FlagFromChar('i') == JSRegExp::kIgnoreCase); - STATIC_ASSERT(JSRegExp::FlagFromChar('m') == JSRegExp::kMultiline); - STATIC_ASSERT(JSRegExp::FlagFromChar('s') == JSRegExp::kDotAll); - STATIC_ASSERT(JSRegExp::FlagFromChar('u') == JSRegExp::kUnicode); - STATIC_ASSERT(JSRegExp::FlagFromChar('y') == JSRegExp::kSticky); + STATIC_ASSERT(*JSRegExp::FlagFromChar('g') == JSRegExp::kGlobal); + STATIC_ASSERT(*JSRegExp::FlagFromChar('i') == JSRegExp::kIgnoreCase); + STATIC_ASSERT(*JSRegExp::FlagFromChar('m') == JSRegExp::kMultiline); + STATIC_ASSERT(*JSRegExp::FlagFromChar('s') == JSRegExp::kDotAll); + STATIC_ASSERT(*JSRegExp::FlagFromChar('u') == JSRegExp::kUnicode); + STATIC_ASSERT(*JSRegExp::FlagFromChar('y') == JSRegExp::kSticky); int length = flags->length(); if (length == 0) { @@ -6190,14 +6232,16 @@ JSRegExp::Flags JSRegExp::FlagsFromString(Isolate* isolate, } // A longer flags string cannot be valid. if (length > JSRegExp::kFlagCount) return JSRegExp::Flags(0); - // Initialize {value} to {kInvalid} to allow 2-in-1 duplicate/invalid check. - JSRegExp::Flags value = JSRegExp::kInvalid; + JSRegExp::Flags value(0); if (flags->IsSeqOneByteString()) { DisallowHeapAllocation no_gc; SeqOneByteString seq_flags = SeqOneByteString::cast(*flags); for (int i = 0; i < length; i++) { - JSRegExp::Flag flag = JSRegExp::FlagFromChar(seq_flags.Get(i)); - // Duplicate or invalid flag. + base::Optional<JSRegExp::Flag> maybe_flag = + JSRegExp::FlagFromChar(seq_flags.Get(i)); + if (!maybe_flag.has_value()) return JSRegExp::Flags(0); + JSRegExp::Flag flag = *maybe_flag; + // Duplicate flag. if (value & flag) return JSRegExp::Flags(0); value |= flag; } @@ -6206,15 +6250,16 @@ JSRegExp::Flags JSRegExp::FlagsFromString(Isolate* isolate, DisallowHeapAllocation no_gc; String::FlatContent flags_content = flags->GetFlatContent(no_gc); for (int i = 0; i < length; i++) { - JSRegExp::Flag flag = JSRegExp::FlagFromChar(flags_content.Get(i)); - // Duplicate or invalid flag. + base::Optional<JSRegExp::Flag> maybe_flag = + JSRegExp::FlagFromChar(flags_content.Get(i)); + if (!maybe_flag.has_value()) return JSRegExp::Flags(0); + JSRegExp::Flag flag = *maybe_flag; + // Duplicate flag. if (value & flag) return JSRegExp::Flags(0); value |= flag; } } *success = true; - // Drop the initially set {kInvalid} bit. - value ^= JSRegExp::kInvalid; return value; } @@ -7852,6 +7897,13 @@ void JSSet::Clear(Isolate* isolate, Handle<JSSet> set) { set->set_table(*table); } +void JSSet::Rehash(Isolate* isolate) { + Handle<OrderedHashSet> table_handle(OrderedHashSet::cast(table()), isolate); + Handle<OrderedHashSet> new_table = + OrderedHashSet::Rehash(isolate, table_handle).ToHandleChecked(); + set_table(*new_table); +} + void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) { Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap(); map->set_table(*table); @@ -7863,6 +7915,13 @@ void JSMap::Clear(Isolate* isolate, Handle<JSMap> map) { map->set_table(*table); } +void JSMap::Rehash(Isolate* isolate) { + Handle<OrderedHashMap> table_handle(OrderedHashMap::cast(table()), isolate); + Handle<OrderedHashMap> new_table = + OrderedHashMap::Rehash(isolate, table_handle).ToHandleChecked(); + set_table(*new_table); +} + void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection, Isolate* isolate) { Handle<EphemeronHashTable> table = EphemeronHashTable::New(isolate, 0); diff --git a/chromium/v8/src/objects/oddball.h b/chromium/v8/src/objects/oddball.h index 4f32e157941..5f0c7ce0015 100644 --- a/chromium/v8/src/objects/oddball.h +++ b/chromium/v8/src/objects/oddball.h @@ -47,6 +47,7 @@ class Oddball : public TorqueGeneratedOddball<Oddball, PrimitiveHeapObject> { static const byte kOptimizedOut = 9; static const byte kStaleRegister = 10; static const byte kSelfReferenceMarker = 10; + static const byte kBasicBlockCountersMarker = 11; static_assert(kStartOfWeakFieldsOffset == kEndOfWeakFieldsOffset, "Ensure BodyDescriptor does not need to handle weak fields."); diff --git a/chromium/v8/src/objects/ordered-hash-table.cc b/chromium/v8/src/objects/ordered-hash-table.cc index cbf3ba373b9..d3250bd92db 100644 --- a/chromium/v8/src/objects/ordered-hash-table.cc +++ b/chromium/v8/src/objects/ordered-hash-table.cc @@ -196,6 +196,13 @@ HeapObject OrderedHashMap::GetEmpty(ReadOnlyRoots ro_roots) { template <class Derived, int entrysize> MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash( + Isolate* isolate, Handle<Derived> table) { + return OrderedHashTable<Derived, entrysize>::Rehash(isolate, table, + table->Capacity()); +} + +template <class Derived, int entrysize> +MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash( Isolate* isolate, Handle<Derived> table, int new_capacity) { DCHECK(!table->IsObsolete()); @@ -250,6 +257,20 @@ MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash(Isolate* isolate, new_capacity); } +MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash( + Isolate* isolate, Handle<OrderedHashSet> table) { + return OrderedHashTable< + OrderedHashSet, OrderedHashSet::kEntrySizeWithoutChain>::Rehash(isolate, + table); +} + +MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash( + Isolate* isolate, Handle<OrderedHashMap> table) { + return OrderedHashTable< + OrderedHashMap, OrderedHashMap::kEntrySizeWithoutChain>::Rehash(isolate, + table); +} + MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash(Isolate* isolate, Handle<OrderedHashMap> table, int new_capacity) { diff --git a/chromium/v8/src/objects/ordered-hash-table.h b/chromium/v8/src/objects/ordered-hash-table.h index b587960432c..5f3c45a110a 100644 --- a/chromium/v8/src/objects/ordered-hash-table.h +++ b/chromium/v8/src/objects/ordered-hash-table.h @@ -138,6 +138,7 @@ class OrderedHashTable : public FixedArray { // The extra +1 is for linking the bucket chains together. static const int kEntrySize = entrysize + 1; + static const int kEntrySizeWithoutChain = entrysize; static const int kChainOffset = entrysize; static const int kNotFound = -1; @@ -200,6 +201,8 @@ class OrderedHashTable : public FixedArray { static MaybeHandle<Derived> Allocate( Isolate* isolate, int capacity, AllocationType allocation = AllocationType::kYoung); + + static MaybeHandle<Derived> Rehash(Isolate* isolate, Handle<Derived> table); static MaybeHandle<Derived> Rehash(Isolate* isolate, Handle<Derived> table, int new_capacity); @@ -244,6 +247,8 @@ class V8_EXPORT_PRIVATE OrderedHashSet static MaybeHandle<OrderedHashSet> Rehash(Isolate* isolate, Handle<OrderedHashSet> table, int new_capacity); + static MaybeHandle<OrderedHashSet> Rehash(Isolate* isolate, + Handle<OrderedHashSet> table); static MaybeHandle<OrderedHashSet> Allocate( Isolate* isolate, int capacity, AllocationType allocation = AllocationType::kYoung); @@ -273,6 +278,8 @@ class V8_EXPORT_PRIVATE OrderedHashMap static MaybeHandle<OrderedHashMap> Rehash(Isolate* isolate, Handle<OrderedHashMap> table, int new_capacity); + static MaybeHandle<OrderedHashMap> Rehash(Isolate* isolate, + Handle<OrderedHashMap> table); Object ValueAt(int entry); // This takes and returns raw Address values containing tagged Object diff --git a/chromium/v8/src/objects/property-descriptor.cc b/chromium/v8/src/objects/property-descriptor.cc index 9c9a71849f4..a14601bc74b 100644 --- a/chromium/v8/src/objects/property-descriptor.cc +++ b/chromium/v8/src/objects/property-descriptor.cc @@ -43,29 +43,29 @@ bool GetPropertyIfPresent(Handle<JSReceiver> receiver, Handle<String> name, bool ToPropertyDescriptorFastPath(Isolate* isolate, Handle<JSReceiver> obj, PropertyDescriptor* desc) { if (!obj->IsJSObject()) return false; - Map map = Handle<JSObject>::cast(obj)->map(); - if (map.instance_type() != JS_OBJECT_TYPE) return false; - if (map.is_access_check_needed()) return false; - if (map.prototype() != *isolate->initial_object_prototype()) return false; + Handle<Map> map(Handle<JSObject>::cast(obj)->map(), isolate); + if (map->instance_type() != JS_OBJECT_TYPE) return false; + if (map->is_access_check_needed()) return false; + if (map->prototype() != *isolate->initial_object_prototype()) return false; // During bootstrapping, the object_function_prototype_map hasn't been // set up yet. if (isolate->bootstrapper()->IsActive()) return false; - if (JSObject::cast(map.prototype()).map() != + if (JSObject::cast(map->prototype()).map() != isolate->native_context()->object_function_prototype_map()) { return false; } // TODO(jkummerow): support dictionary properties? - if (map.is_dictionary_map()) return false; + if (map->is_dictionary_map()) return false; Handle<DescriptorArray> descs = - Handle<DescriptorArray>(map.instance_descriptors(), isolate); - for (InternalIndex i : map.IterateOwnDescriptors()) { + Handle<DescriptorArray>(map->instance_descriptors(), isolate); + for (InternalIndex i : map->IterateOwnDescriptors()) { PropertyDetails details = descs->GetDetails(i); Handle<Object> value; if (details.location() == kField) { if (details.kind() == kData) { value = JSObject::FastPropertyAt(Handle<JSObject>::cast(obj), details.representation(), - FieldIndex::ForDescriptor(map, i)); + FieldIndex::ForDescriptor(*map, i)); } else { DCHECK_EQ(kAccessor, details.kind()); // Bail out to slow path. diff --git a/chromium/v8/src/objects/prototype-info-inl.h b/chromium/v8/src/objects/prototype-info-inl.h index 80efa862c28..8c93b21f24b 100644 --- a/chromium/v8/src/objects/prototype-info-inl.h +++ b/chromium/v8/src/objects/prototype-info-inl.h @@ -20,9 +20,7 @@ namespace v8 { namespace internal { -OBJECT_CONSTRUCTORS_IMPL(PrototypeInfo, Struct) - -CAST_ACCESSOR(PrototypeInfo) +TQ_OBJECT_CONSTRUCTORS_IMPL(PrototypeInfo) Map PrototypeInfo::ObjectCreateMap() { return Map::cast(object_create_map()->GetHeapObjectAssumeWeak()); @@ -39,14 +37,8 @@ bool PrototypeInfo::HasObjectCreateMap() { return cache->IsWeak(); } -ACCESSORS(PrototypeInfo, module_namespace, Object, kJsModuleNamespaceOffset) -ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset) -ACCESSORS(PrototypeInfo, prototype_chain_enum_cache, Object, - kPrototypeChainEnumCacheOffset) -WEAK_ACCESSORS(PrototypeInfo, object_create_map, kObjectCreateMapOffset) -SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset) -SMI_ACCESSORS(PrototypeInfo, bit_field, kBitFieldOffset) -BOOL_ACCESSORS(PrototypeInfo, bit_field, should_be_fast_map, kShouldBeFastBit) +BOOL_ACCESSORS(PrototypeInfo, bit_field, should_be_fast_map, + ShouldBeFastBit::kShift) void PrototypeUsers::MarkSlotEmpty(WeakArrayList array, int index) { DCHECK_GT(index, 0); diff --git a/chromium/v8/src/objects/prototype-info.h b/chromium/v8/src/objects/prototype-info.h index ab238bd9c2f..4e665a39c8d 100644 --- a/chromium/v8/src/objects/prototype-info.h +++ b/chromium/v8/src/objects/prototype-info.h @@ -8,6 +8,7 @@ #include "src/objects/fixed-array.h" #include "src/objects/objects.h" #include "src/objects/struct.h" +#include "torque-generated/bit-fields-tq.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -16,57 +17,29 @@ namespace v8 { namespace internal { // Container for metadata stored on each prototype map. -class PrototypeInfo : public Struct { +class PrototypeInfo + : public TorqueGeneratedPrototypeInfo<PrototypeInfo, Struct> { public: static const int UNREGISTERED = -1; - // [module_namespace]: A backpointer to JSModuleNamespace from its - // PrototypeInfo (or undefined). This field is only used for JSModuleNamespace - // maps. TODO(jkummerow): Figure out if there's a way to store the namespace - // pointer elsewhere to save memory. - DECL_ACCESSORS(module_namespace, Object) - - // [prototype_users]: WeakArrayList containing weak references to maps using - // this prototype, or Smi(0) if uninitialized. - DECL_ACCESSORS(prototype_users, Object) - - DECL_ACCESSORS(prototype_chain_enum_cache, Object) - // [object_create_map]: A field caching the map for Object.create(prototype). static inline void SetObjectCreateMap(Handle<PrototypeInfo> info, Handle<Map> map); inline Map ObjectCreateMap(); inline bool HasObjectCreateMap(); - // [registry_slot]: Slot in prototype's user registry where this user - // is stored. Returns UNREGISTERED if this prototype has not been registered. - inline int registry_slot() const; - inline void set_registry_slot(int slot); - - // [bit_field] - inline int bit_field() const; - inline void set_bit_field(int bit_field); - DECL_BOOLEAN_ACCESSORS(should_be_fast_map) - DECL_CAST(PrototypeInfo) - // Dispatched behavior. DECL_PRINTER(PrototypeInfo) DECL_VERIFIER(PrototypeInfo) - DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, - TORQUE_GENERATED_PROTOTYPE_INFO_FIELDS) - // Bit field usage. - static const int kShouldBeFastBit = 0; + DEFINE_TORQUE_GENERATED_PROTOTYPE_INFO_FLAGS() class BodyDescriptor; - private: - DECL_ACCESSORS(object_create_map, MaybeObject) - - OBJECT_CONSTRUCTORS(PrototypeInfo, Struct); + TQ_OBJECT_CONSTRUCTORS(PrototypeInfo) }; // A growing array with an additional API for marking slots "empty". When adding diff --git a/chromium/v8/src/objects/prototype-info.tq b/chromium/v8/src/objects/prototype-info.tq index 77ffa4358d7..96f65a053ee 100644 --- a/chromium/v8/src/objects/prototype-info.tq +++ b/chromium/v8/src/objects/prototype-info.tq @@ -2,20 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +bitfield struct PrototypeInfoFlags extends uint31 { + should_be_fast: bool: 1 bit; +} + +@generateCppClass extern class PrototypeInfo extends Struct { - js_module_namespace: JSModuleNamespace|Undefined; + // [module_namespace]: A backpointer to JSModuleNamespace from its + // PrototypeInfo (or undefined). This field is only used for JSModuleNamespace + // maps. TODO(jkummerow): Figure out if there's a way to store the namespace + // pointer elsewhere to save memory. + module_namespace: JSModuleNamespace|Undefined; + + // [prototype_users]: WeakArrayList containing weak references to maps using + // this prototype, or Smi(0) if uninitialized. prototype_users: WeakArrayList|Zero; - prototype_chain_enum_cache: FixedArray|Object|Undefined; + + prototype_chain_enum_cache: FixedArray|Zero|Undefined; + + // [registry_slot]: Slot in prototype's user registry where this user + // is stored. Returns UNREGISTERED if this prototype has not been registered. registry_slot: Smi; - validity_cell: Object; - object_create_map: Weak<Map>|Undefined; - bit_field: Smi; -} -extern macro PrototypeInfoMapConstant(): Map; -const kPrototypeInfoMap: Map = PrototypeInfoMapConstant(); + // [object_create_map]: A field caching the map for Object.create(prototype). + object_create_map: Weak<Map>|Undefined; -Cast<PrototypeInfo>(o: HeapObject): PrototypeInfo labels CastError { - if (o.map != kPrototypeInfoMap) goto CastError; - return %RawDownCast<PrototypeInfo>(o); + bit_field: SmiTagged<PrototypeInfoFlags>; } diff --git a/chromium/v8/src/objects/regexp-match-info.tq b/chromium/v8/src/objects/regexp-match-info.tq index 6940ce45836..33825c7c8a9 100644 --- a/chromium/v8/src/objects/regexp-match-info.tq +++ b/chromium/v8/src/objects/regexp-match-info.tq @@ -3,6 +3,7 @@ // found in the LICENSE file. @hasSameInstanceTypeAsParent +@doNotGenerateCast extern class RegExpMatchInfo extends FixedArray { macro GetStartOfCapture(implicit context: Context)(captureIndex: constexpr int31): Smi { diff --git a/chromium/v8/src/objects/scope-info.cc b/chromium/v8/src/objects/scope-info.cc index 4dcd67905c6..b303e039301 100644 --- a/chromium/v8/src/objects/scope-info.cc +++ b/chromium/v8/src/objects/scope-info.cc @@ -215,7 +215,7 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone, scope->private_name_lookup_skips_outer_class()) | HasContextExtensionSlotBit::encode(scope->HasContextExtensionSlot()) | IsReplModeScopeBit::encode(scope->is_repl_mode_scope()) | - HasLocalsBlackListBit::encode(false); + HasLocalsBlockListBit::encode(false); scope_info.SetFlags(flags); scope_info.SetParameterCount(parameter_count); @@ -415,7 +415,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope( ForceContextAllocationBit::encode(false) | PrivateNameLookupSkipsOuterClassBit::encode(false) | HasContextExtensionSlotBit::encode(true) | - IsReplModeScopeBit::encode(false) | HasLocalsBlackListBit::encode(false); + IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false); scope_info->SetFlags(flags); scope_info->SetParameterCount(0); @@ -495,7 +495,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate, ForceContextAllocationBit::encode(false) | PrivateNameLookupSkipsOuterClassBit::encode(false) | HasContextExtensionSlotBit::encode(is_native_context) | - IsReplModeScopeBit::encode(false) | HasLocalsBlackListBit::encode(false); + IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false); scope_info->SetFlags(flags); scope_info->SetParameterCount(parameter_count); scope_info->SetContextLocalCount(context_local_count); @@ -552,34 +552,34 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate, } // static -Handle<ScopeInfo> ScopeInfo::RecreateWithBlackList( - Isolate* isolate, Handle<ScopeInfo> original, Handle<StringSet> blacklist) { +Handle<ScopeInfo> ScopeInfo::RecreateWithBlockList( + Isolate* isolate, Handle<ScopeInfo> original, Handle<StringSet> blocklist) { DCHECK(!original.is_null()); - if (original->HasLocalsBlackList()) return original; + if (original->HasLocalsBlockList()) return original; Handle<ScopeInfo> scope_info = isolate->factory()->NewScopeInfo(original->length() + 1); // Copy the static part first and update the flags to include the - // blacklist field, so {LocalsBlackListIndex} returns the correct value. + // blocklist field, so {LocalsBlockListIndex} returns the correct value. scope_info->CopyElements(isolate, 0, *original, 0, kVariablePartIndex, WriteBarrierMode::UPDATE_WRITE_BARRIER); scope_info->SetFlags( - HasLocalsBlackListBit::update(scope_info->Flags(), true)); + HasLocalsBlockListBit::update(scope_info->Flags(), true)); - // Copy the dynamic part including the provided blacklist: - // 1) copy all the fields up to the blacklist index - // 2) add the blacklist + // Copy the dynamic part including the provided blocklist: + // 1) copy all the fields up to the blocklist index + // 2) add the blocklist // 3) copy the remaining fields scope_info->CopyElements( isolate, kVariablePartIndex, *original, kVariablePartIndex, - scope_info->LocalsBlackListIndex() - kVariablePartIndex, + scope_info->LocalsBlockListIndex() - kVariablePartIndex, WriteBarrierMode::UPDATE_WRITE_BARRIER); - scope_info->set(scope_info->LocalsBlackListIndex(), *blacklist); + scope_info->set(scope_info->LocalsBlockListIndex(), *blocklist); scope_info->CopyElements( - isolate, scope_info->LocalsBlackListIndex() + 1, *original, - scope_info->LocalsBlackListIndex(), - scope_info->length() - scope_info->LocalsBlackListIndex() - 1, + isolate, scope_info->LocalsBlockListIndex() + 1, *original, + scope_info->LocalsBlockListIndex(), + scope_info->length() - scope_info->LocalsBlockListIndex() - 1, WriteBarrierMode::UPDATE_WRITE_BARRIER); return scope_info; } @@ -735,14 +735,14 @@ bool ScopeInfo::IsReplModeScope() const { return IsReplModeScopeBit::decode(Flags()); } -bool ScopeInfo::HasLocalsBlackList() const { +bool ScopeInfo::HasLocalsBlockList() const { if (length() == 0) return false; - return HasLocalsBlackListBit::decode(Flags()); + return HasLocalsBlockListBit::decode(Flags()); } -StringSet ScopeInfo::LocalsBlackList() const { - DCHECK(HasLocalsBlackList()); - return StringSet::cast(get(LocalsBlackListIndex())); +StringSet ScopeInfo::LocalsBlockList() const { + DCHECK(HasLocalsBlockList()); + return StringSet::cast(get(LocalsBlockListIndex())); } bool ScopeInfo::HasContext() const { return ContextLength() > 0; } @@ -984,12 +984,12 @@ int ScopeInfo::OuterScopeInfoIndex() const { return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0); } -int ScopeInfo::LocalsBlackListIndex() const { +int ScopeInfo::LocalsBlockListIndex() const { return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0); } int ScopeInfo::ModuleInfoIndex() const { - return LocalsBlackListIndex() + (HasLocalsBlackList() ? 1 : 0); + return LocalsBlockListIndex() + (HasLocalsBlockList() ? 1 : 0); } int ScopeInfo::ModuleVariableCountIndex() const { diff --git a/chromium/v8/src/objects/scope-info.h b/chromium/v8/src/objects/scope-info.h index 2e7df22562a..73f039e3f60 100644 --- a/chromium/v8/src/objects/scope-info.h +++ b/chromium/v8/src/objects/scope-info.h @@ -200,13 +200,13 @@ class ScopeInfo : public FixedArray { bool is_script_scope() const; - // Returns true if this ScopeInfo has a black list attached containing - // stack allocated local variables. - V8_EXPORT_PRIVATE bool HasLocalsBlackList() const; + // Returns true if this ScopeInfo has a blocklist attached containing stack + // allocated local variables. + V8_EXPORT_PRIVATE bool HasLocalsBlockList() const; // Returns a list of stack-allocated locals of parent scopes. // Used during local debug-evalute to decide whether a context lookup // can continue upwards after checking this scope. - V8_EXPORT_PRIVATE StringSet LocalsBlackList() const; + V8_EXPORT_PRIVATE StringSet LocalsBlockList() const; // Returns true if this ScopeInfo was created for a scope that skips the // closest outer class when resolving private names. @@ -231,12 +231,12 @@ class ScopeInfo : public FixedArray { static Handle<ScopeInfo> CreateForNativeContext(Isolate* isolate); static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate); - // Creates a copy of a {ScopeInfo} but with the provided locals blacklist + // Creates a copy of a {ScopeInfo} but with the provided locals blocklist // attached. Does nothing if the original {ScopeInfo} already has a field - // for a blacklist reserved. - V8_EXPORT_PRIVATE static Handle<ScopeInfo> RecreateWithBlackList( + // for a blocklist reserved. + V8_EXPORT_PRIVATE static Handle<ScopeInfo> RecreateWithBlockList( Isolate* isolate, Handle<ScopeInfo> original, - Handle<StringSet> blacklist); + Handle<StringSet> blocklist); // Serializes empty scope info. V8_EXPORT_PRIVATE static ScopeInfo Empty(Isolate* isolate); @@ -302,7 +302,7 @@ class ScopeInfo : public FixedArray { // the scope belongs to a function or script. // 8. OuterScopeInfoIndex: // The outer scope's ScopeInfo or the hole if there's none. - // 9. LocalsBlackList: List of stack allocated local variables. Used by + // 9. LocalsBlockList: List of stack allocated local variables. Used by // debug evaluate to properly abort variable lookup when a name clashes // with a stack allocated local that can't be materialized. // 10. SourceTextModuleInfo, ModuleVariableCount, and ModuleVariables: @@ -317,7 +317,7 @@ class ScopeInfo : public FixedArray { int InferredFunctionNameIndex() const; int PositionInfoIndex() const; int OuterScopeInfoIndex() const; - V8_EXPORT_PRIVATE int LocalsBlackListIndex() const; + V8_EXPORT_PRIVATE int LocalsBlockListIndex() const; int ModuleInfoIndex() const; int ModuleVariableCountIndex() const; int ModuleVariablesIndex() const; @@ -354,7 +354,7 @@ class ScopeInfo : public FixedArray { friend std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var); OBJECT_CONSTRUCTORS(ScopeInfo, FixedArray); - FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlacklistWorks); + FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlocklistWorks); }; std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var); diff --git a/chromium/v8/src/objects/scope-info.tq b/chromium/v8/src/objects/scope-info.tq index cb8ead30abb..746c8711717 100644 --- a/chromium/v8/src/objects/scope-info.tq +++ b/chromium/v8/src/objects/scope-info.tq @@ -40,5 +40,5 @@ bitfield struct ScopeFlags extends uint32 { private_name_lookup_skips_outer_class: bool: 1 bit; has_context_extension_slot: bool: 1 bit; is_repl_mode_scope: bool: 1 bit; - has_locals_black_list: bool: 1 bit; + has_locals_block_list: bool: 1 bit; } diff --git a/chromium/v8/src/objects/script-inl.h b/chromium/v8/src/objects/script-inl.h index 1e8b83798cb..ce0bd80a6dc 100644 --- a/chromium/v8/src/objects/script-inl.h +++ b/chromium/v8/src/objects/script-inl.h @@ -17,29 +17,16 @@ namespace v8 { namespace internal { -OBJECT_CONSTRUCTORS_IMPL(Script, Struct) +TQ_OBJECT_CONSTRUCTORS_IMPL(Script) NEVER_READ_ONLY_SPACE_IMPL(Script) -CAST_ACCESSOR(Script) - -ACCESSORS(Script, source, Object, kSourceOffset) -ACCESSORS(Script, name, Object, kNameOffset) -SMI_ACCESSORS(Script, id, kIdOffset) -SMI_ACCESSORS(Script, line_offset, kLineOffsetOffset) -SMI_ACCESSORS(Script, column_offset, kColumnOffsetOffset) -ACCESSORS(Script, context_data, Object, kContextOffset) SMI_ACCESSORS(Script, type, kScriptTypeOffset) -ACCESSORS(Script, line_ends, Object, kLineEndsOffset) ACCESSORS_CHECKED(Script, eval_from_shared_or_wrapped_arguments, Object, kEvalFromSharedOrWrappedArgumentsOffset, this->type() != TYPE_WASM) SMI_ACCESSORS_CHECKED(Script, eval_from_position, kEvalFromPositionOffset, this->type() != TYPE_WASM) -SMI_ACCESSORS(Script, flags, kFlagsOffset) -ACCESSORS(Script, source_url, Object, kSourceUrlOffset) -ACCESSORS(Script, source_mapping_url, Object, kSourceMappingUrlOffset) -ACCESSORS(Script, host_defined_options, FixedArray, kHostDefinedOptionsOffset) ACCESSORS_CHECKED(Script, wasm_breakpoint_infos, FixedArray, kEvalFromSharedOrWrappedArgumentsOffset, this->type() == TYPE_WASM) @@ -100,39 +87,30 @@ wasm::NativeModule* Script::wasm_native_module() const { } Script::CompilationType Script::compilation_type() { - return BooleanBit::get(flags(), kCompilationTypeBit) ? COMPILATION_TYPE_EVAL - : COMPILATION_TYPE_HOST; + return CompilationTypeBit::decode(flags()); } void Script::set_compilation_type(CompilationType type) { - set_flags(BooleanBit::set(flags(), kCompilationTypeBit, - type == COMPILATION_TYPE_EVAL)); + set_flags(CompilationTypeBit::update(flags(), type)); } Script::CompilationState Script::compilation_state() { - return BooleanBit::get(flags(), kCompilationStateBit) - ? COMPILATION_STATE_COMPILED - : COMPILATION_STATE_INITIAL; + return CompilationStateBit::decode(flags()); } void Script::set_compilation_state(CompilationState state) { - set_flags(BooleanBit::set(flags(), kCompilationStateBit, - state == COMPILATION_STATE_COMPILED)); + set_flags(CompilationStateBit::update(flags(), state)); } -bool Script::is_repl_mode() const { - return BooleanBit::get(flags(), kREPLModeBit); -} +bool Script::is_repl_mode() const { return IsReplModeBit::decode(flags()); } void Script::set_is_repl_mode(bool value) { - set_flags(BooleanBit::set(flags(), kREPLModeBit, value)); + set_flags(IsReplModeBit::update(flags(), value)); } ScriptOriginOptions Script::origin_options() { - return ScriptOriginOptions((flags() & kOriginOptionsMask) >> - kOriginOptionsShift); + return ScriptOriginOptions(OriginOptionsBits::decode(flags())); } void Script::set_origin_options(ScriptOriginOptions origin_options) { - DCHECK(!(origin_options.Flags() & ~((1 << kOriginOptionsSize) - 1))); - set_flags((flags() & ~kOriginOptionsMask) | - (origin_options.Flags() << kOriginOptionsShift)); + DCHECK(!(origin_options.Flags() & ~((1 << OriginOptionsBits::kSize) - 1))); + set_flags(OriginOptionsBits::update(flags(), origin_options.Flags())); } bool Script::HasValidSource() { diff --git a/chromium/v8/src/objects/script.h b/chromium/v8/src/objects/script.h index d5876de2e0a..9ce44c770fd 100644 --- a/chromium/v8/src/objects/script.h +++ b/chromium/v8/src/objects/script.h @@ -11,6 +11,7 @@ #include "src/objects/fixed-array.h" #include "src/objects/objects.h" #include "src/objects/struct.h" +#include "torque-generated/bit-fields-tq.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -20,7 +21,7 @@ namespace v8 { namespace internal { // Script describes a script which has been added to the VM. -class Script : public Struct { +class Script : public TorqueGeneratedScript<Script, Struct> { public: // Script ID used for temporary scripts, which shouldn't be added to the // script list. @@ -45,31 +46,9 @@ class Script : public Struct { COMPILATION_STATE_COMPILED = 1 }; - // [source]: the script source. - DECL_ACCESSORS(source, Object) - - // [name]: the script name. - DECL_ACCESSORS(name, Object) - - // [id]: the script id. - DECL_INT_ACCESSORS(id) - - // [line_offset]: script line offset in resource from where it was extracted. - DECL_INT_ACCESSORS(line_offset) - - // [column_offset]: script column offset in resource from where it was - // extracted. - DECL_INT_ACCESSORS(column_offset) - - // [context_data]: context data for the context this script was compiled in. - DECL_ACCESSORS(context_data, Object) - // [type]: the script type. DECL_INT_ACCESSORS(type) - // [line_ends]: FixedArray of line ends positions. - DECL_ACCESSORS(line_ends, Object) - DECL_ACCESSORS(eval_from_shared_or_wrapped_arguments, Object) // [eval_from_shared]: for eval scripts the shared function info for the @@ -95,15 +74,6 @@ class Script : public Struct { // function infos created from this script. DECL_ACCESSORS(shared_function_infos, WeakFixedArray) - // [flags]: Holds an exciting bitfield. - DECL_INT_ACCESSORS(flags) - - // [source_url]: sourceURL from magic comment - DECL_ACCESSORS(source_url, Object) - - // [source_mapping_url]: sourceMappingURL magic comment - DECL_ACCESSORS(source_mapping_url, Object) - // [wasm_breakpoint_infos]: the list of {BreakPointInfo} objects describing // all WebAssembly breakpoints for modules/instances managed via this script. // This must only be called if the type of this script is TYPE_WASM. @@ -120,9 +90,6 @@ class Script : public Struct { // This must only be called if the type of this script is TYPE_WASM. DECL_ACCESSORS(wasm_weak_instance_list, WeakArrayList) - // [host_defined_options]: Options defined by the embedder. - DECL_ACCESSORS(host_defined_options, FixedArray) - // [compilation_type]: how the the script was compiled. Encoded in the // 'flags' field. inline CompilationType compilation_type(); @@ -144,8 +111,6 @@ class Script : public Struct { inline v8::ScriptOriginOptions origin_options(); inline void set_origin_options(ScriptOriginOptions origin_options); - DECL_CAST(Script) - // If script source is an external string, check that the underlying // resource is accessible. Otherwise, always return true. inline bool HasValidSource(); @@ -218,20 +183,11 @@ class Script : public Struct { DECL_PRINTER(Script) DECL_VERIFIER(Script) - DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, - TORQUE_GENERATED_SCRIPT_FIELDS) - private: // Bit positions in the flags field. - static const int kCompilationTypeBit = 0; - static const int kCompilationStateBit = 1; - static const int kREPLModeBit = 2; - static const int kOriginOptionsShift = 3; - static const int kOriginOptionsSize = 4; - static const int kOriginOptionsMask = ((1 << kOriginOptionsSize) - 1) - << kOriginOptionsShift; - - OBJECT_CONSTRUCTORS(Script, Struct); + DEFINE_TORQUE_GENERATED_SCRIPT_FLAGS() + + TQ_OBJECT_CONSTRUCTORS(Script) }; } // namespace internal diff --git a/chromium/v8/src/objects/script.tq b/chromium/v8/src/objects/script.tq index 5e68c870239..cac5ceb3ba4 100644 --- a/chromium/v8/src/objects/script.tq +++ b/chromium/v8/src/objects/script.tq @@ -2,20 +2,56 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +type CompilationType extends int32 constexpr 'Script::CompilationType'; +type CompilationState extends int32 constexpr 'Script::CompilationState'; + +bitfield struct ScriptFlags extends uint31 { + compilation_type: CompilationType: 1 bit; + compilation_state: CompilationState: 1 bit; + is_repl_mode: bool: 1 bit; + origin_options: int32: 4 bit; +} + +@generateCppClass extern class Script extends Struct { - source: Object; + // [source]: the script source. + source: String|Undefined; + + // [name]: the script name. name: Object; + + // [line_offset]: script line offset in resource from where it was extracted. line_offset: Smi; + + // [column_offset]: script column offset in resource from where it was + // extracted. column_offset: Smi; - context: Object; + + // [context_data]: context data for the context this script was compiled in. + context_data: Smi|Undefined|Symbol; + script_type: Smi; - line_ends: Object; + + // [line_ends]: FixedArray of line ends positions. + line_ends: FixedArray|Undefined; + + // [id]: the script id. id: Smi; - eval_from_shared_or_wrapped_arguments: Object; + + eval_from_shared_or_wrapped_arguments: SharedFunctionInfo|FixedArray| + Undefined; eval_from_position: Smi|Foreign; // Smi or Managed<wasm::NativeModule> - shared_function_infos: Object; - flags: Smi; - source_url: Object; + shared_function_infos: WeakFixedArray|WeakArrayList; + + // [flags]: Holds an exciting bitfield. + flags: SmiTagged<ScriptFlags>; + + // [source_url]: sourceURL from magic comment + source_url: String|Undefined; + + // [source_mapping_url]: sourceMappingURL magic comment source_mapping_url: Object; - host_defined_options: Object; + + // [host_defined_options]: Options defined by the embedder. + host_defined_options: FixedArray; } diff --git a/chromium/v8/src/objects/shared-function-info-inl.h b/chromium/v8/src/objects/shared-function-info-inl.h index 169e3c0c156..28274b71c17 100644 --- a/chromium/v8/src/objects/shared-function-info-inl.h +++ b/chromium/v8/src/objects/shared-function-info-inl.h @@ -97,6 +97,8 @@ NEVER_READ_ONLY_SPACE_IMPL(SharedFunctionInfo) CAST_ACCESSOR(SharedFunctionInfo) DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object) +SYNCHRONIZED_ACCESSORS(SharedFunctionInfo, function_data, Object, + kFunctionDataOffset) ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object, kNameOrScopeInfoOffset) ACCESSORS(SharedFunctionInfo, script_or_debug_info, HeapObject, @@ -168,15 +170,6 @@ AbstractCode SharedFunctionInfo::abstract_code() { } } -Object SharedFunctionInfo::function_data() const { - return ACQUIRE_READ_FIELD(*this, kFunctionDataOffset); -} - -void SharedFunctionInfo::set_function_data(Object data, WriteBarrierMode mode) { - RELEASE_WRITE_FIELD(*this, kFunctionDataOffset, data); - CONDITIONAL_WRITE_BARRIER(*this, kFunctionDataOffset, data, mode); -} - int SharedFunctionInfo::function_token_position() const { int offset = raw_function_token_offset(); if (offset == kFunctionTokenOutOfRange) { diff --git a/chromium/v8/src/objects/shared-function-info.tq b/chromium/v8/src/objects/shared-function-info.tq index f37cc250bc2..c29060714a7 100644 --- a/chromium/v8/src/objects/shared-function-info.tq +++ b/chromium/v8/src/objects/shared-function-info.tq @@ -77,3 +77,12 @@ extern class UncompiledDataWithoutPreparseData extends UncompiledData { extern class UncompiledDataWithPreparseData extends UncompiledData { preparse_data: PreparseData; } + +@export +class OnHeapBasicBlockProfilerData extends HeapObject { + block_rpo_numbers: ByteArray; // Stored as 4-byte ints + counts: ByteArray; // Stored as 4-byte ints + name: String; + schedule: String; + code: String; +} diff --git a/chromium/v8/src/objects/smi.h b/chromium/v8/src/objects/smi.h index 9468f56e527..44cd5f7446e 100644 --- a/chromium/v8/src/objects/smi.h +++ b/chromium/v8/src/objects/smi.h @@ -26,9 +26,7 @@ class Smi : public Object { // in that we want them to be constexprs. constexpr Smi() : Object() {} explicit constexpr Smi(Address ptr) : Object(ptr) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK(HAS_SMI_TAG(ptr)); -#endif + CONSTEXPR_DCHECK(HAS_SMI_TAG(ptr)); } // Returns the integer value. @@ -45,9 +43,7 @@ class Smi : public Object { // Convert a value to a Smi object. static inline constexpr Smi FromInt(int value) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK(Smi::IsValid(value)); -#endif + CONSTEXPR_DCHECK(Smi::IsValid(value)); return Smi(Internals::IntToSmi(value)); } @@ -73,10 +69,8 @@ class Smi : public Object { // Returns whether value can be represented in a Smi. static inline bool constexpr IsValid(intptr_t value) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK_EQ(Internals::IsValidSmi(value), - value >= kMinValue && value <= kMaxValue); -#endif + CONSTEXPR_DCHECK(Internals::IsValidSmi(value) == + (value >= kMinValue && value <= kMaxValue)); return Internals::IsValidSmi(value); } diff --git a/chromium/v8/src/objects/source-text-module.h b/chromium/v8/src/objects/source-text-module.h index 7e64668a7ed..91970812543 100644 --- a/chromium/v8/src/objects/source-text-module.h +++ b/chromium/v8/src/objects/source-text-module.h @@ -7,6 +7,7 @@ #include "src/objects/module.h" #include "src/objects/promise.h" +#include "torque-generated/bit-fields-tq.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -91,8 +92,7 @@ class SourceTextModule inline void DecrementPendingAsyncDependencies(); // Bits for flags. - static const int kAsyncBit = 0; - static const int kAsyncEvaluatingBit = 1; + DEFINE_TORQUE_GENERATED_SOURCE_TEXT_MODULE_FLAGS() // async_evaluating, top_level_capability, pending_async_dependencies, and // async_parent_modules are used exclusively during evaluation of async diff --git a/chromium/v8/src/objects/source-text-module.tq b/chromium/v8/src/objects/source-text-module.tq index fda0138695f..185443414dd 100644 --- a/chromium/v8/src/objects/source-text-module.tq +++ b/chromium/v8/src/objects/source-text-module.tq @@ -4,6 +4,11 @@ type SourceTextModuleInfo extends FixedArray; +bitfield struct SourceTextModuleFlags extends uint31 { + async: bool: 1 bit; + async_evaluating: bool: 1 bit; +} + @generateCppClass extern class SourceTextModule extends Module { // The code representing this module, or an abstraction thereof. @@ -39,7 +44,7 @@ extern class SourceTextModule extends Module { // The number of currently evaluating async dependencies of this module. pending_async_dependencies: Smi; - flags: Smi; + flags: SmiTagged<SourceTextModuleFlags>; } @generateCppClass diff --git a/chromium/v8/src/objects/stack-frame-info-inl.h b/chromium/v8/src/objects/stack-frame-info-inl.h index 36236f576ba..820d4324a2f 100644 --- a/chromium/v8/src/objects/stack-frame-info-inl.h +++ b/chromium/v8/src/objects/stack-frame-info-inl.h @@ -18,37 +18,22 @@ namespace v8 { namespace internal { -OBJECT_CONSTRUCTORS_IMPL(StackFrameInfo, Struct) +TQ_OBJECT_CONSTRUCTORS_IMPL(StackFrameInfo) NEVER_READ_ONLY_SPACE_IMPL(StackFrameInfo) -CAST_ACCESSOR(StackFrameInfo) - -SMI_ACCESSORS(StackFrameInfo, line_number, kLineNumberOffset) -SMI_ACCESSORS(StackFrameInfo, column_number, kColumnNumberOffset) -SMI_ACCESSORS(StackFrameInfo, script_id, kScriptIdOffset) -SMI_ACCESSORS(StackFrameInfo, wasm_function_index, kWasmFunctionIndexOffset) -SMI_ACCESSORS(StackFrameInfo, promise_all_index, kPromiseAllIndexOffset) -SMI_ACCESSORS_CHECKED(StackFrameInfo, function_offset, kPromiseAllIndexOffset, - is_wasm()) -ACCESSORS(StackFrameInfo, script_name, Object, kScriptNameOffset) -ACCESSORS(StackFrameInfo, script_name_or_source_url, Object, - kScriptNameOrSourceUrlOffset) -ACCESSORS(StackFrameInfo, function_name, Object, kFunctionNameOffset) -ACCESSORS(StackFrameInfo, method_name, Object, kMethodNameOffset) -ACCESSORS(StackFrameInfo, type_name, Object, kTypeNameOffset) -ACCESSORS(StackFrameInfo, eval_origin, Object, kEvalOriginOffset) -ACCESSORS(StackFrameInfo, wasm_module_name, Object, kWasmModuleNameOffset) -ACCESSORS(StackFrameInfo, wasm_instance, Object, kWasmInstanceOffset) -SMI_ACCESSORS(StackFrameInfo, flag, kFlagOffset) -BOOL_ACCESSORS(StackFrameInfo, flag, is_eval, kIsEvalBit) -BOOL_ACCESSORS(StackFrameInfo, flag, is_constructor, kIsConstructorBit) -BOOL_ACCESSORS(StackFrameInfo, flag, is_wasm, kIsWasmBit) -BOOL_ACCESSORS(StackFrameInfo, flag, is_asmjs_wasm, kIsAsmJsWasmBit) -BOOL_ACCESSORS(StackFrameInfo, flag, is_user_java_script, kIsUserJavaScriptBit) -BOOL_ACCESSORS(StackFrameInfo, flag, is_toplevel, kIsToplevelBit) -BOOL_ACCESSORS(StackFrameInfo, flag, is_async, kIsAsyncBit) -BOOL_ACCESSORS(StackFrameInfo, flag, is_promise_all, kIsPromiseAllBit) +SMI_ACCESSORS_CHECKED(StackFrameInfo, function_offset, + kPromiseCombinatorIndexOffset, is_wasm()) +BOOL_ACCESSORS(StackFrameInfo, flag, is_eval, IsEvalBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_constructor, IsConstructorBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_wasm, IsWasmBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_asmjs_wasm, IsAsmJsWasmBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_user_java_script, + IsUserJavaScriptBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_toplevel, IsToplevelBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_async, IsAsyncBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_promise_all, IsPromiseAllBit::kShift) +BOOL_ACCESSORS(StackFrameInfo, flag, is_promise_any, IsPromiseAnyBit::kShift) TQ_OBJECT_CONSTRUCTORS_IMPL(StackTraceFrame) NEVER_READ_ONLY_SPACE_IMPL(StackTraceFrame) diff --git a/chromium/v8/src/objects/stack-frame-info.cc b/chromium/v8/src/objects/stack-frame-info.cc index c15ad1031cf..a6797599871 100644 --- a/chromium/v8/src/objects/stack-frame-info.cc +++ b/chromium/v8/src/objects/stack-frame-info.cc @@ -47,8 +47,8 @@ int StackTraceFrame::GetScriptId(Handle<StackTraceFrame> frame) { } // static -int StackTraceFrame::GetPromiseAllIndex(Handle<StackTraceFrame> frame) { - return GetFrameInfo(frame)->promise_all_index(); +int StackTraceFrame::GetPromiseCombinatorIndex(Handle<StackTraceFrame> frame) { + return GetFrameInfo(frame)->promise_combinator_index(); } // static @@ -169,6 +169,11 @@ bool StackTraceFrame::IsPromiseAll(Handle<StackTraceFrame> frame) { } // static +bool StackTraceFrame::IsPromiseAny(Handle<StackTraceFrame> frame) { + return GetFrameInfo(frame)->is_promise_any(); +} + +// static Handle<StackFrameInfo> StackTraceFrame::GetFrameInfo( Handle<StackTraceFrame> frame) { if (frame->frame_info().IsUndefined()) InitializeFrameInfo(frame); @@ -326,6 +331,7 @@ void SerializeJSStackFrame(Isolate* isolate, Handle<StackTraceFrame> frame, const bool is_toplevel = StackTraceFrame::IsToplevel(frame); const bool is_async = StackTraceFrame::IsAsync(frame); const bool is_promise_all = StackTraceFrame::IsPromiseAll(frame); + const bool is_promise_any = StackTraceFrame::IsPromiseAny(frame); const bool is_constructor = StackTraceFrame::IsConstructor(frame); // Note: Keep the {is_method_call} predicate in sync with the corresponding // predicate in factory.cc where the StackFrameInfo is created. @@ -338,7 +344,13 @@ void SerializeJSStackFrame(Isolate* isolate, Handle<StackTraceFrame> frame, } if (is_promise_all) { builder->AppendCString("Promise.all (index "); - builder->AppendInt(StackTraceFrame::GetPromiseAllIndex(frame)); + builder->AppendInt(StackTraceFrame::GetPromiseCombinatorIndex(frame)); + builder->AppendCString(")"); + return; + } + if (is_promise_any) { + builder->AppendCString("Promise.any (index "); + builder->AppendInt(StackTraceFrame::GetPromiseCombinatorIndex(frame)); builder->AppendCString(")"); return; } diff --git a/chromium/v8/src/objects/stack-frame-info.h b/chromium/v8/src/objects/stack-frame-info.h index 83a24c047a9..0da16a80c30 100644 --- a/chromium/v8/src/objects/stack-frame-info.h +++ b/chromium/v8/src/objects/stack-frame-info.h @@ -6,6 +6,7 @@ #define V8_OBJECTS_STACK_FRAME_INFO_H_ #include "src/objects/struct.h" +#include "torque-generated/bit-fields-tq.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -16,24 +17,12 @@ namespace internal { class FrameArray; class WasmInstanceObject; -class StackFrameInfo : public Struct { +class StackFrameInfo + : public TorqueGeneratedStackFrameInfo<StackFrameInfo, Struct> { public: NEVER_READ_ONLY_SPACE - DECL_INT_ACCESSORS(line_number) - DECL_INT_ACCESSORS(column_number) - DECL_INT_ACCESSORS(script_id) - DECL_INT_ACCESSORS(wasm_function_index) - DECL_INT_ACCESSORS(promise_all_index) - // Wasm frames only: function_offset instead of promise_all_index. + // Wasm frames only: function_offset instead of promise_combinator_index. DECL_INT_ACCESSORS(function_offset) - DECL_ACCESSORS(script_name, Object) - DECL_ACCESSORS(script_name_or_source_url, Object) - DECL_ACCESSORS(function_name, Object) - DECL_ACCESSORS(method_name, Object) - DECL_ACCESSORS(type_name, Object) - DECL_ACCESSORS(eval_origin, Object) - DECL_ACCESSORS(wasm_module_name, Object) - DECL_ACCESSORS(wasm_instance, Object) DECL_BOOLEAN_ACCESSORS(is_eval) DECL_BOOLEAN_ACCESSORS(is_constructor) DECL_BOOLEAN_ACCESSORS(is_wasm) @@ -42,29 +31,16 @@ class StackFrameInfo : public Struct { DECL_BOOLEAN_ACCESSORS(is_toplevel) DECL_BOOLEAN_ACCESSORS(is_async) DECL_BOOLEAN_ACCESSORS(is_promise_all) - DECL_INT_ACCESSORS(flag) - - DECL_CAST(StackFrameInfo) + DECL_BOOLEAN_ACCESSORS(is_promise_any) // Dispatched behavior. DECL_PRINTER(StackFrameInfo) - DECL_VERIFIER(StackFrameInfo) - - DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize, - TORQUE_GENERATED_STACK_FRAME_INFO_FIELDS) private: // Bit position in the flag, from least significant bit position. - static const int kIsEvalBit = 0; - static const int kIsConstructorBit = 1; - static const int kIsWasmBit = 2; - static const int kIsAsmJsWasmBit = 3; - static const int kIsUserJavaScriptBit = 4; - static const int kIsToplevelBit = 5; - static const int kIsAsyncBit = 6; - static const int kIsPromiseAllBit = 7; - - OBJECT_CONSTRUCTORS(StackFrameInfo, Struct); + DEFINE_TORQUE_GENERATED_STACK_FRAME_INFO_FLAGS() + + TQ_OBJECT_CONSTRUCTORS(StackFrameInfo) }; // This class is used to lazily initialize a StackFrameInfo object from @@ -85,7 +61,7 @@ class StackTraceFrame static int GetColumnNumber(Handle<StackTraceFrame> frame); static int GetOneBasedColumnNumber(Handle<StackTraceFrame> frame); static int GetScriptId(Handle<StackTraceFrame> frame); - static int GetPromiseAllIndex(Handle<StackTraceFrame> frame); + static int GetPromiseCombinatorIndex(Handle<StackTraceFrame> frame); static int GetFunctionOffset(Handle<StackTraceFrame> frame); static int GetWasmFunctionIndex(Handle<StackTraceFrame> frame); @@ -107,6 +83,7 @@ class StackTraceFrame static bool IsToplevel(Handle<StackTraceFrame> frame); static bool IsAsync(Handle<StackTraceFrame> frame); static bool IsPromiseAll(Handle<StackTraceFrame> frame); + static bool IsPromiseAny(Handle<StackTraceFrame> frame); private: static Handle<StackFrameInfo> GetFrameInfo(Handle<StackTraceFrame> frame); diff --git a/chromium/v8/src/objects/stack-frame-info.tq b/chromium/v8/src/objects/stack-frame-info.tq index 801e2bc5a0d..b8b218bce14 100644 --- a/chromium/v8/src/objects/stack-frame-info.tq +++ b/chromium/v8/src/objects/stack-frame-info.tq @@ -2,21 +2,34 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +bitfield struct StackFrameInfoFlags extends uint31 { + is_eval: bool: 1 bit; + is_constructor: bool: 1 bit; + is_wasm: bool: 1 bit; + is_asm_js_wasm: bool: 1 bit; + is_user_java_script: bool: 1 bit; + is_toplevel: bool: 1 bit; + is_async: bool: 1 bit; + is_promise_all: bool: 1 bit; + is_promise_any: bool: 1 bit; +} + +@generateCppClass extern class StackFrameInfo extends Struct { line_number: Smi; column_number: Smi; - promise_all_index: Smi; + promise_combinator_index: Smi; script_id: Smi; wasm_function_index: Smi; - script_name: String|Null|Undefined; - script_name_or_source_url: String|Null|Undefined; + script_name: Object; + script_name_or_source_url: Object; function_name: String|Null|Undefined; method_name: String|Null|Undefined; type_name: String|Null|Undefined; eval_origin: String|Null|Undefined; wasm_module_name: String|Null|Undefined; wasm_instance: WasmInstanceObject|Null|Undefined; - flag: Smi; + flag: SmiTagged<StackFrameInfoFlags>; } @generateCppClass diff --git a/chromium/v8/src/objects/string-table.h b/chromium/v8/src/objects/string-table.h index 76f29a01e38..418eee0281d 100644 --- a/chromium/v8/src/objects/string-table.h +++ b/chromium/v8/src/objects/string-table.h @@ -113,7 +113,7 @@ class StringSet : public HashTable<StringSet, StringSetShape> { public: V8_EXPORT_PRIVATE static Handle<StringSet> New(Isolate* isolate); V8_EXPORT_PRIVATE static Handle<StringSet> Add(Isolate* isolate, - Handle<StringSet> blacklist, + Handle<StringSet> stringset, Handle<String> name); V8_EXPORT_PRIVATE bool Has(Isolate* isolate, Handle<String> name); diff --git a/chromium/v8/src/objects/string.cc b/chromium/v8/src/objects/string.cc index 90abd00ebac..9d07740e19c 100644 --- a/chromium/v8/src/objects/string.cc +++ b/chromium/v8/src/objects/string.cc @@ -298,69 +298,60 @@ bool String::SupportsExternalization() { return !isolate->heap()->IsInGCPostProcessing(); } -void String::StringShortPrint(StringStream* accumulator, bool show_details) { - const char* internalized_marker = this->IsInternalizedString() ? "#" : ""; - - int len = length(); - if (len > kMaxShortPrintLength) { - accumulator->Add("<Very long string[%s%u]>", internalized_marker, len); - return; +const char* String::PrefixForDebugPrint() const { + StringShape shape(*this); + if (IsTwoByteRepresentation()) { + StringShape shape(*this); + if (shape.IsInternalized()) { + return "u#"; + } else if (shape.IsCons()) { + return "uc\""; + } else if (shape.IsThin()) { + return "u>\""; + } else { + return "u\""; + } + } else { + StringShape shape(*this); + if (shape.IsInternalized()) { + return "#"; + } else if (shape.IsCons()) { + return "c\""; + } else if (shape.IsThin()) { + return ">\""; + } else { + return "\""; + } } + UNREACHABLE(); +} +const char* String::SuffixForDebugPrint() const { + StringShape shape(*this); + if (shape.IsInternalized()) return ""; + return "\""; +} + +void String::StringShortPrint(StringStream* accumulator) { if (!LooksValid()) { accumulator->Add("<Invalid String>"); return; } - StringCharacterStream stream(*this); + const int len = length(); + accumulator->Add("<String[%u]: ", len); + accumulator->Add(PrefixForDebugPrint()); - bool truncated = false; if (len > kMaxShortPrintLength) { - len = kMaxShortPrintLength; - truncated = true; + accumulator->Add("...<truncated>>"); + accumulator->Add(SuffixForDebugPrint()); + accumulator->Put('>'); + return; } - bool one_byte = true; - for (int i = 0; i < len; i++) { - uint16_t c = stream.GetNext(); - if (c < 32 || c >= 127) { - one_byte = false; - } - } - stream.Reset(*this); - if (one_byte) { - if (show_details) - accumulator->Add("<String[%s%u]: ", internalized_marker, length()); - for (int i = 0; i < len; i++) { - accumulator->Put(static_cast<char>(stream.GetNext())); - } - if (show_details) accumulator->Put('>'); - } else { - // Backslash indicates that the string contains control - // characters and that backslashes are therefore escaped. - if (show_details) - accumulator->Add("<String[%s%u]\\: ", internalized_marker, length()); - for (int i = 0; i < len; i++) { - uint16_t c = stream.GetNext(); - if (c == '\n') { - accumulator->Add("\\n"); - } else if (c == '\r') { - accumulator->Add("\\r"); - } else if (c == '\\') { - accumulator->Add("\\\\"); - } else if (c < 32 || c > 126) { - accumulator->Add("\\x%02x", c); - } else { - accumulator->Put(static_cast<char>(c)); - } - } - if (truncated) { - accumulator->Put('.'); - accumulator->Put('.'); - accumulator->Put('.'); - } - if (show_details) accumulator->Put('>'); - } + PrintUC16(accumulator, 0, len); + accumulator->Add(SuffixForDebugPrint()); + accumulator->Put('>'); } void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT @@ -371,6 +362,25 @@ void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT } } +void String::PrintUC16(StringStream* accumulator, int start, int end) { + if (end < 0) end = length(); + StringCharacterStream stream(*this, start); + for (int i = start; i < end && stream.HasMore(); i++) { + uint16_t c = stream.GetNext(); + if (c == '\n') { + accumulator->Add("\\n"); + } else if (c == '\r') { + accumulator->Add("\\r"); + } else if (c == '\\') { + accumulator->Add("\\\\"); + } else if (!std::isprint(c)) { + accumulator->Add("\\x%02x", c); + } else { + accumulator->Put(static_cast<char>(c)); + } + } +} + // static Handle<String> String::Trim(Isolate* isolate, Handle<String> string, TrimMode mode) { @@ -410,9 +420,9 @@ int32_t String::ToArrayIndex(Address addr) { bool String::LooksValid() { // TODO(leszeks): Maybe remove this check entirely, Heap::Contains uses // basically the same logic as the way we access the heap in the first place. - MemoryChunk* chunk = MemoryChunk::FromHeapObject(*this); // RO_SPACE objects should always be valid. if (ReadOnlyHeap::Contains(*this)) return true; + BasicMemoryChunk* chunk = BasicMemoryChunk::FromHeapObject(*this); if (chunk->heap() == nullptr) return false; return chunk->heap()->Contains(*this); } diff --git a/chromium/v8/src/objects/string.h b/chromium/v8/src/objects/string.h index f9f92a53dd1..7c275cc6cbf 100644 --- a/chromium/v8/src/objects/string.h +++ b/chromium/v8/src/objects/string.h @@ -352,9 +352,20 @@ class String : public TorqueGeneratedString<String, Name> { // For use during stack traces. Performs rudimentary sanity check. bool LooksValid(); - // Dispatched behavior. - void StringShortPrint(StringStream* accumulator, bool show_details = true); + // Printing utility functions. + // - PrintUC16 prints the raw string contents to the given stream. + // Non-printable characters are formatted as hex, but otherwise the string + // is printed as-is. + // - StringShortPrint and StringPrint have extra formatting: they add a + // prefix and suffix depending on the string kind, may add other information + // such as the string heap object address, may truncate long strings, etc. + const char* PrefixForDebugPrint() const; + const char* SuffixForDebugPrint() const; + void StringShortPrint(StringStream* accumulator); void PrintUC16(std::ostream& os, int start = 0, int end = -1); // NOLINT + void PrintUC16(StringStream* accumulator, int start, int end); + + // Dispatched behavior. #if defined(DEBUG) || defined(OBJECT_PRINT) char* ToAsciiArray(); #endif diff --git a/chromium/v8/src/objects/string.tq b/chromium/v8/src/objects/string.tq index 7d3f250964d..6c4ff691c0c 100644 --- a/chromium/v8/src/objects/string.tq +++ b/chromium/v8/src/objects/string.tq @@ -11,6 +11,7 @@ extern class String extends Name { @generateCppClass @generateBodyDescriptor +@doNotGenerateCast extern class ConsString extends String { first: String; second: String; @@ -18,35 +19,46 @@ extern class ConsString extends String { @abstract @generateBodyDescriptor +@doNotGenerateCast extern class ExternalString extends String { resource: ExternalPointer; resource_data: ExternalPointer; } -extern class ExternalOneByteString extends ExternalString {} -extern class ExternalTwoByteString extends ExternalString {} +@doNotGenerateCast +extern class ExternalOneByteString extends ExternalString { +} + +@doNotGenerateCast +extern class ExternalTwoByteString extends ExternalString { +} @generateCppClass +@doNotGenerateCast extern class InternalizedString extends String { } @abstract @generateCppClass +@doNotGenerateCast extern class SeqString extends String { } @generateCppClass @generateBodyDescriptor +@doNotGenerateCast extern class SeqOneByteString extends SeqString { chars[length]: char8; } @generateCppClass @generateBodyDescriptor +@doNotGenerateCast extern class SeqTwoByteString extends SeqString { chars[length]: char16; } @generateCppClass @generateBodyDescriptor +@doNotGenerateCast extern class SlicedString extends String { parent: String; offset: Smi; @@ -54,6 +66,7 @@ extern class SlicedString extends String { @generateCppClass @generateBodyDescriptor +@doNotGenerateCast extern class ThinString extends String { actual: String; } diff --git a/chromium/v8/src/objects/tagged-impl.h b/chromium/v8/src/objects/tagged-impl.h index 036075fc2d6..9ef8b58d991 100644 --- a/chromium/v8/src/objects/tagged-impl.h +++ b/chromium/v8/src/objects/tagged-impl.h @@ -88,9 +88,8 @@ class TaggedImpl { // Returns true if this tagged value is a strong pointer to a HeapObject. constexpr inline bool IsStrong() const { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK_IMPLIES(!kCanBeWeak, !IsSmi() == HAS_STRONG_HEAP_OBJECT_TAG(ptr_)); -#endif + CONSTEXPR_DCHECK(kCanBeWeak || + (!IsSmi() == HAS_STRONG_HEAP_OBJECT_TAG(ptr_))); return kCanBeWeak ? HAS_STRONG_HEAP_OBJECT_TAG(ptr_) : !IsSmi(); } diff --git a/chromium/v8/src/objects/tagged-index.h b/chromium/v8/src/objects/tagged-index.h index c7d6a85a0d1..e8cfbc76087 100644 --- a/chromium/v8/src/objects/tagged-index.h +++ b/chromium/v8/src/objects/tagged-index.h @@ -38,9 +38,7 @@ class TaggedIndex : public Object { // special in that we want them to be constexprs. constexpr TaggedIndex() : Object() {} explicit constexpr TaggedIndex(Address ptr) : Object(ptr) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK(HAS_SMI_TAG(ptr)); -#endif + CONSTEXPR_DCHECK(HAS_SMI_TAG(ptr)); } // Returns the integer value. @@ -51,9 +49,7 @@ class TaggedIndex : public Object { // Convert a value to a TaggedIndex object. static inline TaggedIndex FromIntptr(intptr_t value) { -#if V8_HAS_CXX14_CONSTEXPR - DCHECK(TaggedIndex::IsValid(value)); -#endif + CONSTEXPR_DCHECK(TaggedIndex::IsValid(value)); return TaggedIndex((static_cast<Address>(value) << kSmiTagSize) | kSmiTag); } diff --git a/chromium/v8/src/objects/template.tq b/chromium/v8/src/objects/template.tq index d3e251aa165..1336fb19ba7 100644 --- a/chromium/v8/src/objects/template.tq +++ b/chromium/v8/src/objects/template.tq @@ -5,46 +5,56 @@ @abstract @generateCppClass extern class TemplateInfo extends Struct { - tag: Object; - serial_number: Object; + tag: Smi; + serial_number: Smi; number_of_properties: Smi; - property_list: Object; - property_accessors: Object; + property_list: TemplateList|Undefined; + property_accessors: TemplateList|Undefined; } @generateCppClass +@generatePrint extern class FunctionTemplateRareData extends Struct { // See DECL_RARE_ACCESSORS in FunctionTemplateInfo. - prototype_template: Object; - prototype_provider_template: Object; - parent_template: Object; - named_property_handler: Object; - indexed_property_handler: Object; - instance_template: Object; - instance_call_handler: Object; - access_check_info: Object; - c_function: Foreign|Smi; - c_signature: Foreign|Smi; + prototype_template: ObjectTemplateInfo|Undefined; + prototype_provider_template: FunctionTemplateInfo|Undefined; + parent_template: FunctionTemplateInfo|Undefined; + named_property_handler: InterceptorInfo|Undefined; + indexed_property_handler: InterceptorInfo|Undefined; + instance_template: ObjectTemplateInfo|Undefined; + instance_call_handler: CallHandlerInfo|Undefined; + access_check_info: AccessCheckInfo|Undefined; + c_function: Foreign|Zero; + c_signature: Foreign|Zero; +} + +bitfield struct FunctionTemplateInfoFlags extends uint31 { + undetectable: bool: 1 bit; + needs_access_check: bool: 1 bit; + read_only_prototype: bool: 1 bit; + remove_prototype: bool: 1 bit; + do_not_cache: bool: 1 bit; + accept_any_receiver: bool: 1 bit; } @generateCppClass extern class FunctionTemplateInfo extends TemplateInfo { // Handler invoked when calling an instance of this FunctionTemplateInfo. // Either CallHandlerInfo or Undefined. - call_code: Object; - class_name: Object; + call_code: CallHandlerInfo|Undefined; + class_name: String|Undefined; // If the signature is a FunctionTemplateInfo it is used to check whether the // receiver calling the associated JSFunction is a compatible receiver, i.e. // it is an instance of the signature FunctionTemplateInfo or any of the // receiver's prototypes are. - signature: Object; + signature: FunctionTemplateInfo|Undefined; // If any of the setters declared by DECL_RARE_ACCESSORS are used then a // FunctionTemplateRareData will be stored here. Until then this contains // undefined. - rare_data: HeapObject; - shared_function_info: Object; + rare_data: FunctionTemplateRareData|Undefined; + shared_function_info: SharedFunctionInfo|Undefined; // Internal field to store a flag bitfield. - flag: Smi; + flag: SmiTagged<FunctionTemplateInfoFlags>; // "length" property of the final JSFunction. length: Smi; // Either the_hole or a private symbol. Used to cache the result on @@ -53,8 +63,13 @@ extern class FunctionTemplateInfo extends TemplateInfo { cached_property_name: Object; } +bitfield struct ObjectTemplateInfoFlags extends uint31 { + is_immutable_prototype: bool: 1 bit; + embedder_field_count: int32: 29 bit; +} + @generateCppClass extern class ObjectTemplateInfo extends TemplateInfo { - constructor: Object; - data: Object; + constructor: FunctionTemplateInfo|Undefined; + data: SmiTagged<ObjectTemplateInfoFlags>; } diff --git a/chromium/v8/src/objects/templates-inl.h b/chromium/v8/src/objects/templates-inl.h index 988230b7ae4..8dd5aa6e2db 100644 --- a/chromium/v8/src/objects/templates-inl.h +++ b/chromium/v8/src/objects/templates-inl.h @@ -24,16 +24,17 @@ TQ_OBJECT_CONSTRUCTORS_IMPL(FunctionTemplateRareData) NEVER_READ_ONLY_SPACE_IMPL(TemplateInfo) -BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit) +BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, + UndetectableBit::kShift) BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check, - kNeedsAccessCheckBit) + NeedsAccessCheckBit::kShift) BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype, - kReadOnlyPrototypeBit) + ReadOnlyPrototypeBit::kShift) BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype, - kRemovePrototypeBit) -BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache, kDoNotCacheBit) + RemovePrototypeBit::kShift) +BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache, DoNotCacheBit::kShift) BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver, - kAcceptAnyReceiver) + AcceptAnyReceiverBit::kShift) // static FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData( @@ -61,16 +62,18 @@ FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData( rare_data.set_##Name(*Name); \ } -RARE_ACCESSORS(prototype_template, PrototypeTemplate, Object, undefined) -RARE_ACCESSORS(prototype_provider_template, PrototypeProviderTemplate, Object, +RARE_ACCESSORS(prototype_template, PrototypeTemplate, HeapObject, undefined) +RARE_ACCESSORS(prototype_provider_template, PrototypeProviderTemplate, + HeapObject, undefined) +RARE_ACCESSORS(parent_template, ParentTemplate, HeapObject, undefined) +RARE_ACCESSORS(named_property_handler, NamedPropertyHandler, HeapObject, undefined) -RARE_ACCESSORS(parent_template, ParentTemplate, Object, undefined) -RARE_ACCESSORS(named_property_handler, NamedPropertyHandler, Object, undefined) -RARE_ACCESSORS(indexed_property_handler, IndexedPropertyHandler, Object, +RARE_ACCESSORS(indexed_property_handler, IndexedPropertyHandler, HeapObject, undefined) -RARE_ACCESSORS(instance_template, InstanceTemplate, Object, undefined) -RARE_ACCESSORS(instance_call_handler, InstanceCallHandler, Object, undefined) -RARE_ACCESSORS(access_check_info, AccessCheckInfo, Object, undefined) +RARE_ACCESSORS(instance_template, InstanceTemplate, HeapObject, undefined) +RARE_ACCESSORS(instance_call_handler, InstanceCallHandler, HeapObject, + undefined) +RARE_ACCESSORS(access_check_info, AccessCheckInfo, HeapObject, undefined) RARE_ACCESSORS(c_function, CFunction, Object, Smi(0)) RARE_ACCESSORS(c_signature, CSignature, Object, Smi(0)) #undef RARE_ACCESSORS @@ -110,26 +113,20 @@ ObjectTemplateInfo ObjectTemplateInfo::GetParent(Isolate* isolate) { } int ObjectTemplateInfo::embedder_field_count() const { - Object value = data(); - DCHECK(value.IsSmi()); - return EmbedderFieldCount::decode(Smi::ToInt(value)); + return EmbedderFieldCountBits::decode(data()); } void ObjectTemplateInfo::set_embedder_field_count(int count) { DCHECK_LE(count, JSObject::kMaxEmbedderFields); - return set_data( - Smi::FromInt(EmbedderFieldCount::update(Smi::ToInt(data()), count))); + return set_data(EmbedderFieldCountBits::update(data(), count)); } bool ObjectTemplateInfo::immutable_proto() const { - Object value = data(); - DCHECK(value.IsSmi()); - return IsImmutablePrototype::decode(Smi::ToInt(value)); + return IsImmutablePrototypeBit::decode(data()); } void ObjectTemplateInfo::set_immutable_proto(bool immutable) { - return set_data(Smi::FromInt( - IsImmutablePrototype::update(Smi::ToInt(data()), immutable))); + return set_data(IsImmutablePrototypeBit::update(data(), immutable)); } bool FunctionTemplateInfo::IsTemplateFor(JSObject object) { diff --git a/chromium/v8/src/objects/templates.h b/chromium/v8/src/objects/templates.h index 01d40eb29ae..a3b509928be 100644 --- a/chromium/v8/src/objects/templates.h +++ b/chromium/v8/src/objects/templates.h @@ -6,6 +6,7 @@ #define V8_OBJECTS_TEMPLATES_H_ #include "src/objects/struct.h" +#include "torque-generated/bit-fields-tq.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -32,9 +33,6 @@ class FunctionTemplateRareData : public TorqueGeneratedFunctionTemplateRareData<FunctionTemplateRareData, Struct> { public: - // Dispatched behavior. - DECL_PRINTER(FunctionTemplateRareData) - TQ_OBJECT_CONSTRUCTORS(FunctionTemplateRareData) }; @@ -51,36 +49,37 @@ class FunctionTemplateInfo // ObjectTemplateInfo or Undefined, used for the prototype property of the // resulting JSFunction instance of this FunctionTemplate. - DECL_RARE_ACCESSORS(prototype_template, PrototypeTemplate, Object) + DECL_RARE_ACCESSORS(prototype_template, PrototypeTemplate, HeapObject) // In the case the prototype_template is Undefined we use the // prototype_provider_template to retrieve the instance prototype. Either - // contains an ObjectTemplateInfo or Undefined. + // contains an FunctionTemplateInfo or Undefined. DECL_RARE_ACCESSORS(prototype_provider_template, PrototypeProviderTemplate, - Object) + HeapObject) // Used to create prototype chains. The parent_template's prototype is set as // __proto__ of this FunctionTemplate's instance prototype. Is either a // FunctionTemplateInfo or Undefined. - DECL_RARE_ACCESSORS(parent_template, ParentTemplate, Object) + DECL_RARE_ACCESSORS(parent_template, ParentTemplate, HeapObject) // Returns an InterceptorInfo or Undefined for named properties. - DECL_RARE_ACCESSORS(named_property_handler, NamedPropertyHandler, Object) + DECL_RARE_ACCESSORS(named_property_handler, NamedPropertyHandler, HeapObject) // Returns an InterceptorInfo or Undefined for indexed properties/elements. - DECL_RARE_ACCESSORS(indexed_property_handler, IndexedPropertyHandler, Object) + DECL_RARE_ACCESSORS(indexed_property_handler, IndexedPropertyHandler, + HeapObject) // An ObjectTemplateInfo that is used when instantiating the JSFunction // associated with this FunctionTemplateInfo. Contains either an // ObjectTemplateInfo or Undefined. A default instance_template is assigned // upon first instantiation if it's Undefined. - DECL_RARE_ACCESSORS(instance_template, InstanceTemplate, Object) + DECL_RARE_ACCESSORS(instance_template, InstanceTemplate, HeapObject) // Either a CallHandlerInfo or Undefined. If an instance_call_handler is // provided the instances created from the associated JSFunction are marked as // callable. - DECL_RARE_ACCESSORS(instance_call_handler, InstanceCallHandler, Object) + DECL_RARE_ACCESSORS(instance_call_handler, InstanceCallHandler, HeapObject) - DECL_RARE_ACCESSORS(access_check_info, AccessCheckInfo, Object) + DECL_RARE_ACCESSORS(access_check_info, AccessCheckInfo, HeapObject) DECL_RARE_ACCESSORS(c_function, CFunction, Object) DECL_RARE_ACCESSORS(c_signature, CSignature, Object) @@ -138,12 +137,7 @@ class FunctionTemplateInfo Handle<Object> getter); // Bit position in the flag, from least significant bit position. - static const int kUndetectableBit = 0; - static const int kNeedsAccessCheckBit = 1; - static const int kReadOnlyPrototypeBit = 2; - static const int kRemovePrototypeBit = 3; - static const int kDoNotCacheBit = 4; - static const int kAcceptAnyReceiver = 5; + DEFINE_TORQUE_GENERATED_FUNCTION_TEMPLATE_INFO_FLAGS() private: static inline FunctionTemplateRareData EnsureFunctionTemplateRareData( @@ -170,8 +164,7 @@ class ObjectTemplateInfo inline ObjectTemplateInfo GetParent(Isolate* isolate); private: - using IsImmutablePrototype = base::BitField<bool, 0, 1>; - using EmbedderFieldCount = IsImmutablePrototype::Next<int, 29>; + DEFINE_TORQUE_GENERATED_OBJECT_TEMPLATE_INFO_FLAGS() TQ_OBJECT_CONSTRUCTORS(ObjectTemplateInfo) }; diff --git a/chromium/v8/src/objects/transitions.cc b/chromium/v8/src/objects/transitions.cc index e0ba40ce7d0..1309ca82be5 100644 --- a/chromium/v8/src/objects/transitions.cc +++ b/chromium/v8/src/objects/transitions.cc @@ -36,6 +36,7 @@ bool TransitionsAccessor::HasSimpleTransitionTo(Map map) { void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target, SimpleTransitionFlag flag) { DCHECK(!map_handle_.is_null()); + DCHECK_NE(kPrototypeInfo, encoding()); target->SetBackPointer(map_); // If the map doesn't have any transitions at all yet, install the new one. @@ -49,23 +50,25 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target, isolate_->factory()->NewTransitionArray(0, 1); ReplaceTransitions(MaybeObject::FromObject(*result)); Reload(); + DCHECK_EQ(kFullTransitionArray, encoding()); } - bool is_special_transition = flag == SPECIAL_TRANSITION; // If the map has a simple transition, check if it should be overwritten. Map simple_transition = GetSimpleTransition(); if (!simple_transition.is_null()) { - Name key = GetSimpleTransitionKey(simple_transition); - PropertyDetails old_details = GetSimpleTargetDetails(simple_transition); - PropertyDetails new_details = is_special_transition - ? PropertyDetails::Empty() - : GetTargetDetails(*name, *target); - if (flag == SIMPLE_PROPERTY_TRANSITION && key.Equals(*name) && - old_details.kind() == new_details.kind() && - old_details.attributes() == new_details.attributes()) { - ReplaceTransitions(HeapObjectReference::Weak(*target)); - return; + DCHECK_EQ(kWeakRef, encoding()); + + if (flag == SIMPLE_PROPERTY_TRANSITION) { + Name key = GetSimpleTransitionKey(simple_transition); + PropertyDetails old_details = GetSimpleTargetDetails(simple_transition); + PropertyDetails new_details = GetTargetDetails(*name, *target); + if (key.Equals(*name) && old_details.kind() == new_details.kind() && + old_details.attributes() == new_details.attributes()) { + ReplaceTransitions(HeapObjectReference::Weak(*target)); + return; + } } + // Otherwise allocate a full TransitionArray with slack for a new entry. Handle<Map> map(simple_transition, isolate_); Handle<TransitionArray> result = @@ -75,12 +78,9 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target, simple_transition = GetSimpleTransition(); if (!simple_transition.is_null()) { DCHECK_EQ(*map, simple_transition); - if (encoding_ == kWeakRef) { - result->Set(0, GetSimpleTransitionKey(simple_transition), - HeapObjectReference::Weak(simple_transition)); - } else { - UNREACHABLE(); - } + DCHECK_EQ(kWeakRef, encoding()); + result->Set(0, GetSimpleTransitionKey(simple_transition), + HeapObjectReference::Weak(simple_transition)); } else { result->SetNumberOfTransitions(0); } @@ -94,6 +94,7 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target, int number_of_transitions = 0; int new_nof = 0; int insertion_index = kNotFound; + const bool is_special_transition = flag == SPECIAL_TRANSITION; DCHECK_EQ(is_special_transition, IsSpecialTransition(ReadOnlyRoots(isolate_), *name)); PropertyDetails details = is_special_transition @@ -104,7 +105,6 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target, DisallowHeapAllocation no_gc; TransitionArray array = transitions(); number_of_transitions = array.number_of_transitions(); - new_nof = number_of_transitions; int index = is_special_transition ? array.SearchSpecial(Symbol::cast(*name), &insertion_index) @@ -116,19 +116,20 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target, return; } - ++new_nof; + new_nof = number_of_transitions + 1; CHECK_LE(new_nof, kMaxNumberOfTransitions); - DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); + DCHECK_GE(insertion_index, 0); + DCHECK_LE(insertion_index, number_of_transitions); // If there is enough capacity, insert new entry into the existing array. if (new_nof <= array.Capacity()) { array.SetNumberOfTransitions(new_nof); - for (index = number_of_transitions; index > insertion_index; --index) { - array.SetKey(index, array.GetKey(index - 1)); - array.SetRawTarget(index, array.GetRawTarget(index - 1)); + for (int i = number_of_transitions; i > insertion_index; --i) { + array.SetKey(i, array.GetKey(i - 1)); + array.SetRawTarget(i, array.GetRawTarget(i - 1)); } - array.SetKey(index, *name); - array.SetRawTarget(index, HeapObjectReference::Weak(*target)); + array.SetKey(insertion_index, *name); + array.SetRawTarget(insertion_index, HeapObjectReference::Weak(*target)); SLOW_DCHECK(array.IsSortedNoDuplicates()); return; } @@ -146,23 +147,19 @@ void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target, DisallowHeapAllocation no_gc; TransitionArray array = transitions(); if (array.number_of_transitions() != number_of_transitions) { - DCHECK(array.number_of_transitions() < number_of_transitions); + DCHECK_LT(array.number_of_transitions(), number_of_transitions); - number_of_transitions = array.number_of_transitions(); - new_nof = number_of_transitions; - - insertion_index = kNotFound; int index = is_special_transition ? array.SearchSpecial(Symbol::cast(*name), &insertion_index) : array.Search(details.kind(), *name, details.attributes(), &insertion_index); - if (index == kNotFound) { - ++new_nof; - } else { - insertion_index = index; - } - DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); + CHECK_EQ(index, kNotFound); + USE(index); + DCHECK_GE(insertion_index, 0); + DCHECK_LE(insertion_index, number_of_transitions); + number_of_transitions = array.number_of_transitions(); + new_nof = number_of_transitions + 1; result->SetNumberOfTransitions(new_nof); } @@ -405,26 +402,14 @@ Map TransitionsAccessor::GetMigrationTarget() { return Map(); } -void TransitionArray::Zap(Isolate* isolate) { - MemsetTagged(ObjectSlot(RawFieldOfElementAt(kPrototypeTransitionsIndex)), - ReadOnlyRoots(isolate).the_hole_value(), - length() - kPrototypeTransitionsIndex); - SetNumberOfTransitions(0); -} - void TransitionsAccessor::ReplaceTransitions(MaybeObject new_transitions) { if (encoding() == kFullTransitionArray) { - TransitionArray old_transitions = transitions(); #if DEBUG + TransitionArray old_transitions = transitions(); CheckNewTransitionsAreConsistent( old_transitions, new_transitions->GetHeapObjectAssumeStrong()); DCHECK(old_transitions != new_transitions->GetHeapObjectAssumeStrong()); #endif - // Transition arrays are not shared. When one is replaced, it should not - // keep referenced objects alive, so we zap it. - // When there is another reference to the array somewhere (e.g. a handle), - // not zapping turns from a waste of memory into a source of crashes. - old_transitions.Zap(isolate_); } map_.set_raw_transitions(new_transitions); MarkNeedsReload(); diff --git a/chromium/v8/src/objects/transitions.h b/chromium/v8/src/objects/transitions.h index 5a7db13e516..7bc4d70a35d 100644 --- a/chromium/v8/src/objects/transitions.h +++ b/chromium/v8/src/objects/transitions.h @@ -228,7 +228,7 @@ class TransitionArray : public WeakFixedArray { int GetSortedKeyIndex(int transition_number) { return transition_number; } inline int number_of_entries() const; #ifdef DEBUG - V8_EXPORT_PRIVATE bool IsSortedNoDuplicates(int valid_entries = -1); + V8_EXPORT_PRIVATE bool IsSortedNoDuplicates(); #endif void Sort(); @@ -338,8 +338,6 @@ class TransitionArray : public WeakFixedArray { inline void Set(int transition_number, Name key, MaybeObject target); - void Zap(Isolate* isolate); - OBJECT_CONSTRUCTORS(TransitionArray, WeakFixedArray); }; diff --git a/chromium/v8/src/objects/type-hints.cc b/chromium/v8/src/objects/type-hints.cc index cb0a6a4ea9b..da63443b4ca 100644 --- a/chromium/v8/src/objects/type-hints.cc +++ b/chromium/v8/src/objects/type-hints.cc @@ -39,6 +39,8 @@ std::ostream& operator<<(std::ostream& os, CompareOperationHint hint) { return os << "SignedSmall"; case CompareOperationHint::kNumber: return os << "Number"; + case CompareOperationHint::kNumberOrBoolean: + return os << "NumberOrBoolean"; case CompareOperationHint::kNumberOrOddball: return os << "NumberOrOddball"; case CompareOperationHint::kInternalizedString: diff --git a/chromium/v8/src/objects/type-hints.h b/chromium/v8/src/objects/type-hints.h index 1aa27096652..d61ebef8457 100644 --- a/chromium/v8/src/objects/type-hints.h +++ b/chromium/v8/src/objects/type-hints.h @@ -35,6 +35,7 @@ enum class CompareOperationHint : uint8_t { kNone, kSignedSmall, kNumber, + kNumberOrBoolean, kNumberOrOddball, kInternalizedString, kString, |