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( |