blob: a1c61f4c230aaeb2ab986614733d7e5bcf0ef843 [file] [edit]
// Copyright 2026 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-data-object-builder.h"
#include "src/heap/factory.h"
#include "src/objects/js-data-object-builder-inl.h"
#include "src/objects/lookup.h"
namespace v8 {
namespace internal {
JSDataObjectBuilder::JSDataObjectBuilder(Isolate* isolate,
ElementsKind elements_kind,
int expected_named_properties,
DirectHandle<Map> expected_final_map,
HeapNumberMode heap_number_mode)
: isolate_(isolate),
elements_kind_(elements_kind),
expected_property_count_(expected_named_properties),
heap_number_mode_(heap_number_mode),
may_have_duplicate_keys_(true),
expected_final_map_(expected_final_map) {
if (!TryInitializeMapFromExpectedFinalMap()) {
InitializeMapFromZero();
}
}
void JSDataObjectBuilder::AddSlowProperty(DirectHandle<InternalizedString> key,
Handle<Object> value) {
DCHECK(!object_.is_null());
LookupIterator it(isolate_, object_, key, object_, LookupIterator::OWN);
JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE).Check();
}
bool JSDataObjectBuilder::TryInitializeMapFromExpectedFinalMap() {
if (expected_final_map_.is_null()) return false;
if (expected_final_map_->elements_kind() != elements_kind_) return false;
int property_count_in_expected_final_map =
expected_final_map_->NumberOfOwnDescriptors();
if (property_count_in_expected_final_map < expected_property_count_) {
return false;
}
map_ = expected_final_map_;
property_count_in_expected_final_map_ = property_count_in_expected_final_map;
return true;
}
void JSDataObjectBuilder::InitializeMapFromZero() {
// Must be called before any properties are registered.
DCHECK_EQ(current_property_index_, 0);
map_ = isolate_->factory()->ObjectLiteralMapFromCache(
isolate_->native_context(), expected_property_count_);
if (elements_kind_ == DICTIONARY_ELEMENTS) {
map_ = Map::AsElementsKind(isolate_, map_, elements_kind_);
} else {
DCHECK_EQ(map_->elements_kind(), elements_kind_);
}
}
void JSDataObjectBuilder::RewindExpectedFinalMapFastPathToBeforeCurrent() {
DCHECK_GT(property_count_in_expected_final_map_, 0);
if (current_property_index_ == 0) {
InitializeMapFromZero();
DCHECK_EQ(0, map_->NumberOfOwnDescriptors());
}
if (current_property_index_ == 0) {
return;
}
DCHECK_EQ(*map_, *expected_final_map_);
map_ =
handle(map_->FindFieldOwner(InternalIndex(current_property_index_ - 1)),
isolate_);
}
void JSDataObjectBuilder::RewindExpectedFinalMapFastPathToIncludeCurrent() {
DCHECK_EQ(*map_, *expected_final_map_);
map_ = handle(expected_final_map_->FindFieldOwner(
InternalIndex(current_property_index_)),
isolate_);
}
} // namespace internal
} // namespace v8