Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
index fbc064c..81d4cd0 100644
--- a/src/compiler/js-native-context-specialization.cc
+++ b/src/compiler/js-native-context-specialization.cc
@@ -15,7 +15,6 @@
#include "src/compiler/node-matchers.h"
#include "src/field-index-inl.h"
#include "src/isolate-inl.h"
-#include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker!
#include "src/type-cache.h"
#include "src/type-feedback-vector.h"
@@ -79,9 +78,9 @@
node->opcode() == IrOpcode::kJSLoadProperty ||
node->opcode() == IrOpcode::kJSStoreProperty);
Node* receiver = NodeProperties::GetValueInput(node, 0);
- Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
+ Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
@@ -112,8 +111,8 @@
if (index != nullptr) {
Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()),
index, jsgraph()->HeapConstant(name));
- control = graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
- effect, control);
+ control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
+ frame_state, effect, control);
}
// Check if {receiver} may be a number.
@@ -126,17 +125,17 @@
}
// Ensure that {receiver} is a heap object.
- Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
Node* receiverissmi_control = nullptr;
Node* receiverissmi_effect = effect;
if (receiverissmi_possible) {
+ Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
Node* branch = graph()->NewNode(common()->Branch(), check, control);
control = graph()->NewNode(common()->IfFalse(), branch);
receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
receiverissmi_effect = effect;
} else {
- control = graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
- effect, control);
+ receiver = effect = graph()->NewNode(simplified()->CheckTaggedPointer(),
+ receiver, effect, control);
}
// Load the {receiver} map. The resulting effect is the dominating effect for
@@ -159,7 +158,7 @@
if (receiver_type->Is(Type::String())) {
Node* check = graph()->NewNode(simplified()->ObjectIsString(), receiver);
if (j == access_infos.size() - 1) {
- this_control =
+ this_control = this_effect =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
this_effect, fallthrough_control);
fallthrough_control = nullptr;
@@ -182,10 +181,11 @@
graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()),
receiver_map, jsgraph()->Constant(map));
if (--num_classes == 0 && j == access_infos.size() - 1) {
- this_controls.push_back(
+ Node* deoptimize =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
- this_effect, fallthrough_control));
- this_effects.push_back(this_effect);
+ this_effect, fallthrough_control);
+ this_controls.push_back(deoptimize);
+ this_effects.push_back(deoptimize);
fallthrough_control = nullptr;
} else {
Node* branch =
@@ -237,38 +237,14 @@
if (access_mode == AccessMode::kStore) {
Node* check = graph()->NewNode(
simplified()->ReferenceEqual(Type::Tagged()), value, this_value);
- this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
- frame_state, this_effect, this_control);
+ this_control = this_effect =
+ graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+ this_effect, this_control);
}
} else {
DCHECK(access_info.IsDataField());
FieldIndex const field_index = access_info.field_index();
- FieldCheck const field_check = access_info.field_check();
Type* const field_type = access_info.field_type();
- switch (field_check) {
- case FieldCheck::kNone:
- break;
- case FieldCheck::kJSArrayBufferViewBufferNotNeutered: {
- Node* this_buffer = this_effect =
- graph()->NewNode(simplified()->LoadField(
- AccessBuilder::ForJSArrayBufferViewBuffer()),
- this_receiver, this_effect, this_control);
- Node* this_buffer_bit_field = this_effect =
- graph()->NewNode(simplified()->LoadField(
- AccessBuilder::ForJSArrayBufferBitField()),
- this_buffer, this_effect, this_control);
- Node* check = graph()->NewNode(
- machine()->Word32Equal(),
- graph()->NewNode(machine()->Word32And(), this_buffer_bit_field,
- jsgraph()->Int32Constant(
- 1 << JSArrayBuffer::WasNeutered::kShift)),
- jsgraph()->Int32Constant(0));
- this_control =
- graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
- this_effect, this_control);
- break;
- }
- }
if (access_mode == AccessMode::kLoad &&
access_info.holder().ToHandle(&holder)) {
this_receiver = jsgraph()->Constant(holder);
@@ -284,6 +260,11 @@
field_type, MachineType::AnyTagged(), kFullWriteBarrier};
if (access_mode == AccessMode::kLoad) {
if (field_type->Is(Type::UntaggedFloat64())) {
+ // TODO(turbofan): We remove the representation axis from the type to
+ // avoid uninhabited representation types. This is a workaround until
+ // the {PropertyAccessInfo} is using {MachineRepresentation} instead.
+ field_access.type = Type::Union(
+ field_type, Type::Representation(Type::Number(), zone()), zone());
if (!field_index.is_inobject() || field_index.is_hidden_field() ||
!FLAG_unbox_double_fields) {
this_storage = this_effect =
@@ -300,9 +281,14 @@
} else {
DCHECK_EQ(AccessMode::kStore, access_mode);
if (field_type->Is(Type::UntaggedFloat64())) {
+ // TODO(turbofan): We remove the representation axis from the type to
+ // avoid uninhabited representation types. This is a workaround until
+ // the {PropertyAccessInfo} is using {MachineRepresentation} instead.
+ field_access.type = Type::Union(
+ field_type, Type::Representation(Type::Number(), zone()), zone());
Node* check =
graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
- this_control =
+ this_control = this_effect =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
this_effect, this_control);
this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
@@ -312,8 +298,9 @@
!FLAG_unbox_double_fields) {
if (access_info.HasTransitionMap()) {
// Allocate a MutableHeapNumber for the new property.
- this_effect =
- graph()->NewNode(common()->BeginRegion(), this_effect);
+ this_effect = graph()->NewNode(
+ common()->BeginRegion(RegionObservability::kNotObservable),
+ this_effect);
Node* this_box = this_effect =
graph()->NewNode(simplified()->Allocate(NOT_TENURED),
jsgraph()->Constant(HeapNumber::kSize),
@@ -343,19 +330,12 @@
field_access.machine_type = MachineType::Float64();
}
} else if (field_type->Is(Type::TaggedSigned())) {
- Node* check =
- graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
- this_control =
- graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+ this_value = this_effect =
+ graph()->NewNode(simplified()->CheckTaggedSigned(), this_value,
this_effect, this_control);
- this_value =
- graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi),
- this_value, this_control);
} else if (field_type->Is(Type::TaggedPointer())) {
- Node* check =
- graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
- this_control =
- graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
+ this_value = this_effect =
+ graph()->NewNode(simplified()->CheckTaggedPointer(), this_value,
this_effect, this_control);
if (field_type->NumClasses() == 1) {
// Emit a map check for the value.
@@ -365,7 +345,7 @@
Node* check = graph()->NewNode(
simplified()->ReferenceEqual(Type::Internal()), this_value_map,
jsgraph()->Constant(field_type->Classes().Current()));
- this_control =
+ this_control = this_effect =
graph()->NewNode(common()->DeoptimizeUnless(), check,
frame_state, this_effect, this_control);
} else {
@@ -376,7 +356,9 @@
}
Handle<Map> transition_map;
if (access_info.transition_map().ToHandle(&transition_map)) {
- this_effect = graph()->NewNode(common()->BeginRegion(), this_effect);
+ this_effect = graph()->NewNode(
+ common()->BeginRegion(RegionObservability::kObservable),
+ this_effect);
this_effect = graph()->NewNode(
simplified()->StoreField(AccessBuilder::ForMap()), this_receiver,
jsgraph()->Constant(transition_map), this_effect, this_control);
@@ -522,9 +504,9 @@
node->opcode() == IrOpcode::kJSStoreProperty);
Node* receiver = NodeProperties::GetValueInput(node, 0);
Node* context = NodeProperties::GetContextInput(node);
- Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
+ Node* frame_state = NodeProperties::FindFrameStateBefore(node);
// Not much we can do if deoptimization support is disabled.
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
@@ -555,9 +537,8 @@
ZoneVector<Node*> controls(zone());
// Ensure that {receiver} is a heap object.
- Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
- control = graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
- effect, control);
+ receiver = effect = graph()->NewNode(simplified()->CheckTaggedPointer(),
+ receiver, effect, control);
// Load the {receiver} map. The resulting effect is the dominating effect for
// all (polymorphic) branches.
@@ -597,17 +578,19 @@
// TODO(turbofan): This is ugly as hell! We should probably introduce
// macro-ish operators for property access that encapsulate this whole
// mess.
- this_controls.push_back(graph()->NewNode(common()->DeoptimizeUnless(),
- check, frame_state, effect,
- fallthrough_control));
+ Node* deoptimize =
+ graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+ effect, fallthrough_control);
+ this_controls.push_back(deoptimize);
+ this_effects.push_back(deoptimize);
fallthrough_control = nullptr;
} else {
Node* branch =
graph()->NewNode(common()->Branch(), check, fallthrough_control);
this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch));
+ this_effects.push_back(effect);
fallthrough_control = graph()->NewNode(common()->IfFalse(), branch);
}
- this_effects.push_back(effect);
if (!map->IsJSArrayMap()) receiver_is_jsarray = false;
}
@@ -624,7 +607,7 @@
simplified()->ReferenceEqual(Type::Any()), receiver_map,
jsgraph()->HeapConstant(transition_source));
if (--num_transitions == 0 && j == access_infos.size() - 1) {
- transition_control =
+ transition_control = transition_effect =
graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
transition_effect, fallthrough_control);
fallthrough_control = nullptr;
@@ -647,8 +630,7 @@
// Instance migration, let the stub deal with the {receiver}.
TransitionElementsKindStub stub(isolate(),
transition_source->elements_kind(),
- transition_target->elements_kind(),
- transition_source->IsJSArrayMap());
+ transition_target->elements_kind());
CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 0,
CallDescriptor::kNeedsFrameState, node->op()->properties());
@@ -657,6 +639,7 @@
receiver, jsgraph()->HeapConstant(transition_target), context,
frame_state, transition_effect, transition_control);
}
+
this_controls.push_back(transition_control);
this_effects.push_back(transition_effect);
}
@@ -675,6 +658,14 @@
graph()->NewNode(common()->EffectPhi(this_control_count),
this_control_count + 1, &this_effects.front());
}
+
+ // TODO(turbofan): The effect/control linearization will not find a
+ // FrameState after the StoreField or Call that is generated for the
+ // elements kind transition above. This is because those operators
+ // don't have the kNoWrite flag on it, even though they are not
+ // observable by JavaScript.
+ this_effect = graph()->NewNode(common()->Checkpoint(), frame_state,
+ this_effect, this_control);
}
// Certain stores need a prototype chain check because shape changes
@@ -685,28 +676,6 @@
AssumePrototypesStable(receiver_type, native_context, holder);
}
- // Check that the {index} is actually a Number.
- if (!NumberMatcher(this_index).HasValue()) {
- Node* check =
- graph()->NewNode(simplified()->ObjectIsNumber(), this_index);
- this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
- frame_state, this_effect, this_control);
- this_index = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
- this_index, this_control);
- }
-
- // Convert the {index} to an unsigned32 value and check if the result is
- // equal to the original {index}.
- if (!NumberMatcher(this_index).IsInRange(0.0, kMaxUInt32)) {
- Node* this_index32 =
- graph()->NewNode(simplified()->NumberToUint32(), this_index);
- Node* check = graph()->NewNode(simplified()->NumberEqual(), this_index32,
- this_index);
- this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
- frame_state, this_effect, this_control);
- this_index = this_index32;
- }
-
// TODO(bmeurer): We currently specialize based on elements kind. We should
// also be able to properly support strings and other JSObjects here.
ElementsKind elements_kind = access_info.elements_kind();
@@ -725,8 +694,9 @@
Node* check = graph()->NewNode(
simplified()->ReferenceEqual(Type::Any()), this_elements_map,
jsgraph()->HeapConstant(factory()->fixed_array_map()));
- this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
- frame_state, this_effect, this_control);
+ this_control = this_effect =
+ graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+ this_effect, this_control);
}
// Load the length of the {receiver}.
@@ -741,10 +711,9 @@
this_elements, this_effect, this_control);
// Check that the {index} is in the valid range for the {receiver}.
- Node* check = graph()->NewNode(simplified()->NumberLessThan(), this_index,
- this_length);
- this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
- frame_state, this_effect, this_control);
+ this_index = this_effect =
+ graph()->NewNode(simplified()->CheckBounds(), this_index, this_length,
+ this_effect, this_control);
// Compute the element access.
Type* element_type = Type::Any();
@@ -781,45 +750,26 @@
if (elements_kind == FAST_HOLEY_ELEMENTS ||
elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
// Perform the hole check on the result.
- Node* check =
- graph()->NewNode(simplified()->ReferenceEqual(element_access.type),
- this_value, jsgraph()->TheHoleConstant());
+ CheckTaggedHoleMode mode = CheckTaggedHoleMode::kNeverReturnHole;
// Check if we are allowed to turn the hole into undefined.
Type* initial_holey_array_type = Type::Class(
handle(isolate()->get_initial_js_array_map(elements_kind)),
graph()->zone());
if (receiver_type->NowIs(initial_holey_array_type) &&
isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
- Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
- check, this_control);
- Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
- Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
// Add a code dependency on the array protector cell.
AssumePrototypesStable(receiver_type, native_context,
isolate()->initial_object_prototype());
dependencies()->AssumePropertyCell(factory()->array_protector());
// Turn the hole into undefined.
- this_control =
- graph()->NewNode(common()->Merge(2), if_true, if_false);
- this_value = graph()->NewNode(
- common()->Phi(MachineRepresentation::kTagged, 2),
- jsgraph()->UndefinedConstant(), this_value, this_control);
- element_type =
- Type::Union(element_type, Type::Undefined(), graph()->zone());
- } else {
- // Deoptimize in case of the hole.
- this_control =
- graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
- this_effect, this_control);
+ mode = CheckTaggedHoleMode::kConvertHoleToUndefined;
}
- // Rename the result to represent the actual type (not polluted by the
- // hole).
- this_value = graph()->NewNode(simplified()->TypeGuard(element_type),
- this_value, this_control);
+ this_value = this_effect =
+ graph()->NewNode(simplified()->CheckTaggedHole(mode), this_value,
+ this_effect, this_control);
} else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
// Perform the hole check on the result.
- Node* check =
- graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value);
+ CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
// Check if we are allowed to return the hole directly.
Type* initial_holey_array_type = Type::Class(
handle(isolate()->get_initial_js_array_map(elements_kind)),
@@ -830,33 +780,32 @@
AssumePrototypesStable(receiver_type, native_context,
isolate()->initial_object_prototype());
dependencies()->AssumePropertyCell(factory()->array_protector());
- // Turn the hole into undefined.
- this_value = graph()->NewNode(
- common()->Select(MachineRepresentation::kTagged,
- BranchHint::kFalse),
- check, jsgraph()->UndefinedConstant(), this_value);
- } else {
- // Deoptimize in case of the hole.
- this_control =
- graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
- this_effect, this_control);
+ // Return the signaling NaN hole directly if all uses are truncating.
+ mode = CheckFloat64HoleMode::kAllowReturnHole;
}
+ this_value = this_effect =
+ graph()->NewNode(simplified()->CheckFloat64Hole(mode), this_value,
+ this_effect, this_control);
}
} else {
DCHECK_EQ(AccessMode::kStore, access_mode);
if (IsFastSmiElementsKind(elements_kind)) {
- Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value);
- this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
- frame_state, this_effect, this_control);
- this_value = graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi),
- this_value, this_control);
+ this_value = this_effect =
+ graph()->NewNode(simplified()->CheckTaggedSigned(), this_value,
+ this_effect, this_control);
} else if (IsFastDoubleElementsKind(elements_kind)) {
Node* check =
graph()->NewNode(simplified()->ObjectIsNumber(), this_value);
- this_control = graph()->NewNode(common()->DeoptimizeUnless(), check,
- frame_state, this_effect, this_control);
+ this_control = this_effect =
+ graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state,
+ this_effect, this_control);
this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()),
this_value, this_control);
+ // Make sure we do not store signalling NaNs into holey double arrays.
+ if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
+ this_value =
+ graph()->NewNode(simplified()->NumberSilenceNaN(), this_value);
+ }
}
this_effect = graph()->NewNode(simplified()->StoreElement(element_access),
this_elements, this_index, this_value,
@@ -960,9 +909,9 @@
Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(Node* node) {
- Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
+ Node* frame_state = NodeProperties::FindFrameStateBefore(node);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(DeoptimizeKind::kSoft), frame_state,
effect, control);