Commit a7985022 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[json] Preallocate mutable heap numbers so object verification doesn't fail

Additionally pass WriteBarrierMode while building the object

Change-Id: Ibc8ad592f822ee3b046406013cc36ae64f6b099b
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1613251Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61547}
parent 94b2c121
......@@ -524,49 +524,82 @@ Handle<Object> JsonParser<Char>::BuildJsonObject(
descriptor++;
}
// Fast path: Write all transitioned named properties.
if (i == length && descriptor < feedback_descriptors) {
map = ParentOfDescriptorOwner(isolate_, map, map, descriptor);
}
// Preallocate all mutable heap numbers so we don't need to allocate while
// setting up the object. Otherwise verification of that object may fail.
Handle<FixedArray> mutable_doubles;
if (!FLAG_unbox_double_fields && descriptor != 0) {
descriptor = 0;
int new_mutable_double = 0;
for (int j = 0; j < i; j++) {
const JsonProperty& property = property_stack[start + j];
if (property.string.is_index()) continue;
PropertyDetails details =
map->instance_descriptors()->GetDetails(descriptor++);
if (details.representation().IsDouble() && property.value->IsSmi()) {
new_mutable_double++;
}
}
if (new_mutable_double > 0) {
mutable_doubles = factory()->NewFixedArray(new_mutable_double);
for (int i = 0; i < new_mutable_double; i++) {
Handle<MutableHeapNumber> number =
factory()->NewMutableHeapNumberWithHoleNaN();
mutable_doubles->set(i, *number);
}
}
}
Handle<JSObject> object = initial_map->is_dictionary_map()
? factory()->NewSlowJSObjectFromMap(map)
: factory()->NewJSObjectFromMap(map);
object->set_elements(*elements);
// Fast path: Write all transitioned named properties.
if (i == length && descriptor < feedback_descriptors) {
map = ParentOfDescriptorOwner(isolate_, map, map, descriptor);
}
descriptor = 0;
for (int j = 0; j < i; j++) {
const JsonProperty& property = property_stack[start + j];
if (property.string.is_index()) continue;
PropertyDetails details =
map->instance_descriptors()->GetDetails(descriptor);
Handle<Object> value = property.value;
FieldIndex index = FieldIndex::ForDescriptor(*map, descriptor);
descriptor++;
int mutable_double = 0;
{
descriptor = 0;
DisallowHeapAllocation no_gc;
WriteBarrierMode mode = object->GetWriteBarrierMode(no_gc);
for (int j = 0; j < i; j++) {
const JsonProperty& property = property_stack[start + j];
if (property.string.is_index()) continue;
PropertyDetails details =
map->instance_descriptors()->GetDetails(descriptor);
Object value = *property.value;
FieldIndex index = FieldIndex::ForDescriptor(*map, descriptor);
descriptor++;
if (details.representation().IsDouble()) {
if (object->IsUnboxedDoubleField(index)) {
uint64_t bits;
if (value.IsSmi()) {
bits = bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value)));
} else {
DCHECK(value.IsHeapNumber());
bits = HeapNumber::cast(value).value_as_bits();
}
object->RawFastDoublePropertyAsBitsAtPut(index, bits);
continue;
}
if (details.representation().IsDouble()) {
if (object->IsUnboxedDoubleField(index)) {
uint64_t bits;
if (value->IsSmi()) {
bits = bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(*value)));
if (value.IsSmi()) {
uint64_t bits =
bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value)));
value = mutable_doubles->get(mutable_double++);
MutableHeapNumber::cast(value).set_value_as_bits(bits);
} else {
DCHECK(value->IsHeapNumber());
bits = HeapNumber::cast(*value)->value_as_bits();
DCHECK(value.IsHeapNumber());
HeapObject::cast(value)->synchronized_set_map(
*factory()->mutable_heap_number_map());
}
object->RawFastDoublePropertyAsBitsAtPut(index, bits);
continue;
}
if (value->IsSmi()) {
uint64_t bits =
bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(*value)));
value = factory()->NewMutableHeapNumberFromBits(bits);
} else {
DCHECK(value->IsHeapNumber());
HeapObject::cast(*value)->synchronized_set_map(
*factory()->mutable_heap_number_map());
}
object->RawFastPropertyAtPut(index, value, mode);
}
object->RawFastPropertyAtPut(index, *value);
}
// Slow path: define remaining named properties.
......
......@@ -341,12 +341,14 @@ uint64_t JSObject::RawFastDoublePropertyAsBitsAt(FieldIndex index) {
return READ_UINT64_FIELD(*this, index.offset());
}
void JSObject::RawFastPropertyAtPut(FieldIndex index, Object value) {
void JSObject::RawFastPropertyAtPut(FieldIndex index, Object value,
WriteBarrierMode mode) {
if (index.is_inobject()) {
int offset = index.offset();
WRITE_FIELD(*this, offset, value);
WRITE_BARRIER(*this, offset, value);
CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
} else {
DCHECK_EQ(UPDATE_WRITE_BARRIER, mode);
property_array()->set(index.outobject_array_index(), value);
}
}
......
......@@ -639,7 +639,9 @@ class JSObject : public JSReceiver {
inline uint64_t RawFastDoublePropertyAsBitsAt(FieldIndex index);
inline void FastPropertyAtPut(FieldIndex index, Object value);
inline void RawFastPropertyAtPut(FieldIndex index, Object value);
inline void RawFastPropertyAtPut(
FieldIndex index, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void RawFastDoublePropertyAsBitsAtPut(FieldIndex index, uint64_t bits);
inline void WriteToField(int descriptor, PropertyDetails details,
Object value);
......
......@@ -72,7 +72,7 @@ function generate(n) {
print("generating");
var str = generate(30000);
var str = generate(10000);
print("parsing " + str.length);
JSON.parse(str);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment