diff options
Diffstat (limited to 'deps/v8/src/compiler/js-native-context-specialization.cc')
-rw-r--r-- | deps/v8/src/compiler/js-native-context-specialization.cc | 187 |
1 files changed, 137 insertions, 50 deletions
diff --git a/deps/v8/src/compiler/js-native-context-specialization.cc b/deps/v8/src/compiler/js-native-context-specialization.cc index b2f8c567e2..35e0a551db 100644 --- a/deps/v8/src/compiler/js-native-context-specialization.cc +++ b/deps/v8/src/compiler/js-native-context-specialization.cc @@ -76,6 +76,10 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) { return ReduceJSHasInPrototypeChain(node); case IrOpcode::kJSOrdinaryHasInstance: return ReduceJSOrdinaryHasInstance(node); + case IrOpcode::kJSPromiseResolve: + return ReduceJSPromiseResolve(node); + case IrOpcode::kJSResolvePromise: + return ReduceJSResolvePromise(node); case IrOpcode::kJSLoadContext: return ReduceJSLoadContext(node); case IrOpcode::kJSLoadGlobal: @@ -168,7 +172,7 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { if (m.HasValue() && m.Value()->IsJSObject()) { receiver = Handle<JSObject>::cast(m.Value()); } else if (p.feedback().IsValid()) { - InstanceOfICNexus nexus(p.feedback().vector(), p.feedback().slot()); + FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot()); if (!nexus.GetConstructorFeedback().ToHandle(&receiver)) return NoChange(); } else { return NoChange(); @@ -411,6 +415,87 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance( return NoChange(); } +// ES section #sec-promise-resolve +Reduction JSNativeContextSpecialization::ReduceJSPromiseResolve(Node* node) { + DCHECK_EQ(IrOpcode::kJSPromiseResolve, node->opcode()); + Node* constructor = NodeProperties::GetValueInput(node, 0); + Node* value = NodeProperties::GetValueInput(node, 1); + Node* context = NodeProperties::GetContextInput(node); + Node* frame_state = NodeProperties::GetFrameStateInput(node); + Node* effect = NodeProperties::GetEffectInput(node); + Node* control = NodeProperties::GetControlInput(node); + + // Check if the {constructor} is the %Promise% function. + HeapObjectMatcher m(constructor); + if (!m.Is(handle(native_context()->promise_function()))) return NoChange(); + + // Check if we know something about the {value}. + ZoneHandleSet<Map> value_maps; + NodeProperties::InferReceiverMapsResult result = + NodeProperties::InferReceiverMaps(value, effect, &value_maps); + if (result == NodeProperties::kNoReceiverMaps) return NoChange(); + DCHECK_NE(0, value_maps.size()); + + // Check that the {value} cannot be a JSPromise. + for (Handle<Map> const value_map : value_maps) { + if (value_map->IsJSPromiseMap()) return NoChange(); + } + + // Create a %Promise% instance and resolve it with {value}. + Node* promise = effect = + graph()->NewNode(javascript()->CreatePromise(), context, effect); + effect = graph()->NewNode(javascript()->ResolvePromise(), promise, value, + context, frame_state, effect, control); + ReplaceWithValue(node, promise, effect, control); + return Replace(promise); +} + +// ES section #sec-promise-resolve-functions +Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) { + DCHECK_EQ(IrOpcode::kJSResolvePromise, node->opcode()); + Node* promise = NodeProperties::GetValueInput(node, 0); + Node* resolution = NodeProperties::GetValueInput(node, 1); + Node* context = NodeProperties::GetContextInput(node); + Node* effect = NodeProperties::GetEffectInput(node); + Node* control = NodeProperties::GetControlInput(node); + + // Check if we know something about the {resolution}. + ZoneHandleSet<Map> resolution_maps; + NodeProperties::InferReceiverMapsResult result = + NodeProperties::InferReceiverMaps(resolution, effect, &resolution_maps); + if (result != NodeProperties::kReliableReceiverMaps) return NoChange(); + DCHECK_NE(0, resolution_maps.size()); + + // Compute property access info for "then" on {resolution}. + PropertyAccessInfo access_info; + AccessInfoFactory access_info_factory(dependencies(), native_context(), + graph()->zone()); + if (!access_info_factory.ComputePropertyAccessInfo( + MapHandles(resolution_maps.begin(), resolution_maps.end()), + factory()->then_string(), AccessMode::kLoad, &access_info)) { + return NoChange(); + } + + // We can further optimize the case where {resolution} + // definitely doesn't have a "then" property. + if (!access_info.IsNotFound()) return NoChange(); + PropertyAccessBuilder access_builder(jsgraph(), dependencies()); + + // Add proper dependencies on the {resolution}s [[Prototype]]s. + Handle<JSObject> holder; + if (access_info.holder().ToHandle(&holder)) { + access_builder.AssumePrototypesStable(native_context(), + access_info.receiver_maps(), holder); + } + + // Simply fulfill the {promise} with the {resolution}. + Node* value = effect = + graph()->NewNode(javascript()->FulfillPromise(), promise, resolution, + context, effect, control); + ReplaceWithValue(node, value, effect, control); + return Replace(value); +} + Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) { DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); ContextAccess const& access = ContextAccessOf(node->op()); @@ -945,16 +1030,6 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( return ReduceGlobalAccess(node, nullptr, value, name, access_mode); } - // Check if the {nexus} reports type feedback for the IC. - if (nexus.IsUninitialized()) { - if (flags() & kBailoutOnUninitialized) { - return ReduceSoftDeoptimize( - node, - DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess); - } - return NoChange(); - } - // Extract receiver maps from the IC using the {nexus}. MapHandles receiver_maps; if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { @@ -967,6 +1042,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( } return NoChange(); } + DCHECK(!nexus.IsUninitialized()); // Try to lower the named access based on the {receiver_maps}. return ReduceNamedAccess(node, value, receiver_maps, name, access_mode); @@ -1007,9 +1083,9 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { } } - // Extract receiver maps from the load IC using the LoadICNexus. + // Extract receiver maps from the load IC using the FeedbackNexus. if (!p.feedback().IsValid()) return NoChange(); - LoadICNexus nexus(p.feedback().vector(), p.feedback().slot()); + FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot()); // Try to lower the named access based on the {receiver_maps}. return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), @@ -1022,9 +1098,9 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) { NamedAccess const& p = NamedAccessOf(node->op()); Node* const value = NodeProperties::GetValueInput(node, 1); - // Extract receiver maps from the store IC using the StoreICNexus. + // Extract receiver maps from the store IC using the FeedbackNexus. if (!p.feedback().IsValid()) return NoChange(); - StoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); + FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot()); // Try to lower the named access based on the {receiver_maps}. return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), @@ -1036,9 +1112,9 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreNamedOwn(Node* node) { StoreNamedOwnParameters const& p = StoreNamedOwnParametersOf(node->op()); Node* const value = NodeProperties::GetValueInput(node, 1); - // Extract receiver maps from the IC using the StoreOwnICNexus. + // Extract receiver maps from the IC using the FeedbackNexus. if (!p.feedback().IsValid()) return NoChange(); - StoreOwnICNexus nexus(p.feedback().vector(), p.feedback().slot()); + FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot()); // Try to lower the creation of a named property based on the {receiver_maps}. return ReduceNamedAccessFromNexus(node, value, nexus, p.name(), @@ -1264,9 +1340,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( return Replace(value); } -template <typename KeyedICNexus> Reduction JSNativeContextSpecialization::ReduceKeyedAccess( - Node* node, Node* index, Node* value, KeyedICNexus const& nexus, + Node* node, Node* index, Node* value, FeedbackNexus const& nexus, AccessMode access_mode, KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode) { DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || @@ -1354,16 +1429,6 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess( } } - // Check if the {nexus} reports type feedback for the IC. - if (nexus.IsUninitialized()) { - if (flags() & kBailoutOnUninitialized) { - return ReduceSoftDeoptimize( - node, - DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess); - } - return NoChange(); - } - // Extract receiver maps from the {nexus}. MapHandles receiver_maps; if (!ExtractReceiverMaps(receiver, effect, nexus, &receiver_maps)) { @@ -1376,6 +1441,7 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess( } return NoChange(); } + DCHECK(!nexus.IsUninitialized()); // Optimize access for constant {index}. HeapObjectMatcher mindex(index); @@ -1543,9 +1609,9 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) { } } - // Extract receiver maps from the keyed load IC using the KeyedLoadICNexus. + // Extract receiver maps from the keyed load IC using the FeedbackNexus. if (!p.feedback().IsValid()) return NoChange(); - KeyedLoadICNexus nexus(p.feedback().vector(), p.feedback().slot()); + FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot()); // Extract the keyed access load mode from the keyed load IC. KeyedAccessLoadMode load_mode = nexus.GetKeyedAccessLoadMode(); @@ -1561,9 +1627,9 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) { Node* const index = NodeProperties::GetValueInput(node, 1); Node* const value = NodeProperties::GetValueInput(node, 2); - // Extract receiver maps from the keyed store IC using the KeyedStoreICNexus. + // Extract receiver maps from the keyed store IC using the FeedbackNexus. if (!p.feedback().IsValid()) return NoChange(); - KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); + FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot()); // Extract the keyed access store mode from the keyed store IC. KeyedAccessStoreMode store_mode = nexus.GetKeyedAccessStoreMode(); @@ -1663,7 +1729,7 @@ Node* JSNativeContextSpecialization::InlineApiCall( CallApiCallbackStub stub(isolate(), argc); CallInterfaceDescriptor call_interface_descriptor = stub.GetCallInterfaceDescriptor(); - CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor( + auto call_descriptor = Linkage::GetStubCallDescriptor( isolate(), graph()->zone(), call_interface_descriptor, call_interface_descriptor.GetStackParameterCount() + argc + 1 /* implicit receiver */, @@ -1960,8 +2026,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral( if (!p.feedback().IsValid()) return NoChange(); - StoreDataPropertyInLiteralICNexus nexus(p.feedback().vector(), - p.feedback().slot()); + FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot()); if (nexus.IsUninitialized()) { return NoChange(); } @@ -2124,12 +2189,18 @@ JSNativeContextSpecialization::BuildElementAccess( if (load_mode == LOAD_IGNORE_OUT_OF_BOUNDS || store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { - // Check that the {index} is a valid array index, we do the actual - // bounds check below and just skip the store below if it's out of + // Only check that the {index} is in Signed32 range. We do the actual + // bounds check below and just skip the property access if it's out of // bounds for the {receiver}. index = effect = graph()->NewNode( - simplified()->CheckBounds(VectorSlotPair()), index, - jsgraph()->Constant(Smi::kMaxValue), effect, control); + simplified()->SpeculativeToNumber(NumberOperationHint::kSigned32, + VectorSlotPair()), + index, effect, control); + + // Cast the {index} to Unsigned32 range, so that the bounds checks + // below are performed on unsigned values, which means that all the + // Negative32 values are treated as out-of-bounds. + index = graph()->NewNode(simplified()->NumberToUint32(), index); } else { // Check that the {index} is in the valid range for the {receiver}. index = effect = @@ -2193,10 +2264,10 @@ JSNativeContextSpecialization::BuildElementAccess( case AccessMode::kStore: { // Ensure that the {value} is actually a Number or an Oddball, // and truncate it to a Number appropriately. - value = effect = - graph()->NewNode(simplified()->SpeculativeToNumber( - NumberOperationHint::kNumberOrOddball), - value, effect, control); + value = effect = graph()->NewNode( + simplified()->SpeculativeToNumber( + NumberOperationHint::kNumberOrOddball, VectorSlotPair()), + value, effect, control); // Introduce the appropriate truncation for {value}. Currently we // only need to do this for ClamedUint8Array {receiver}s, as the @@ -2246,10 +2317,11 @@ JSNativeContextSpecialization::BuildElementAccess( simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, effect, control); - // Don't try to store to a copy-on-write backing store. + // Don't try to store to a copy-on-write backing store (unless supported by + // the store mode). if (access_mode == AccessMode::kStore && IsSmiOrObjectElementsKind(elements_kind) && - store_mode != STORE_NO_TRANSITION_HANDLE_COW) { + !IsCOWHandlingStoreMode(store_mode)) { effect = graph()->NewNode( simplified()->CheckMaps( CheckMapsFlag::kNone, @@ -2459,6 +2531,15 @@ JSNativeContextSpecialization::BuildElementAccess( simplified()->MaybeGrowFastElements(mode, VectorSlotPair()), receiver, elements, index, elements_length, effect, control); + // If we didn't grow {elements}, it might still be COW, in which case we + // copy it now. + if (IsSmiOrObjectElementsKind(elements_kind) && + store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW) { + elements = effect = + graph()->NewNode(simplified()->EnsureWritableFastElements(), + receiver, elements, effect, control); + } + // Also update the "length" property if {receiver} is a JSArray. if (receiver_is_jsarray) { Node* check = @@ -2524,13 +2605,16 @@ Node* JSNativeContextSpecialization::BuildIndexedStringLoad( graph()->NewNode(simplified()->MaskIndexWithBound(), index, length); Node* if_true = graph()->NewNode(common()->IfTrue(), branch); - Node* vtrue = graph()->NewNode(simplified()->StringCharAt(), receiver, - masked_index, if_true); + Node* etrue; + Node* vtrue = etrue = graph()->NewNode( + simplified()->StringCharAt(), receiver, masked_index, *effect, if_true); Node* if_false = graph()->NewNode(common()->IfFalse(), branch); Node* vfalse = jsgraph()->UndefinedConstant(); *control = graph()->NewNode(common()->Merge(2), if_true, if_false); + *effect = + graph()->NewNode(common()->EffectPhi(2), etrue, *effect, *control); return graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, *control); } else { @@ -2543,8 +2627,10 @@ Node* JSNativeContextSpecialization::BuildIndexedStringLoad( graph()->NewNode(simplified()->MaskIndexWithBound(), index, length); // Return the character from the {receiver} as single character string. - return graph()->NewNode(simplified()->StringCharAt(), receiver, - masked_index, *control); + Node* value = *effect = + graph()->NewNode(simplified()->StringCharAt(), receiver, masked_index, + *effect, *control); + return value; } } @@ -2652,6 +2738,7 @@ bool JSNativeContextSpecialization::ExtractReceiverMaps( Node* receiver, Node* effect, FeedbackNexus const& nexus, MapHandles* receiver_maps) { DCHECK_EQ(0, receiver_maps->size()); + if (nexus.IsUninitialized()) return true; // See if we can infer a concrete type for the {receiver}. if (InferReceiverMaps(receiver, effect, receiver_maps)) { // We can assume that the {receiver} still has the inferred {receiver_maps}. |