Commit eaf2a23b authored by Georg Schmid's avatar Georg Schmid Committed by Commit Bot

[objects] Migrate kHoleNanInt64 unboxed doubles to uninitialized values during...

[objects] Migrate kHoleNanInt64 unboxed doubles to uninitialized values during boilerplate serialization

Boilerplate values may possess an unboxed double field filled with the kHoleNan64Int sentinel value, which indicates that the field is uninitialized. When a boilerplate value migrates away from the unboxed double representation to a tagged one, we should replace the sentinel value by the proper uninitialized oddball value.

This fixes an issue with JSCreateLowering::AllocateFastLiteral not detecting const stores of uninitialized values properly.

R=bmeurer@chromium.org, jarin@chromium.org

Bug: chromium:976598
Change-Id: I6bb216c0618a3105e6c8cfc04b1900d2f83a52ce
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1674034Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Georg Schmid <gsps@google.com>
Cr-Commit-Position: refs/heads/master@{#62394}
parent 55c33c01
......@@ -283,7 +283,7 @@ class JSObjectData : public HeapObjectData {
bool cow_or_empty_elements_tenured() const;
private:
void SerializeRecursive(JSHeapBroker* broker, int max_depths);
void SerializeRecursiveAsBoilerplate(JSHeapBroker* broker, int max_depths);
FixedArrayBaseData* elements_ = nullptr;
bool cow_or_empty_elements_tenured_ = false;
......@@ -1663,7 +1663,7 @@ bool JSObjectData::cow_or_empty_elements_tenured() const {
FixedArrayBaseData* JSObjectData::elements() const { return elements_; }
void JSObjectData::SerializeAsBoilerplate(JSHeapBroker* broker) {
SerializeRecursive(broker, kMaxFastLiteralDepth);
SerializeRecursiveAsBoilerplate(broker, kMaxFastLiteralDepth);
}
void JSObjectData::SerializeElements(JSHeapBroker* broker) {
......@@ -1766,11 +1766,13 @@ void MapData::SerializeOwnDescriptor(JSHeapBroker* broker,
<< contents.size() << " total)");
}
void JSObjectData::SerializeRecursive(JSHeapBroker* broker, int depth) {
void JSObjectData::SerializeRecursiveAsBoilerplate(JSHeapBroker* broker,
int depth) {
if (serialized_as_boilerplate_) return;
serialized_as_boilerplate_ = true;
TraceScope tracer(broker, this, "JSObjectData::SerializeRecursive");
TraceScope tracer(broker, this,
"JSObjectData::SerializeRecursiveAsBoilerplate");
Handle<JSObject> boilerplate = Handle<JSObject>::cast(object());
// We only serialize boilerplates that pass the IsInlinableFastLiteral
......@@ -1816,7 +1818,8 @@ void JSObjectData::SerializeRecursive(JSHeapBroker* broker, int depth) {
Handle<Object> value(fast_elements->get(i), isolate);
if (value->IsJSObject()) {
ObjectData* value_data = broker->GetOrCreateData(value);
value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
value_data->AsJSObject()->SerializeRecursiveAsBoilerplate(broker,
depth - 1);
}
}
} else {
......@@ -1851,9 +1854,22 @@ void JSObjectData::SerializeRecursive(JSHeapBroker* broker, int depth) {
} else {
Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
isolate);
// In case of unboxed double fields we use a sentinel NaN value to mark
// uninitialized fields. A boilerplate value with such a field may migrate
// from its unboxed double to a tagged representation. In the process the
// raw double is converted to a heap number. The sentinel value carries no
// special meaning when it occurs in a heap number, so we would like to
// recover the uninitialized value.
// We check for the sentinel here, specifically, since migrations might
// have been triggered as part of boilerplate serialization.
if (value->IsHeapNumber() &&
HeapNumber::cast(*value).value_as_bits() == kHoleNanInt64) {
value = isolate->factory()->uninitialized_value();
}
ObjectData* value_data = broker->GetOrCreateData(value);
if (value->IsJSObject()) {
value_data->AsJSObject()->SerializeRecursive(broker, depth - 1);
value_data->AsJSObject()->SerializeRecursiveAsBoilerplate(broker,
depth - 1);
}
inobject_fields_.push_back(JSObjectField{value_data});
}
......
// Copyright 2019 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.
// Flags: --allow-natives-syntax
function f() {
return { value: NaN };
}
%PrepareFunctionForOptimization(f);
f();
f();
let x = { value: "Y" };
%OptimizeFunctionOnNextCall(f);
f();
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