Commit b6e1c4e2 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[turbofan] Avoid map check for copy-on-write constant-folding.

When loading a known value from a JSArray with a copy-on-write backing
store, we don't need to actually do a map check on the JSArray, but just
check that the backing store didn't change in the meantime.

R=jarin@chromium.org

Bug: v8:6816, v8:6815
Change-Id: I6764f3b8af7d4c17b9f6d2396555b584eae08176
Reviewed-on: https://chromium-review.googlesource.com/691721Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48218}
parent 2218522b
......@@ -1268,14 +1268,44 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
LookupIterator it(isolate(), mreceiver.Value(),
static_cast<uint32_t>(mindex.Value()),
LookupIterator::OWN);
if (it.state() == LookupIterator::DATA && it.IsReadOnly() &&
!it.IsConfigurable()) {
// We can safely constant-fold the {index} access to {receiver},
// since the element is non-configurable, non-writable and thus
// cannot change anymore.
value = jsgraph()->Constant(it.GetDataValue());
ReplaceWithValue(node, value, effect, control);
return Replace(value);
if (it.state() == LookupIterator::DATA) {
if (it.IsReadOnly() && !it.IsConfigurable()) {
// We can safely constant-fold the {index} access to {receiver},
// since the element is non-configurable, non-writable and thus
// cannot change anymore.
value = jsgraph()->Constant(it.GetDataValue());
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
// Check if the {receiver} is a known constant with a copy-on-write
// backing store, and whether {index} is within the appropriate
// bounds. In that case we can constant-fold the access and only
// check that the {elements} didn't change. This is sufficient as
// the backing store of a copy-on-write JSArray is defensively copied
// whenever the length or the elements (might) change.
//
// What's interesting here is that we don't need to map check the
// {receiver}, since JSArray's will always have their elements in
// the backing store.
if (mreceiver.Value()->IsJSArray()) {
Handle<JSArray> array = Handle<JSArray>::cast(mreceiver.Value());
if (array->elements()->IsCowArray()) {
Node* elements = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
receiver, effect, control);
Handle<FixedArray> array_elements(
FixedArray::cast(array->elements()), isolate());
Node* check =
graph()->NewNode(simplified()->ReferenceEqual(), elements,
jsgraph()->HeapConstant(array_elements));
effect = graph()->NewNode(simplified()->CheckIf(), check, effect,
control);
value = jsgraph()->Constant(it.GetDataValue());
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
}
}
}
......@@ -2182,43 +2212,6 @@ JSNativeContextSpecialization::BuildElementAccess(
simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
effect, control);
// Check if the {receiver} is a known constant with a copy-on-write
// backing store, and whether {index} is within the appropriate
// bounds. In that case we can constant-fold the access and only
// check that the {elements} didn't change. This is sufficient as
// the backing store of a copy-on-write JSArray is defensively copied
// whenever the length or the elements (might) change.
if (access_mode == AccessMode::kLoad) {
HeapObjectMatcher mreceiver(receiver);
if (mreceiver.HasValue() && mreceiver.Value()->IsJSArray()) {
Handle<JSArray> array = Handle<JSArray>::cast(mreceiver.Value());
if (std::find_if(receiver_maps.begin(), receiver_maps.end(),
[array](Handle<Map> map) {
return *map == array->map();
}) != receiver_maps.end()) {
uint32_t length;
if (array->length()->ToUint32(&length) &&
array->elements()->IsCowArray()) {
NumberMatcher mindex(index);
if (mindex.IsInteger() && mindex.IsInRange(0, length - 1)) {
Handle<FixedArray> array_elements(
FixedArray::cast(array->elements()), isolate());
Handle<Object> array_element(
array_elements->get(static_cast<int>(mindex.Value())),
isolate());
Node* check =
graph()->NewNode(simplified()->ReferenceEqual(), elements,
jsgraph()->HeapConstant(array_elements));
effect = graph()->NewNode(simplified()->CheckIf(), check, effect,
control);
Node* value = jsgraph()->Constant(array_element);
return ValueEffectControl(value, effect, control);
}
}
}
}
}
// Don't try to store to a copy-on-write backing store.
if (access_mode == AccessMode::kStore &&
IsSmiOrObjectElementsKind(elements_kind) &&
......
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