| Index: src/compiler/js-type-hint-lowering.cc
|
| diff --git a/src/compiler/js-type-hint-lowering.cc b/src/compiler/js-type-hint-lowering.cc
|
| index 0d6518606c0a4f7684b45c080465cd4b700d749c..0c3226b5a965b8c8d9ed1fa31dbf2d8372857fa1 100644
|
| --- a/src/compiler/js-type-hint-lowering.cc
|
| +++ b/src/compiler/js-type-hint-lowering.cc
|
| @@ -4,8 +4,10 @@
|
|
|
| #include "src/compiler/js-type-hint-lowering.h"
|
|
|
| +#include "src/compiler/access-info.h"
|
| #include "src/compiler/js-graph.h"
|
| #include "src/compiler/operator-properties.h"
|
| +#include "src/compiler/property-access-builder.h"
|
| #include "src/compiler/simplified-operator.h"
|
| #include "src/feedback-vector.h"
|
| #include "src/type-hints.h"
|
| @@ -196,8 +198,16 @@ class JSSpeculativeBinopBuilder final {
|
|
|
| JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph,
|
| Handle<FeedbackVector> feedback_vector,
|
| + Handle<Context> native_context,
|
| + CompilationDependencies* dependencies,
|
| Flags flags)
|
| - : jsgraph_(jsgraph), flags_(flags), feedback_vector_(feedback_vector) {}
|
| + : jsgraph_(jsgraph),
|
| + flags_(flags),
|
| + feedback_vector_(feedback_vector),
|
| + native_context_(native_context),
|
| + dependencies_(dependencies) {}
|
| +
|
| +Graph* JSTypeHintLowering::graph() const { return jsgraph_->graph(); }
|
|
|
| Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
|
| Node* left, Node* right,
|
| @@ -274,8 +284,8 @@ Reduction JSTypeHintLowering::ReduceToPrimitiveToStringOperation(
|
| return Reduction();
|
| }
|
|
|
| -Reduction JSTypeHintLowering::ReduceLoadNamedOperation(
|
| - const Operator* op, Node* obj, Node* effect, Node* control,
|
| +JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceLoadNamedOperation(
|
| + const Operator* op, Node* receiver, Node* effect, Node* control,
|
| FeedbackSlot slot) const {
|
| DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode());
|
| DCHECK(!slot.IsInvalid());
|
| @@ -283,9 +293,61 @@ Reduction JSTypeHintLowering::ReduceLoadNamedOperation(
|
| if (Node* node = TryBuildSoftDeopt(
|
| nexus, effect, control,
|
| DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess)) {
|
| - return Reduction(node);
|
| + return LoweringResult::Exit(node);
|
| }
|
| - return Reduction();
|
| +
|
| + // Try to extract maps from the feedback vector. Give up if the IC
|
| + // is megamorphic or unitialized.
|
| + MapHandles receiver_maps;
|
| + if (nexus.ExtractMaps(&receiver_maps) == 0) {
|
| + return LoweringResult::NoChange();
|
| + }
|
| +
|
| + // Extract information about accesses from the maps.
|
| + NamedAccess const& p = NamedAccessOf(op);
|
| + AccessInfoFactory access_info_factory(dependencies(), native_context(),
|
| + graph()->zone());
|
| + // TODO(jarin) Use a temporary zone here.
|
| + ZoneVector<PropertyAccessInfo> access_infos(graph()->zone());
|
| + if (!access_info_factory.ComputePropertyAccessInfos(
|
| + receiver_maps, p.name(), AccessMode::kLoad, &access_infos)) {
|
| + return LoweringResult::NoChange();
|
| + }
|
| +
|
| + // Bail out if not monomorphic.
|
| + if (access_infos.size() != 1) return LoweringResult::NoChange();
|
| +
|
| + // We only lower data fields and data constants.
|
| + PropertyAccessInfo const& access_info = access_infos[0];
|
| + if (!access_info.IsDataField() && !access_info.IsDataConstant()) {
|
| + return LoweringResult::NoChange();
|
| + }
|
| +
|
| + PropertyAccessBuilder access_builder(jsgraph(), dependencies());
|
| + if (!access_builder.TryBuildStringCheck(access_info.receiver_maps(),
|
| + &receiver, &effect, control) &&
|
| + !access_builder.TryBuildNumberCheck(access_info.receiver_maps(),
|
| + &receiver, &effect, control)) {
|
| + receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control);
|
| + access_builder.BuildCheckMaps(receiver, &effect, control,
|
| + access_info.receiver_maps());
|
| + }
|
| +
|
| + Handle<JSObject> holder;
|
| + if (access_info.holder().ToHandle(&holder)) {
|
| + access_builder.AssumePrototypesStable(native_context(),
|
| + access_info.receiver_maps(), holder);
|
| + }
|
| +
|
| + Node* value = nullptr;
|
| + if (access_info.IsDataConstant()) {
|
| + value = jsgraph()->Constant(access_info.constant());
|
| + } else {
|
| + DCHECK(access_info.IsDataField());
|
| + value = access_builder.BuildLoadDataField(p.name(), access_info, receiver,
|
| + &effect, &control);
|
| + }
|
| + return LoweringResult::SideEffectFree(value, effect, control);
|
| }
|
|
|
| Reduction JSTypeHintLowering::ReduceLoadKeyedOperation(
|
|
|