Reviewers: Hannes Payer,

Message:
PTAL

Description:
Avoid dynamic initial map check when inlining call-new.

This improves check elimination and removes a load plus
a map check for every inlined call-new.

Please review this at https://codereview.chromium.org/293223002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+26, -21 lines):
  M src/hydrogen.cc
  M src/objects.h
  M src/objects.cc


Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 5d78a4a2e33158d23e0a3d560251b1929ef40f67..5ae72194ae82449f0b36068792cb665df04f37bd 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -8610,25 +8610,16 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
       }
     }

-    HAllocate* receiver =
-        BuildAllocate(size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE,
-                      allocation_mode);
+    HAllocate* receiver = BuildAllocate(
+        size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
     receiver->set_known_initial_map(initial_map);

-    // Load the initial map from the constructor.
-    HValue* constructor_value = Add<HConstant>(constructor);
-    HValue* initial_map_value =
-      Add<HLoadNamedField>(constructor_value, static_cast<HValue*>(NULL),
-                           HObjectAccess::ForMapAndOffset(
-                               handle(constructor->map()),
-                               JSFunction::kPrototypeOrInitialMapOffset));
-
     // Initialize map and fields of the newly allocated object.
     { NoObservableSideEffectsScope no_effects(this);
       ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
       Add<HStoreNamedField>(receiver,
HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
-          initial_map_value);
+          Add<HConstant>(initial_map));
HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
       Add<HStoreNamedField>(receiver,
           HObjectAccess::ForMapAndOffset(initial_map,
@@ -8655,21 +8646,25 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
     ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
     environment()->SetExpressionStackAt(receiver_index, receiver);

-    if (TryInlineConstruct(expr, receiver)) return;
+    if (TryInlineConstruct(expr, receiver)) {
+ // Inlining worked, add a dependency on the initial map to make sure that + // this code is deoptimized whenever the initial map of the constructor
+      // changes.
+      Map::AddDependentCompilationInfo(
+          initial_map, DependentCode::kInitialMapChangedGroup, top_info());
+      return;
+    }

     // TODO(mstarzinger): For now we remove the previous HAllocate and all
     // corresponding instructions and instead add HPushArgument for the
// arguments in case inlining failed. What we actually should do is for // inlining to try to build a subgraph without mutating the parent graph.
     HInstruction* instr = current_block()->last();
-    while (instr != initial_map_value) {
+    do {
       HInstruction* prev_instr = instr->previous();
       instr->DeleteAndReplaceWith(NULL);
       instr = prev_instr;
-    }
-    initial_map_value->DeleteAndReplaceWith(NULL);
-    receiver->DeleteAndReplaceWith(NULL);
-    check->DeleteAndReplaceWith(NULL);
+    } while (instr != check);
     environment()->SetExpressionStackAt(receiver_index, function);
     HInstruction* call =
       PreProcessCall(New<HCallNew>(function, argument_count));
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 352e5d6508d5465728352992d9a974e7bafeea16..744af1845a7b6b25bba80abcabff67b8d69f527f 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -10210,6 +10210,8 @@ Handle<Object> CacheInitialJSArrayMaps(

 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
                                       Handle<Object> value) {
+  Isolate* isolate = function->GetIsolate();
+
   ASSERT(value->IsJSReceiver());

// First some logic for the map of the prototype to make sure it is in fast @@ -10228,7 +10230,8 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
     if (function->shared()->IsInobjectSlackTrackingInProgress()) {
       function->shared()->CompleteInobjectSlackTracking();
     }
-    Handle<Map> new_map = Map::Copy(handle(function->initial_map()));
+    Handle<Map> initial_map(function->initial_map(), isolate);
+    Handle<Map> new_map = Map::Copy(initial_map);
     new_map->set_prototype(*value);

     // If the function is used as the global Array function, cache the
@@ -10237,17 +10240,21 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function, Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX);
     if (array_function->IsJSFunction() &&
         *function == JSFunction::cast(array_function)) {
-      CacheInitialJSArrayMaps(handle(native_context), new_map);
+      CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
     }

     function->set_initial_map(*new_map);
+
+    // Deoptimize all code that embeds the previous initial map.
+    initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
+        isolate, DependentCode::kInitialMapChangedGroup);
   } else {
     // Put the value in the initial map field until an initial map is
     // needed.  At that point, a new initial map is created and the
     // prototype is put into the initial map where it belongs.
     function->set_prototype_or_initial_map(*value);
   }
-  function->GetHeap()->ClearInstanceofCache();
+  isolate->heap()->ClearInstanceofCache();
 }


Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 47fea39e4d9e7566646541c0cd8869ef743b3251..f472757311ab4ef6c819ddb749b331d3fddbfef7 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5884,6 +5884,9 @@ class DependentCode: public FixedArray {
// Group of code that omit run-time type checks for the field(s) introduced
     // by this map.
     kFieldTypeGroup,
+    // Group of code that omit run-time type checks for initial maps of
+    // constructors.
+    kInitialMapChangedGroup,
// Group of code that depends on tenuring information in AllocationSites
     // not being changed.
     kAllocationSiteTenuringChangedGroup,


--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to