[turbofan] Pass deoptimization mode to type feedback specializer.
authorbmeurer <bmeurer@chromium.org>
Wed, 20 May 2015 17:01:31 +0000 (10:01 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 20 May 2015 17:01:17 +0000 (17:01 +0000)
R=jarin@chromium.org

Review URL: https://codereview.chromium.org/1145143002

Cr-Commit-Position: refs/heads/master@{#28524}

src/compiler/js-type-feedback.cc
src/compiler/js-type-feedback.h
src/compiler/pipeline.cc
test/unittests/compiler/js-type-feedback-unittest.cc

index 689e4ac..1a218c2 100644 (file)
@@ -173,7 +173,7 @@ Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) {
     return ReduceJSLoadNamedForGlobalVariable(node);
   }
 
-  if (!FLAG_turbo_deoptimization) return NoChange();
+  if (mode() != kDeoptimizationEnabled) return NoChange();
   Node* frame_state_before = GetFrameStateBefore(node);
   if (frame_state_before == nullptr) return NoChange();
 
@@ -245,7 +245,7 @@ Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamedForGlobalVariable(
     return NoChange();
   }
 
-  if (FLAG_turbo_deoptimization) {
+  if (mode() == kDeoptimizationEnabled) {
     // Handle lookups in the script context.
     {
       Handle<ScriptContextTable> script_contexts(
index 17a6b58..80a0d56 100644 (file)
@@ -62,10 +62,13 @@ class JSTypeFeedbackTable : public ZoneObject {
 // {js_type_feedback} provided to the constructor.
 class JSTypeFeedbackSpecializer : public AdvancedReducer {
  public:
+  enum DeoptimizationMode { kDeoptimizationEnabled, kDeoptimizationDisabled };
+
   JSTypeFeedbackSpecializer(Editor* editor, JSGraph* jsgraph,
                             JSTypeFeedbackTable* js_type_feedback,
                             TypeFeedbackOracle* oracle,
                             Handle<GlobalObject> global_object,
+                            DeoptimizationMode mode,
                             CompilationDependencies* dependencies)
       : AdvancedReducer(editor),
         jsgraph_(jsgraph),
@@ -73,8 +76,9 @@ class JSTypeFeedbackSpecializer : public AdvancedReducer {
         js_type_feedback_(js_type_feedback),
         oracle_(oracle),
         global_object_(global_object),
+        mode_(mode),
         dependencies_(dependencies) {
-    CHECK(js_type_feedback);
+    CHECK_NOT_NULL(js_type_feedback);
   }
 
   Reduction Reduce(Node* node) override;
@@ -92,12 +96,14 @@ class JSTypeFeedbackSpecializer : public AdvancedReducer {
   JSTypeFeedbackTable* js_type_feedback_;
   TypeFeedbackOracle* oracle_;
   Handle<GlobalObject> global_object_;
+  DeoptimizationMode const mode_;
   CompilationDependencies* dependencies_;
 
   TypeFeedbackOracle* oracle() { return oracle_; }
   Graph* graph() { return jsgraph_->graph(); }
   JSGraph* jsgraph() { return jsgraph_; }
   CommonOperatorBuilder* common() { return jsgraph_->common(); }
+  DeoptimizationMode mode() const { return mode_; }
   SimplifiedOperatorBuilder* simplified() { return &simplified_; }
 
   void BuildMapCheck(Node* receiver, Handle<Map> map, bool smi_check,
index 4118e1d..e74c9fb 100644 (file)
@@ -546,7 +546,10 @@ struct JSTypeFeedbackPhase {
     // specializing to the global object here.
     JSTypeFeedbackSpecializer specializer(
         &graph_reducer, data->jsgraph(), data->js_type_feedback(), &oracle,
-        global_object, data->info()->dependencies());
+        global_object, data->info()->is_deoptimization_enabled()
+                           ? JSTypeFeedbackSpecializer::kDeoptimizationEnabled
+                           : JSTypeFeedbackSpecializer::kDeoptimizationDisabled,
+        data->info()->dependencies());
     AddReducer(data, &graph_reducer, &specializer);
     graph_reducer.ReduceGraph();
   }
@@ -1048,9 +1051,7 @@ Handle<Code> Pipeline::GenerateCode() {
       RunPrintAndVerify("OSR deconstruction");
     }
 
-    // TODO(turbofan): Type feedback currently requires deoptimization.
-    if (info()->is_deoptimization_enabled() &&
-        info()->is_type_feedback_enabled()) {
+    if (info()->is_type_feedback_enabled()) {
       Run<JSTypeFeedbackPhase>();
       RunPrintAndVerify("JSType feedback");
     }
index c243c5f..2691d3f 100644 (file)
@@ -34,7 +34,8 @@ class JSTypeFeedbackTest : public TypedGraphTest {
   ~JSTypeFeedbackTest() override { dependencies_.Rollback(); }
 
  protected:
-  Reduction Reduce(Node* node) {
+  Reduction Reduce(Node* node,
+                   JSTypeFeedbackSpecializer::DeoptimizationMode mode) {
     Handle<GlobalObject> global_object(
         isolate()->native_context()->global_object(), isolate());
 
@@ -44,7 +45,7 @@ class JSTypeFeedbackTest : public TypedGraphTest {
     // TODO(titzer): mock the GraphReducer here for better unit testing.
     GraphReducer graph_reducer(graph(), zone());
     JSTypeFeedbackSpecializer reducer(&graph_reducer, &jsgraph, &table, nullptr,
-                                      global_object, &dependencies_);
+                                      global_object, mode, &dependencies_);
     return reducer.Reduce(node);
   }
 
@@ -73,8 +74,9 @@ class JSTypeFeedbackTest : public TypedGraphTest {
     result.Assert();
   }
 
-  Node* ReturnLoadNamedFromGlobal(const char* string, Node* effect,
-                                  Node* control) {
+  Node* ReturnLoadNamedFromGlobal(
+      const char* string, Node* effect, Node* control,
+      JSTypeFeedbackSpecializer::DeoptimizationMode mode) {
     VectorSlotPair feedback(Handle<TypeFeedbackVector>::null(),
                             FeedbackVectorICSlot::Invalid());
     Node* global = Parameter(Type::GlobalObject());
@@ -84,7 +86,7 @@ class JSTypeFeedbackTest : public TypedGraphTest {
         isolate()->factory()->NewStringFromAsciiChecked(string));
     const Operator* op = javascript()->LoadNamed(name, feedback);
     Node* load = graph()->NewNode(op, global, context);
-    if (FLAG_turbo_deoptimization) {
+    if (mode == JSTypeFeedbackSpecializer::kDeoptimizationEnabled) {
       for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(op);
            i++) {
         load->AppendInput(zone(), EmptyFrameState());
@@ -103,180 +105,240 @@ class JSTypeFeedbackTest : public TypedGraphTest {
   CompilationDependencies dependencies_;
 };
 
-#define WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION        \
-  for (int i = FLAG_turbo_deoptimization = 0; i < 2; \
-       FLAG_turbo_deoptimization = ++i)
 
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmi) {
+  const int kValue = 111;
+  const char* kName = "banana";
+  SetGlobalProperty(kName, kValue);
 
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_smi) {
-  const int const_value = 111;
-  const char* property_name = "banana";
-  SetGlobalProperty(property_name, const_value);
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
 
-  WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
-    Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
-                                          graph()->start());
-    graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  EXPECT_FALSE(r.Changed());
+  EXPECT_TRUE(dependencies()->IsEmpty());
+}
 
-    Reduction r = Reduce(ret->InputAt(0));
 
-    if (FLAG_turbo_deoptimization) {
-      // Check LoadNamed(global) => HeapConstant[const_value]
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(), IsNumberConstant(const_value));
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstSmiWithDeoptimization) {
+  const int kValue = 111;
+  const char* kName = "banana";
+  SetGlobalProperty(kName, kValue);
 
-      EXPECT_THAT(ret, IsReturn(IsNumberConstant(const_value), graph()->start(),
-                                graph()->start()));
-      EXPECT_THAT(graph()->end(), IsEnd(ret));
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
 
-      EXPECT_FALSE(dependencies()->IsEmpty());
-      dependencies()->Rollback();
-    } else {
-      ASSERT_FALSE(r.Changed());
-      EXPECT_TRUE(dependencies()->IsEmpty());
-    }
-  }
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+  // Check LoadNamed(global) => HeapConstant[kValue]
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberConstant(kValue));
+
+  EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(),
+                            graph()->start()));
+  EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+  EXPECT_FALSE(dependencies()->IsEmpty());
+  dependencies()->Rollback();
 }
 
 
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_derble) {
-  const double const_value = -11.25;
-  const char* property_name = "kiwi";
-  SetGlobalProperty(property_name, const_value);
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumber) {
+  const double kValue = -11.25;
+  const char* kName = "kiwi";
+  SetGlobalProperty(kName, kValue);
 
-  WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
-    Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
-                                          graph()->start());
-    graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
 
-    Reduction r = Reduce(ret->InputAt(0));
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
 
-    if (FLAG_turbo_deoptimization) {
-      // Check LoadNamed(global) => HeapConstant[const_value]
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(), IsNumberConstant(const_value));
+  EXPECT_FALSE(r.Changed());
+  EXPECT_TRUE(dependencies()->IsEmpty());
+}
 
-      EXPECT_THAT(ret, IsReturn(IsNumberConstant(const_value), graph()->start(),
-                                graph()->start()));
-      EXPECT_THAT(graph()->end(), IsEnd(ret));
 
-      EXPECT_FALSE(dependencies()->IsEmpty());
-    } else {
-      ASSERT_FALSE(r.Changed());
-      EXPECT_TRUE(dependencies()->IsEmpty());
-    }
-  }
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstNumberWithDeoptimization) {
+  const double kValue = -11.25;
+  const char* kName = "kiwi";
+  SetGlobalProperty(kName, kValue);
+
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+  // Check LoadNamed(global) => HeapConstant[kValue]
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsNumberConstant(kValue));
+
+  EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), graph()->start(),
+                            graph()->start()));
+  EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+  EXPECT_FALSE(dependencies()->IsEmpty());
 }
 
 
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConst_string) {
-  Unique<HeapObject> const_value = Unique<HeapObject>::CreateImmovable(
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstString) {
+  Unique<HeapObject> kValue = Unique<HeapObject>::CreateImmovable(
       isolate()->factory()->undefined_string());
-  const char* property_name = "mango";
-  SetGlobalProperty(property_name, const_value.handle());
-
-  WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
-    Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
-                                          graph()->start());
-    graph()->SetEnd(graph()->NewNode(common()->End(), ret));
-
-    Reduction r = Reduce(ret->InputAt(0));
-
-    if (FLAG_turbo_deoptimization) {
-      // Check LoadNamed(global) => HeapConstant[const_value]
-      ASSERT_TRUE(r.Changed());
-      EXPECT_THAT(r.replacement(), IsHeapConstant(const_value));
-
-      EXPECT_THAT(ret, IsReturn(IsHeapConstant(const_value), graph()->start(),
-                                graph()->start()));
-      EXPECT_THAT(graph()->end(), IsEnd(ret));
-
-      EXPECT_FALSE(dependencies()->IsEmpty());
-      dependencies()->Rollback();
-    } else {
-      ASSERT_FALSE(r.Changed());
-      EXPECT_TRUE(dependencies()->IsEmpty());
-    }
-  }
+  const char* kName = "mango";
+  SetGlobalProperty(kName, kValue.handle());
+
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  ASSERT_FALSE(r.Changed());
+  EXPECT_TRUE(dependencies()->IsEmpty());
 }
 
 
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCell_smi) {
-  const char* property_name = "melon";
-  SetGlobalProperty(property_name, 123);
-  SetGlobalProperty(property_name, 124);
-
-  WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
-    Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
-                                          graph()->start());
-    graph()->SetEnd(graph()->NewNode(common()->End(), ret));
-
-    Reduction r = Reduce(ret->InputAt(0));
-
-    if (FLAG_turbo_deoptimization) {
-      // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
-      ASSERT_TRUE(r.Changed());
-      FieldAccess access = AccessBuilder::ForPropertyCellValue();
-      Capture<Node*> cell_capture;
-      Matcher<Node*> load_field_match = IsLoadField(
-          access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
-      EXPECT_THAT(r.replacement(), load_field_match);
-
-      HeapObjectMatcher<PropertyCell> cell(cell_capture.value());
-      EXPECT_TRUE(cell.HasValue());
-      EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
-
-      EXPECT_THAT(
-          ret, IsReturn(load_field_match, load_field_match, graph()->start()));
-      EXPECT_THAT(graph()->end(), IsEnd(ret));
-
-      EXPECT_FALSE(dependencies()->IsEmpty());
-      dependencies()->Rollback();
-    } else {
-      ASSERT_FALSE(r.Changed());
-      EXPECT_TRUE(dependencies()->IsEmpty());
-    }
-  }
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalConstStringWithDeoptimization) {
+  Unique<HeapObject> kValue = Unique<HeapObject>::CreateImmovable(
+      isolate()->factory()->undefined_string());
+  const char* kName = "mango";
+  SetGlobalProperty(kName, kValue.handle());
+
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+  // Check LoadNamed(global) => HeapConstant[kValue]
+  ASSERT_TRUE(r.Changed());
+  EXPECT_THAT(r.replacement(), IsHeapConstant(kValue));
+
+  EXPECT_THAT(ret, IsReturn(IsHeapConstant(kValue), graph()->start(),
+                            graph()->start()));
+  EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+  EXPECT_FALSE(dependencies()->IsEmpty());
+  dependencies()->Rollback();
 }
 
 
-TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCell_string) {
-  const char* property_name = "pineapple";
-  SetGlobalProperty(property_name, isolate()->factory()->undefined_string());
-  SetGlobalProperty(property_name, isolate()->factory()->undefined_value());
-
-  WITH_AND_WITHOUT_TURBO_DEOPTIMIZATION {
-    Node* ret = ReturnLoadNamedFromGlobal(property_name, graph()->start(),
-                                          graph()->start());
-    graph()->SetEnd(graph()->NewNode(common()->End(), ret));
-
-    Reduction r = Reduce(ret->InputAt(0));
-
-    if (FLAG_turbo_deoptimization) {
-      // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
-      ASSERT_TRUE(r.Changed());
-      FieldAccess access = AccessBuilder::ForPropertyCellValue();
-      Capture<Node*> cell_capture;
-      Matcher<Node*> load_field_match = IsLoadField(
-          access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
-      EXPECT_THAT(r.replacement(), load_field_match);
-
-      HeapObjectMatcher<PropertyCell> cell(cell_capture.value());
-      EXPECT_TRUE(cell.HasValue());
-      EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
-
-      EXPECT_THAT(
-          ret, IsReturn(load_field_match, load_field_match, graph()->start()));
-      EXPECT_THAT(graph()->end(), IsEnd(ret));
-
-      EXPECT_FALSE(dependencies()->IsEmpty());
-      dependencies()->Rollback();
-    } else {
-      ASSERT_FALSE(r.Changed());
-      EXPECT_TRUE(dependencies()->IsEmpty());
-    }
-  }
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmi) {
+  const char* kName = "melon";
+  SetGlobalProperty(kName, 123);
+  SetGlobalProperty(kName, 124);
+
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  ASSERT_FALSE(r.Changed());
+  EXPECT_TRUE(dependencies()->IsEmpty());
 }
+
+
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellSmiWithDeoptimization) {
+  const char* kName = "melon";
+  SetGlobalProperty(kName, 123);
+  SetGlobalProperty(kName, 124);
+
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+  // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
+  ASSERT_TRUE(r.Changed());
+  FieldAccess access = AccessBuilder::ForPropertyCellValue();
+  Capture<Node*> cell_capture;
+  Matcher<Node*> load_field_match = IsLoadField(
+      access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
+  EXPECT_THAT(r.replacement(), load_field_match);
+
+  HeapObjectMatcher<PropertyCell> cell(cell_capture.value());
+  EXPECT_TRUE(cell.HasValue());
+  EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
+
+  EXPECT_THAT(ret,
+              IsReturn(load_field_match, load_field_match, graph()->start()));
+  EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+  EXPECT_FALSE(dependencies()->IsEmpty());
+  dependencies()->Rollback();
 }
+
+
+TEST_F(JSTypeFeedbackTest, JSLoadNamedGlobalPropertyCellString) {
+  const char* kName = "pineapple";
+  SetGlobalProperty(kName, isolate()->factory()->undefined_string());
+  SetGlobalProperty(kName, isolate()->factory()->undefined_value());
+
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationDisabled);
+  ASSERT_FALSE(r.Changed());
+  EXPECT_TRUE(dependencies()->IsEmpty());
 }
+
+
+TEST_F(JSTypeFeedbackTest,
+       JSLoadNamedGlobalPropertyCellStringWithDeoptimization) {
+  const char* kName = "pineapple";
+  SetGlobalProperty(kName, isolate()->factory()->undefined_string());
+  SetGlobalProperty(kName, isolate()->factory()->undefined_value());
+
+  Node* ret = ReturnLoadNamedFromGlobal(
+      kName, graph()->start(), graph()->start(),
+      JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+  graph()->SetEnd(graph()->NewNode(common()->End(), ret));
+
+  Reduction r = Reduce(ret->InputAt(0),
+                       JSTypeFeedbackSpecializer::kDeoptimizationEnabled);
+
+  // Check LoadNamed(global) => LoadField[PropertyCell::value](cell)
+  ASSERT_TRUE(r.Changed());
+  FieldAccess access = AccessBuilder::ForPropertyCellValue();
+  Capture<Node*> cell_capture;
+  Matcher<Node*> load_field_match = IsLoadField(
+      access, CaptureEq(&cell_capture), graph()->start(), graph()->start());
+  EXPECT_THAT(r.replacement(), load_field_match);
+
+  HeapObjectMatcher<PropertyCell> cell(cell_capture.value());
+  EXPECT_TRUE(cell.HasValue());
+  EXPECT_TRUE(cell.Value().handle()->IsPropertyCell());
+
+  EXPECT_THAT(ret,
+              IsReturn(load_field_match, load_field_match, graph()->start()));
+  EXPECT_THAT(graph()->end(), IsEnd(ret));
+
+  EXPECT_FALSE(dependencies()->IsEmpty());
+  dependencies()->Rollback();
 }
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8