summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/js-objects.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/js-objects.cc')
-rw-r--r--deps/v8/src/objects/js-objects.cc190
1 files changed, 109 insertions, 81 deletions
diff --git a/deps/v8/src/objects/js-objects.cc b/deps/v8/src/objects/js-objects.cc
index 3666f5afbe..ea0917f18f 100644
--- a/deps/v8/src/objects/js-objects.cc
+++ b/deps/v8/src/objects/js-objects.cc
@@ -216,15 +216,19 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
}
Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
- int length = map->NumberOfOwnDescriptors();
bool stable = true;
- for (int i = 0; i < length; i++) {
+ for (InternalIndex i : map->IterateOwnDescriptors()) {
+ HandleScope inner_scope(isolate);
+
Handle<Name> next_key(descriptors->GetKey(i), isolate);
Handle<Object> prop_value;
// Directly decode from the descriptor array if |from| did not change shape.
if (stable) {
+ DCHECK_EQ(from->map(), *map);
+ DCHECK_EQ(*descriptors, map->instance_descriptors());
+
PropertyDetails details = descriptors->GetDetails(i);
if (!details.IsEnumerable()) continue;
if (details.kind() == kData) {
@@ -232,7 +236,8 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
prop_value = handle(descriptors->GetStrongValue(i), isolate);
} else {
Representation representation = details.representation();
- FieldIndex index = FieldIndex::ForDescriptor(*map, i);
+ FieldIndex index = FieldIndex::ForPropertyIndex(
+ *map, details.field_index(), representation);
prop_value = JSObject::FastPropertyAt(from, representation, index);
}
} else {
@@ -240,6 +245,7 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
isolate, prop_value,
JSReceiver::GetProperty(isolate, from, next_key), Nothing<bool>());
stable = from->map() == *map;
+ *descriptors.location() = map->instance_descriptors().ptr();
}
} else {
// If the map did change, do a slower lookup. We are still guaranteed that
@@ -260,7 +266,10 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
Object::SetProperty(&it, prop_value, StoreOrigin::kNamed,
Just(ShouldThrow::kThrowOnError));
if (result.IsNothing()) return result;
- if (stable) stable = from->map() == *map;
+ if (stable) {
+ stable = from->map() == *map;
+ *descriptors.location() = map->instance_descriptors().ptr();
+ }
} else {
if (excluded_properties != nullptr &&
HasExcludedProperty(excluded_properties, next_key)) {
@@ -1094,8 +1103,7 @@ Maybe<bool> SetPropertyWithInterceptorInternal(
Maybe<bool> DefinePropertyWithInterceptorInternal(
LookupIterator* it, Handle<InterceptorInfo> interceptor,
- Maybe<ShouldThrow> should_throw,
- PropertyDescriptor& desc) { // NOLINT(runtime/references)
+ Maybe<ShouldThrow> should_throw, PropertyDescriptor* desc) {
Isolate* isolate = it->isolate();
// Make sure that the top context does not change when doing callbacks or
// interceptor calls.
@@ -1116,23 +1124,23 @@ Maybe<bool> DefinePropertyWithInterceptorInternal(
std::unique_ptr<v8::PropertyDescriptor> descriptor(
new v8::PropertyDescriptor());
- if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
+ if (PropertyDescriptor::IsAccessorDescriptor(desc)) {
descriptor.reset(new v8::PropertyDescriptor(
- v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
- } else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
- if (desc.has_writable()) {
+ v8::Utils::ToLocal(desc->get()), v8::Utils::ToLocal(desc->set())));
+ } else if (PropertyDescriptor::IsDataDescriptor(desc)) {
+ if (desc->has_writable()) {
descriptor.reset(new v8::PropertyDescriptor(
- v8::Utils::ToLocal(desc.value()), desc.writable()));
+ v8::Utils::ToLocal(desc->value()), desc->writable()));
} else {
descriptor.reset(
- new v8::PropertyDescriptor(v8::Utils::ToLocal(desc.value())));
+ new v8::PropertyDescriptor(v8::Utils::ToLocal(desc->value())));
}
}
- if (desc.has_enumerable()) {
- descriptor->set_enumerable(desc.enumerable());
+ if (desc->has_enumerable()) {
+ descriptor->set_enumerable(desc->enumerable());
}
- if (desc.has_configurable()) {
- descriptor->set_configurable(desc.configurable());
+ if (desc->has_configurable()) {
+ descriptor->set_configurable(desc->configurable());
}
if (it->IsElement()) {
@@ -1166,7 +1174,7 @@ Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(
if (it->state() == LookupIterator::INTERCEPTOR) {
if (it->HolderIsReceiverOrHiddenPrototype()) {
Maybe<bool> result = DefinePropertyWithInterceptorInternal(
- it, it->GetInterceptor(), should_throw, *desc);
+ it, it->GetInterceptor(), should_throw, desc);
if (result.IsNothing() || result.FromJust()) {
return result;
}
@@ -1834,8 +1842,8 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
if (!map->OnlyHasSimpleProperties()) return Just(false);
Handle<JSObject> object(JSObject::cast(*receiver), isolate);
-
Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
+
int number_of_own_descriptors = map->NumberOfOwnDescriptors();
int number_of_own_elements =
object->GetElementsAccessor()->GetCapacity(*object, object->elements());
@@ -1857,15 +1865,25 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
Nothing<bool>());
}
- bool stable = object->map() == *map;
+ // We may have already lost stability, if CollectValuesOrEntries had
+ // side-effects.
+ bool stable = *map == object->map();
+ if (stable) {
+ *descriptors.location() = map->instance_descriptors().ptr();
+ }
+
+ for (InternalIndex index : InternalIndex::Range(number_of_own_descriptors)) {
+ HandleScope inner_scope(isolate);
- for (int index = 0; index < number_of_own_descriptors; index++) {
Handle<Name> next_key(descriptors->GetKey(index), isolate);
if (!next_key->IsString()) continue;
Handle<Object> prop_value;
// Directly decode from the descriptor array if |from| did not change shape.
if (stable) {
+ DCHECK_EQ(object->map(), *map);
+ DCHECK_EQ(*descriptors, map->instance_descriptors());
+
PropertyDetails details = descriptors->GetDetails(index);
if (!details.IsEnumerable()) continue;
if (details.kind() == kData) {
@@ -1873,7 +1891,8 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
prop_value = handle(descriptors->GetStrongValue(index), isolate);
} else {
Representation representation = details.representation();
- FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
+ FieldIndex field_index = FieldIndex::ForPropertyIndex(
+ *map, details.field_index(), representation);
prop_value =
JSObject::FastPropertyAt(object, representation, field_index);
}
@@ -1883,6 +1902,7 @@ V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
JSReceiver::GetProperty(isolate, object, next_key),
Nothing<bool>());
stable = object->map() == *map;
+ *descriptors.location() = map->instance_descriptors().ptr();
}
} else {
// If the map did change, do a slower lookup. We are still guaranteed that
@@ -2121,15 +2141,15 @@ int JSObject::GetHeaderSize(InstanceType type,
return JSWeakSet::kSize;
case JS_PROMISE_TYPE:
return JSPromise::kSize;
- case JS_REGEXP_TYPE:
+ case JS_REG_EXP_TYPE:
return JSRegExp::kSize;
- case JS_REGEXP_STRING_ITERATOR_TYPE:
+ case JS_REG_EXP_STRING_ITERATOR_TYPE:
return JSRegExpStringIterator::kSize;
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
return JSObject::kHeaderSize;
case JS_MESSAGE_OBJECT_TYPE:
return JSMessageObject::kSize;
- case JS_ARGUMENTS_TYPE:
+ case JS_ARGUMENTS_OBJECT_TYPE:
return JSObject::kHeaderSize;
case JS_ERROR_TYPE:
return JSObject::kHeaderSize;
@@ -2138,38 +2158,38 @@ int JSObject::GetHeaderSize(InstanceType type,
case JS_MODULE_NAMESPACE_TYPE:
return JSModuleNamespace::kHeaderSize;
#ifdef V8_INTL_SUPPORT
- case JS_INTL_V8_BREAK_ITERATOR_TYPE:
+ case JS_V8_BREAK_ITERATOR_TYPE:
return JSV8BreakIterator::kSize;
- case JS_INTL_COLLATOR_TYPE:
+ case JS_COLLATOR_TYPE:
return JSCollator::kSize;
- case JS_INTL_DATE_TIME_FORMAT_TYPE:
+ case JS_DATE_TIME_FORMAT_TYPE:
return JSDateTimeFormat::kSize;
- case JS_INTL_LIST_FORMAT_TYPE:
+ case JS_LIST_FORMAT_TYPE:
return JSListFormat::kSize;
- case JS_INTL_LOCALE_TYPE:
+ case JS_LOCALE_TYPE:
return JSLocale::kSize;
- case JS_INTL_NUMBER_FORMAT_TYPE:
+ case JS_NUMBER_FORMAT_TYPE:
return JSNumberFormat::kSize;
- case JS_INTL_PLURAL_RULES_TYPE:
+ case JS_PLURAL_RULES_TYPE:
return JSPluralRules::kSize;
- case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
+ case JS_RELATIVE_TIME_FORMAT_TYPE:
return JSRelativeTimeFormat::kSize;
- case JS_INTL_SEGMENT_ITERATOR_TYPE:
+ case JS_SEGMENT_ITERATOR_TYPE:
return JSSegmentIterator::kSize;
- case JS_INTL_SEGMENTER_TYPE:
+ case JS_SEGMENTER_TYPE:
return JSSegmenter::kSize;
#endif // V8_INTL_SUPPORT
- case WASM_GLOBAL_TYPE:
+ case WASM_GLOBAL_OBJECT_TYPE:
return WasmGlobalObject::kSize;
- case WASM_INSTANCE_TYPE:
+ case WASM_INSTANCE_OBJECT_TYPE:
return WasmInstanceObject::kSize;
- case WASM_MEMORY_TYPE:
+ case WASM_MEMORY_OBJECT_TYPE:
return WasmMemoryObject::kSize;
- case WASM_MODULE_TYPE:
+ case WASM_MODULE_OBJECT_TYPE:
return WasmModuleObject::kSize;
- case WASM_TABLE_TYPE:
+ case WASM_TABLE_OBJECT_TYPE:
return WasmTableObject::kSize;
- case WASM_EXCEPTION_TYPE:
+ case WASM_EXCEPTION_OBJECT_TYPE:
return WasmExceptionObject::kSize;
default:
UNREACHABLE();
@@ -2377,7 +2397,7 @@ void JSObject::JSObjectShortPrint(StringStream* accumulator) {
accumulator->Add("<JSWeakSet>");
break;
}
- case JS_REGEXP_TYPE: {
+ case JS_REG_EXP_TYPE: {
accumulator->Add("<JSRegExp");
JSRegExp regexp = JSRegExp::cast(*this);
if (regexp.source().IsString()) {
@@ -2506,7 +2526,7 @@ void JSObject::PrintInstanceMigration(FILE* file, Map original_map,
PrintF(file, "[migrating]");
DescriptorArray o = original_map.instance_descriptors();
DescriptorArray n = new_map.instance_descriptors();
- for (int i = 0; i < original_map.NumberOfOwnDescriptors(); i++) {
+ for (InternalIndex i : original_map.IterateOwnDescriptors()) {
Representation o_r = o.GetDetails(i).representation();
Representation n_r = n.GetDetails(i).representation();
if (!o_r.Equals(n_r)) {
@@ -2703,7 +2723,7 @@ void MigrateFastToFast(Isolate* isolate, Handle<JSObject> object,
// number of properties.
DCHECK(old_nof <= new_nof);
- for (int i = 0; i < old_nof; i++) {
+ for (InternalIndex i : InternalIndex::Range(old_nof)) {
PropertyDetails details = new_descriptors->GetDetails(i);
if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind());
@@ -2753,7 +2773,7 @@ void MigrateFastToFast(Isolate* isolate, Handle<JSObject> object,
}
}
- for (int i = old_nof; i < new_nof; i++) {
+ for (InternalIndex i : InternalIndex::Range(old_nof, new_nof)) {
PropertyDetails details = new_descriptors->GetDetails(i);
if (details.location() != kField) continue;
DCHECK_EQ(kData, details.kind());
@@ -2776,9 +2796,10 @@ void MigrateFastToFast(Isolate* isolate, Handle<JSObject> object,
Heap* heap = isolate->heap();
- int old_instance_size = old_map->instance_size();
-
- heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
+ // Invalidate slots manually later in case of tagged to untagged translation.
+ // In all other cases the recorded slot remains dereferenceable.
+ heap->NotifyObjectLayoutChange(*object, no_allocation,
+ InvalidateRecordedSlots::kNo);
// Copy (real) inobject properties. If necessary, stop at number_of_fields to
// avoid overwriting |one_pointer_filler_map|.
@@ -2795,7 +2816,8 @@ void MigrateFastToFast(Isolate* isolate, Handle<JSObject> object,
index, HeapNumber::cast(value).value_as_bits());
if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
// Transition from tagged to untagged slot.
- heap->ClearRecordedSlot(*object, object->RawField(index.offset()));
+ MemoryChunk* chunk = MemoryChunk::FromHeapObject(*object);
+ chunk->InvalidateRecordedSlots(*object);
} else {
#ifdef DEBUG
heap->VerifyClearedSlot(*object, object->RawField(index.offset()));
@@ -2809,6 +2831,7 @@ void MigrateFastToFast(Isolate* isolate, Handle<JSObject> object,
object->SetProperties(*array);
// Create filler object past the new instance size.
+ int old_instance_size = old_map->instance_size();
int new_instance_size = new_map->instance_size();
int instance_size_delta = old_instance_size - new_instance_size;
DCHECK_GE(instance_size_delta, 0);
@@ -2851,7 +2874,7 @@ void MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object,
NameDictionary::New(isolate, property_count);
Handle<DescriptorArray> descs(map->instance_descriptors(isolate), isolate);
- for (int i = 0; i < real_size; i++) {
+ for (InternalIndex i : InternalIndex::Range(real_size)) {
PropertyDetails details = descs->GetDetails(i);
Handle<Name> key(descs->GetKey(isolate, i), isolate);
Handle<Object> value;
@@ -2891,10 +2914,15 @@ void MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object,
DisallowHeapAllocation no_allocation;
Heap* heap = isolate->heap();
- int old_instance_size = map->instance_size();
- heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
+
+ // Invalidate slots manually later in case the new map has in-object
+ // properties. If not, it is not possible to store an untagged value
+ // in a recorded slot.
+ heap->NotifyObjectLayoutChange(*object, no_allocation,
+ InvalidateRecordedSlots::kNo);
// Resize the object in the heap if necessary.
+ int old_instance_size = map->instance_size();
int new_instance_size = new_map->instance_size();
int instance_size_delta = old_instance_size - new_instance_size;
DCHECK_GE(instance_size_delta, 0);
@@ -2914,10 +2942,8 @@ void MigrateFastToSlow(Isolate* isolate, Handle<JSObject> object,
// garbage.
int inobject_properties = new_map->GetInObjectProperties();
if (inobject_properties) {
- Heap* heap = isolate->heap();
- heap->ClearRecordedSlotRange(
- object->address() + map->GetInObjectPropertyOffset(0),
- object->address() + new_instance_size);
+ MemoryChunk* chunk = MemoryChunk::FromHeapObject(*object);
+ chunk->InvalidateRecordedSlots(*object);
for (int i = 0; i < inobject_properties; i++) {
FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
@@ -3047,7 +3073,7 @@ void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
Handle<PropertyArray> array =
isolate->factory()->NewPropertyArray(external);
- for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
+ for (InternalIndex i : map->IterateOwnDescriptors()) {
PropertyDetails details = descriptors->GetDetails(i);
Representation representation = details.representation();
if (!representation.IsDouble()) continue;
@@ -3344,8 +3370,8 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
}
// Allocate the instance descriptor.
- Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
- isolate, instance_descriptor_length, 0, AllocationType::kOld);
+ Handle<DescriptorArray> descriptors =
+ DescriptorArray::Allocate(isolate, instance_descriptor_length, 0);
int number_of_allocated_fields =
number_of_fields + unused_property_fields - inobject_props;
@@ -3410,7 +3436,7 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
}
current_offset += details.field_width_in_words();
}
- descriptors->Set(i, &d);
+ descriptors->Set(InternalIndex(i), &d);
}
DCHECK(current_offset == number_of_fields);
@@ -3441,6 +3467,8 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
}
void JSObject::RequireSlowElements(NumberDictionary dictionary) {
+ DCHECK_NE(dictionary,
+ ReadOnlyRoots(GetIsolate()).empty_slow_element_dictionary());
if (dictionary.requires_slow_elements()) return;
dictionary.set_requires_slow_elements();
if (map().is_prototype_map()) {
@@ -3603,8 +3631,7 @@ bool TestFastPropertiesIntegrityLevel(Map map, PropertyAttributes level) {
DCHECK(!map.is_dictionary_map());
DescriptorArray descriptors = map.instance_descriptors();
- int number_of_own_descriptors = map.NumberOfOwnDescriptors();
- for (int i = 0; i < number_of_own_descriptors; i++) {
+ for (InternalIndex i : map.IterateOwnDescriptors()) {
if (descriptors.GetKey(i).IsPrivate()) continue;
PropertyDetails details = descriptors.GetDetails(i);
if (details.IsConfigurable()) return false;
@@ -3709,7 +3736,9 @@ Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
object->HasSlowArgumentsElements());
// Make sure that we never go back to fast case.
- object->RequireSlowElements(*dictionary);
+ if (*dictionary != ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
+ object->RequireSlowElements(*dictionary);
+ }
}
// Do a map transition, other objects with this map may still
@@ -4136,10 +4165,9 @@ MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
Object JSObject::SlowReverseLookup(Object value) {
if (HasFastProperties()) {
- int number_of_own_descriptors = map().NumberOfOwnDescriptors();
DescriptorArray descs = map().instance_descriptors();
bool value_is_number = value.IsNumber();
- for (int i = 0; i < number_of_own_descriptors; i++) {
+ for (InternalIndex i : map().IterateOwnDescriptors()) {
PropertyDetails details = descs.GetDetails(i);
if (details.location() == kField) {
DCHECK_EQ(kData, details.kind());
@@ -5187,16 +5215,16 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_FUNCTION_TYPE:
case JS_GENERATOR_OBJECT_TYPE:
#ifdef V8_INTL_SUPPORT
- case JS_INTL_COLLATOR_TYPE:
- case JS_INTL_DATE_TIME_FORMAT_TYPE:
- case JS_INTL_LIST_FORMAT_TYPE:
- case JS_INTL_LOCALE_TYPE:
- case JS_INTL_NUMBER_FORMAT_TYPE:
- case JS_INTL_PLURAL_RULES_TYPE:
- case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
- case JS_INTL_SEGMENT_ITERATOR_TYPE:
- case JS_INTL_SEGMENTER_TYPE:
- case JS_INTL_V8_BREAK_ITERATOR_TYPE:
+ case JS_COLLATOR_TYPE:
+ case JS_DATE_TIME_FORMAT_TYPE:
+ case JS_LIST_FORMAT_TYPE:
+ case JS_LOCALE_TYPE:
+ case JS_NUMBER_FORMAT_TYPE:
+ case JS_PLURAL_RULES_TYPE:
+ case JS_RELATIVE_TIME_FORMAT_TYPE:
+ case JS_SEGMENT_ITERATOR_TYPE:
+ case JS_SEGMENTER_TYPE:
+ case JS_V8_BREAK_ITERATOR_TYPE:
#endif
case JS_ASYNC_FUNCTION_OBJECT_TYPE:
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
@@ -5205,9 +5233,9 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_OBJECT_TYPE:
case JS_ERROR_TYPE:
case JS_FINALIZATION_GROUP_TYPE:
- case JS_ARGUMENTS_TYPE:
+ case JS_ARGUMENTS_OBJECT_TYPE:
case JS_PROMISE_TYPE:
- case JS_REGEXP_TYPE:
+ case JS_REG_EXP_TYPE:
case JS_SET_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_TYPED_ARRAY_TYPE:
@@ -5215,11 +5243,11 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_WEAK_MAP_TYPE:
case JS_WEAK_REF_TYPE:
case JS_WEAK_SET_TYPE:
- case WASM_GLOBAL_TYPE:
- case WASM_INSTANCE_TYPE:
- case WASM_MEMORY_TYPE:
- case WASM_MODULE_TYPE:
- case WASM_TABLE_TYPE:
+ case WASM_GLOBAL_OBJECT_TYPE:
+ case WASM_INSTANCE_OBJECT_TYPE:
+ case WASM_MEMORY_OBJECT_TYPE:
+ case WASM_MODULE_OBJECT_TYPE:
+ case WASM_TABLE_OBJECT_TYPE:
return true;
case BIGINT_TYPE: