[ptr-compr][cleanup] Prepare for improving literals creation

Create[Array|Object]Literal were simply extracted from Helper
classes.

Bug: v8:9353
Change-Id: I8a97a7d5151c324db4a924cbfe1720444a1529aa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1683992
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62474}
This commit is contained in:
Igor Sheludko 2019-07-01 13:01:08 +02:00 committed by Commit Bot
parent 6f41bff276
commit 0c2cd56551

View File

@ -324,135 +324,159 @@ MaybeHandle<JSObject> DeepCopy(Handle<JSObject> object,
return copy;
}
Handle<JSObject> CreateObjectLiteral(
Isolate* isolate,
Handle<ObjectBoilerplateDescription> object_boilerplate_description,
int flags, AllocationType allocation);
Handle<JSObject> CreateArrayLiteral(
Isolate* isolate,
Handle<ArrayBoilerplateDescription> array_boilerplate_description,
AllocationType allocation);
struct ObjectLiteralHelper {
static Handle<JSObject> Create(Isolate* isolate,
Handle<HeapObject> description, int flags,
AllocationType allocation) {
Handle<NativeContext> native_context = isolate->native_context();
static inline Handle<JSObject> Create(Isolate* isolate,
Handle<HeapObject> description,
int flags, AllocationType allocation) {
Handle<ObjectBoilerplateDescription> object_boilerplate_description =
Handle<ObjectBoilerplateDescription>::cast(description);
bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;
// In case we have function literals, we want the object to be in
// slow properties mode for now. We don't go in the map cache because
// maps with constant functions can't be shared if the functions are
// not the same (which is the common case).
int number_of_properties =
object_boilerplate_description->backing_store_size();
// Ignoring number_of_properties for force dictionary map with
// __proto__:null.
Handle<Map> map =
has_null_prototype
? handle(native_context->slow_object_with_null_prototype_map(),
isolate)
: isolate->factory()->ObjectLiteralMapFromCache(
native_context, number_of_properties);
Handle<JSObject> boilerplate =
isolate->factory()->NewFastOrSlowJSObjectFromMap(
map, number_of_properties, allocation);
// Normalize the elements of the boilerplate to save space if needed.
if (!use_fast_elements) JSObject::NormalizeElements(boilerplate);
// Add the constant properties to the boilerplate.
int length = object_boilerplate_description->size();
// TODO(verwaest): Support tracking representations in the boilerplate.
for (int index = 0; index < length; index++) {
Handle<Object> key(object_boilerplate_description->name(index), isolate);
Handle<Object> value(object_boilerplate_description->value(index),
isolate);
if (value->IsObjectBoilerplateDescription() ||
value->IsArrayBoilerplateDescription()) {
value = InnerCreateBoilerplate(isolate, value, allocation);
}
uint32_t element_index = 0;
if (key->ToArrayIndex(&element_index)) {
// Array index (uint32).
if (value->IsUninitialized(isolate)) {
value = handle(Smi::kZero, isolate);
}
JSObject::SetOwnElementIgnoreAttributes(boilerplate, element_index,
value, NONE)
.Check();
} else {
Handle<String> name = Handle<String>::cast(key);
DCHECK(!name->AsArrayIndex(&element_index));
JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, value, NONE)
.Check();
}
}
if (map->is_dictionary_map() && !has_null_prototype) {
// TODO(cbruni): avoid making the boilerplate fast again, the clone stub
// supports dict-mode objects directly.
JSObject::MigrateSlowToFast(boilerplate,
boilerplate->map().UnusedPropertyFields(),
"FastLiteral");
}
return boilerplate;
return CreateObjectLiteral(isolate, object_boilerplate_description, flags,
allocation);
}
};
struct ArrayLiteralHelper {
static Handle<JSObject> Create(Isolate* isolate,
Handle<HeapObject> description, int flags,
AllocationType allocation) {
static inline Handle<JSObject> Create(Isolate* isolate,
Handle<HeapObject> description,
int flags_not_used,
AllocationType allocation) {
Handle<ArrayBoilerplateDescription> array_boilerplate_description =
Handle<ArrayBoilerplateDescription>::cast(description);
return CreateArrayLiteral(isolate, array_boilerplate_description,
allocation);
}
};
ElementsKind constant_elements_kind =
array_boilerplate_description->elements_kind();
Handle<JSObject> CreateObjectLiteral(
Isolate* isolate,
Handle<ObjectBoilerplateDescription> object_boilerplate_description,
int flags, AllocationType allocation) {
Handle<NativeContext> native_context = isolate->native_context();
bool use_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
bool has_null_prototype = (flags & ObjectLiteral::kHasNullPrototype) != 0;
Handle<FixedArrayBase> constant_elements_values(
array_boilerplate_description->constant_elements(), isolate);
// In case we have function literals, we want the object to be in
// slow properties mode for now. We don't go in the map cache because
// maps with constant functions can't be shared if the functions are
// not the same (which is the common case).
int number_of_properties =
object_boilerplate_description->backing_store_size();
// Create the JSArray.
Handle<FixedArrayBase> copied_elements_values;
if (IsDoubleElementsKind(constant_elements_kind)) {
copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
Handle<FixedDoubleArray>::cast(constant_elements_values));
// Ignoring number_of_properties for force dictionary map with
// __proto__:null.
Handle<Map> map =
has_null_prototype
? handle(native_context->slow_object_with_null_prototype_map(),
isolate)
: isolate->factory()->ObjectLiteralMapFromCache(native_context,
number_of_properties);
Handle<JSObject> boilerplate =
isolate->factory()->NewFastOrSlowJSObjectFromMap(
map, number_of_properties, allocation);
// Normalize the elements of the boilerplate to save space if needed.
if (!use_fast_elements) JSObject::NormalizeElements(boilerplate);
// Add the constant properties to the boilerplate.
int length = object_boilerplate_description->size();
// TODO(verwaest): Support tracking representations in the boilerplate.
for (int index = 0; index < length; index++) {
Handle<Object> key(object_boilerplate_description->name(index), isolate);
Handle<Object> value(object_boilerplate_description->value(index), isolate);
if (value->IsObjectBoilerplateDescription() ||
value->IsArrayBoilerplateDescription()) {
value = InnerCreateBoilerplate(isolate, value, allocation);
}
uint32_t element_index = 0;
if (key->ToArrayIndex(&element_index)) {
// Array index (uint32).
if (value->IsUninitialized(isolate)) {
value = handle(Smi::kZero, isolate);
}
JSObject::SetOwnElementIgnoreAttributes(boilerplate, element_index, value,
NONE)
.Check();
} else {
DCHECK(IsSmiOrObjectElementsKind(constant_elements_kind));
const bool is_cow = (constant_elements_values->map() ==
ReadOnlyRoots(isolate).fixed_cow_array_map());
if (is_cow) {
copied_elements_values = constant_elements_values;
#if DEBUG
Handle<String> name = Handle<String>::cast(key);
DCHECK(!name->AsArrayIndex(&element_index));
JSObject::SetOwnPropertyIgnoreAttributes(boilerplate, name, value, NONE)
.Check();
}
}
if (map->is_dictionary_map() && !has_null_prototype) {
// TODO(cbruni): avoid making the boilerplate fast again, the clone stub
// supports dict-mode objects directly.
JSObject::MigrateSlowToFast(
boilerplate, boilerplate->map().UnusedPropertyFields(), "FastLiteral");
}
return boilerplate;
}
Handle<JSObject> CreateArrayLiteral(
Isolate* isolate,
Handle<ArrayBoilerplateDescription> array_boilerplate_description,
AllocationType allocation) {
ElementsKind constant_elements_kind =
array_boilerplate_description->elements_kind();
Handle<FixedArrayBase> constant_elements_values(
array_boilerplate_description->constant_elements(), isolate);
// Create the JSArray.
Handle<FixedArrayBase> copied_elements_values;
if (IsDoubleElementsKind(constant_elements_kind)) {
copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
Handle<FixedDoubleArray>::cast(constant_elements_values));
} else {
DCHECK(IsSmiOrObjectElementsKind(constant_elements_kind));
const bool is_cow = (constant_elements_values->map() ==
ReadOnlyRoots(isolate).fixed_cow_array_map());
if (is_cow) {
copied_elements_values = constant_elements_values;
if (DEBUG_BOOL) {
Handle<FixedArray> fixed_array_values =
Handle<FixedArray>::cast(copied_elements_values);
for (int i = 0; i < fixed_array_values->length(); i++) {
DCHECK(!fixed_array_values->get(i).IsFixedArray());
}
#endif
} else {
Handle<FixedArray> fixed_array_values =
Handle<FixedArray>::cast(constant_elements_values);
Handle<FixedArray> fixed_array_values_copy =
isolate->factory()->CopyFixedArray(fixed_array_values);
copied_elements_values = fixed_array_values_copy;
FOR_WITH_HANDLE_SCOPE(
isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
Handle<Object> value(fixed_array_values->get(i), isolate);
if (value->IsArrayBoilerplateDescription() ||
value->IsObjectBoilerplateDescription()) {
Handle<Object> result =
InnerCreateBoilerplate(isolate, value, allocation);
fixed_array_values_copy->set(i, *result);
}
});
}
}
} else {
Handle<FixedArray> fixed_array_values =
Handle<FixedArray>::cast(constant_elements_values);
Handle<FixedArray> fixed_array_values_copy =
isolate->factory()->CopyFixedArray(fixed_array_values);
copied_elements_values = fixed_array_values_copy;
FOR_WITH_HANDLE_SCOPE(
isolate, int, i = 0, i, i < fixed_array_values->length(), i++, {
Handle<Object> value(fixed_array_values->get(i), isolate);
return isolate->factory()->NewJSArrayWithElements(
copied_elements_values, constant_elements_kind,
copied_elements_values->length(), allocation);
if (value->IsArrayBoilerplateDescription() ||
value->IsObjectBoilerplateDescription()) {
Handle<Object> result =
InnerCreateBoilerplate(isolate, value, allocation);
fixed_array_values_copy->set(i, *result);
}
});
}
}
};
return isolate->factory()->NewJSArrayWithElements(
copied_elements_values, constant_elements_kind,
copied_elements_values->length(), allocation);
}
Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
Handle<Object> description,
@ -554,6 +578,7 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
usage_context.ExitScope(site, boilerplate);
return copy;
}
} // namespace
RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {