Revision: 14565
Author:   [email protected]
Date:     Tue May  7 03:32:23 2013
Log: Fix polymorphic to monomorphic load to take representation into account.

Review URL: https://chromiumcodereview.appspot.com/14966005
http://code.google.com/p/v8/source/detail?r=14565

Modified:
 /branches/bleeding_edge/src/code-stubs-hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h
 /branches/bleeding_edge/src/property-details.h
 /branches/bleeding_edge/test/mjsunit/track-fields.js

=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Fri May 3 05:21:16 2013 +++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue May 7 03:32:23 2013
@@ -413,7 +413,7 @@
 template<>
 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
   Representation representation = casted_stub()->representation();
-  HInstruction* load = AddInstruction(new(zone()) HLoadNamedField(
+  HInstruction* load = AddInstruction(DoBuildLoadNamedField(
       GetParameter(0), casted_stub()->is_inobject(),
       representation, casted_stub()->offset()));
   return load;
@@ -428,7 +428,7 @@
 template<>
 HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
   Representation representation = casted_stub()->representation();
-  HInstruction* load = AddInstruction(new(zone()) HLoadNamedField(
+  HInstruction* load = AddInstruction(DoBuildLoadNamedField(
       GetParameter(0), casted_stub()->is_inobject(),
       representation, casted_stub()->offset()));
   return load;
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Fri May  3 06:39:11 2013
+++ /branches/bleeding_edge/src/hydrogen.cc     Tue May  7 03:32:23 2013
@@ -7131,22 +7131,31 @@
     HValue* object,
     SmallMapList* types,
     Handle<String> name) {
-  int count = 0;
-  int previous_field_offset = 0;
-  bool previous_field_is_in_object = false;
-  bool is_monomorphic_field = true;

   if (HandlePolymorphicArrayLengthLoad(expr, object, types, name))
     return;

-  Handle<Map> map;
-  LookupResult lookup(isolate());
- for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
-    map = types->at(i);
-    if (ComputeLoadStoreField(map, name, &lookup, false)) {
+  AddInstruction(new(zone()) HCheckNonSmi(object));
+
+ // Use monomorphic load if property lookup results in the same field index + // for all maps. Requires special map check on the set of all handled maps.
+  HInstruction* instr = NULL;
+  if (types->length() > 0 && types->length() <= kMaxLoadPolymorphism) {
+    LookupResult lookup(isolate());
+    int previous_field_offset = 0;
+    bool previous_field_is_in_object = false;
+    Representation representation = Representation::None();
+    int count;
+    for (count = 0; count < types->length(); ++count) {
+      Handle<Map> map = types->at(count);
+      if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
+
       int index = ComputeLoadStoreFieldIndex(map, &lookup);
+      Representation new_representation =
+          ComputeLoadStoreRepresentation(map, &lookup);
       bool is_in_object = index < 0;
       int offset = index * kPointerSize;
+
       if (index < 0) {
         // Negative property indices are in-object properties, indexed
         // from the end of the fixed part of the object.
@@ -7154,31 +7163,33 @@
       } else {
         offset += FixedArray::kHeaderSize;
       }
+
       if (count == 0) {
         previous_field_offset = offset;
         previous_field_is_in_object = is_in_object;
-      } else if (is_monomorphic_field) {
-        is_monomorphic_field = (offset == previous_field_offset) &&
- (is_in_object == previous_field_is_in_object);
+        representation = new_representation;
+      } else if (offset != previous_field_offset ||
+                 is_in_object != previous_field_is_in_object ||
+                 (FLAG_track_fields &&
+ !representation.IsCompatibleForLoad(new_representation))) {
+        break;
       }
-      ++count;
+
+      representation = representation.generalize(new_representation);
+    }
+
+    if (count == types->length()) {
+      AddInstruction(HCheckMaps::New(object, types, zone()));
+      instr = DoBuildLoadNamedField(
+          object, previous_field_is_in_object,
+          representation, previous_field_offset);
     }
   }

- // Use monomorphic load if property lookup results in the same field index - // for all maps. Requires special map check on the set of all handled maps.
-  AddInstruction(new(zone()) HCheckNonSmi(object));
-  HInstruction* instr;
-  if (count == types->length() && is_monomorphic_field) {
-    AddInstruction(HCheckMaps::New(object, types, zone()));
-    instr = BuildLoadNamedField(object, map, &lookup);
-  } else {
+  if (instr == NULL) {
     HValue* context = environment()->LookupContext();
-    instr = new(zone()) HLoadNamedFieldPolymorphic(context,
-                                                   object,
-                                                   types,
-                                                   name,
-                                                   zone());
+    instr = new(zone()) HLoadNamedFieldPolymorphic(
+        context, object, types, name, zone());
   }

   instr->set_position(expr->position());
@@ -7735,18 +7746,25 @@
     HValue* object,
     Handle<Map> map,
     LookupResult* lookup) {
-  Representation representation = lookup->representation();
   int index = lookup->GetLocalFieldIndexFromMap(*map);
-  if (index < 0) {
-    // Negative property indices are in-object properties, indexed
-    // from the end of the fixed part of the object.
-    int offset = (index * kPointerSize) + map->instance_size();
- return new(zone()) HLoadNamedField(object, true, representation, offset);
-  } else {
-    // Non-negative property indices are in the properties array.
-    int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
- return new(zone()) HLoadNamedField(object, false, representation, offset);
-  }
+ // Negative property indices are in-object properties, indexed from the end of
+  // the fixed part of the object. Non-negative property indices are in the
+  // properties array.
+  int inobject = index < 0;
+  Representation representation = lookup->representation();
+  int offset = inobject
+      ? index * kPointerSize + map->instance_size()
+      : index * kPointerSize + FixedArray::kHeaderSize;
+  return DoBuildLoadNamedField(object, inobject, representation, offset);
+}
+
+
+HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField(
+    HValue* object,
+    bool inobject,
+    Representation representation,
+    int offset) {
+ return new(zone()) HLoadNamedField(object, inobject, representation, offset);
 }


=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Fri May  3 05:21:16 2013
+++ /branches/bleeding_edge/src/hydrogen.h      Tue May  7 03:32:23 2013
@@ -982,6 +982,11 @@
   HValue* BuildCheckMap(HValue* obj, Handle<Map> map);

   // Building common constructs
+  HLoadNamedField* DoBuildLoadNamedField(HValue* object,
+                                         bool inobject,
+                                         Representation representation,
+                                         int offset);
+
   HInstruction* BuildExternalArrayElementAccess(
       HValue* external_elements,
       HValue* checked_key,
=======================================
--- /branches/bleeding_edge/src/property-details.h      Thu May  2 08:41:02 2013
+++ /branches/bleeding_edge/src/property-details.h      Tue May  7 03:32:23 2013
@@ -102,6 +102,11 @@
   bool Equals(const Representation& other) const {
     return kind_ == other.kind_;
   }
+
+  bool IsCompatibleForLoad(const Representation& other) const {
+    return (IsDouble() && other.IsDouble()) ||
+        (!IsDouble() && !other.IsDouble());
+  }

   bool is_more_general_than(const Representation& other) const {
     ASSERT(kind_ != kExternal);
=======================================
--- /branches/bleeding_edge/test/mjsunit/track-fields.js Fri Apr 26 08:30:41 2013 +++ /branches/bleeding_edge/test/mjsunit/track-fields.js Tue May 7 03:32:23 2013
@@ -99,3 +99,22 @@
 // Smi, double, object.
 o6.c = {};
 assertTrue(%HaveSameMap(o6, o7));
+
+function poly_load(o, b) {
+  var v = o.field;
+  if (b) {
+    return v + 10;
+  }
+  return o;
+}
+
+var of1 = {a:0};
+of1.field = {};
+var of2 = {b:0};
+of2.field = 10;
+
+poly_load(of1, false);
+poly_load(of1, false);
+poly_load(of2, true);
+%OptimizeFunctionOnNextCall(poly_load);
+assertEquals("[object Object]10", poly_load(of1, true));

--
--
v8-dev mailing list
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to