Reviewers: Jakob,

Description:
Allow monomorphic loads when static type is known.

This allows Crankshaft to generate monomorphic loads when the receiver
type is statically known even though the load site has polymorphic type
feedback. This applies to inlined constructor calls and literals.

[email protected]
TEST=mjsunit/compiler/property-static


Please review this at https://chromiumcodereview.appspot.com/12051058/

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

Affected files:
  M src/hydrogen-instructions.h
  M src/hydrogen-instructions.cc
  M src/hydrogen.cc
  A + test/mjsunit/compiler/property-static.js


Index: src/hydrogen-instructions.cc
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 9c808c78f2e74e5f94649a5e0b9b369d82b38607..4a6709bf445459e576afe2c011137cdfb5ed9364 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -571,6 +571,11 @@ void HValue::PrintNameTo(StringStream* stream) {
 }


+bool HValue::HasMonomorphicJSObjectType() {
+  return !GetMonomorphicJSObjectMap().is_null();
+}
+
+
 bool HValue::UpdateInferredType() {
   HType type = CalculateInferredType();
   bool result = (!type.Equals(type_));
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 367d2b32fb037369b1ae58db8d41e22c8cee2b66..aa513e707b235c8a20a63a55acacfa78b6189e82 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -770,6 +770,14 @@ class HValue: public ZoneObject {

   const char* Mnemonic() const;

+  // Type information helpers.
+  bool HasMonomorphicJSObjectType();
+
+  // TODO(mstarzinger): For now instructions can override this function to
+  // specify statically known types, once HType can convey more information
+  // it should be based on the HType.
+  virtual Handle<Map> GetMonomorphicJSObjectMap() { return Handle<Map>(); }
+
   // Updated the inferred type of this instruction and returns true if
   // it has changed.
   bool UpdateInferredType();
@@ -5019,6 +5027,10 @@ class HAllocateObject: public HTemplateInstruction<1> {
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
+  virtual Handle<Map> GetMonomorphicJSObjectMap() {
+    ASSERT(constructor()->has_initial_map());
+    return Handle<Map>(constructor()->initial_map());
+  }
   virtual HType CalculateInferredType();

   DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
@@ -5086,6 +5098,9 @@ class HFastLiteral: public HMaterializedLiteral<1> {
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
   }
+  virtual Handle<Map> GetMonomorphicJSObjectMap() {
+    return Handle<Map>(boilerplate()->map());
+  }
   virtual HType CalculateInferredType();

   DECLARE_CONCRETE_INSTRUCTION(FastLiteral)
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 8de8e52c6b069d09941b3606cc9eb172fd611d94..019f39a20f96050f55cbab1d67390afbcf1b8707 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -6796,12 +6796,16 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
   } else if (expr->key()->IsPropertyName()) {
     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
     SmallMapList* types = expr->GetReceiverTypes();
+    HValue* object = Top();

-    bool monomorphic = expr->IsMonomorphic();
     Handle<Map> map;
+    bool monomorphic = false;
     if (expr->IsMonomorphic()) {
       map = types->first();
-      if (map->is_dictionary_map()) monomorphic = false;
+      monomorphic = !map->is_dictionary_map();
+    } else if (object->HasMonomorphicJSObjectType()) {
+      map = object->GetMonomorphicJSObjectMap();
+      monomorphic = !map->is_dictionary_map();
     }
     if (monomorphic) {
       Handle<JSFunction> getter;
Index: test/mjsunit/compiler/property-static.js
diff --git a/test/mjsunit/regress/regress-171641.js b/test/mjsunit/compiler/property-static.js
similarity index 59%
copy from test/mjsunit/regress/regress-171641.js
copy to test/mjsunit/compiler/property-static.js
index 8db6781821325f8f6253eb2df4abb2b362b001c0..07021340cd7aa94440638f925eeed921ee78c9c7 100644
--- a/test/mjsunit/regress/regress-171641.js
+++ b/test/mjsunit/compiler/property-static.js
@@ -27,14 +27,43 @@

 // Flags: --allow-natives-syntax

-function foo(k, p) {
-  for (var i = 0; i < 1; i++) {
-    p = Math.min(p, i);
+// Test usage of static type information for loads that would otherwise
+// turn into polymorphic or generic loads.
+
+// Prepare a highly polymorphic load to be used by all tests.
+Object.prototype.load = function() { return this.property; };
+Object.prototype.load.call({ A:0, property:10 });
+Object.prototype.load.call({ A:0, B:0, property:11 });
+Object.prototype.load.call({ A:0, B:0, C:0, property:12 });
+Object.prototype.load.call({ A:0, B:0, C:0, D:0, property:13 });
+Object.prototype.load.call({ A:0, B:0, C:0, D:0, E:0, property:14 });
+Object.prototype.load.call({ A:0, B:0, C:0, D:0, E:0, F:0, property:15 });
+
+// Test for object literals.
+(function() {
+  function f(x) {
+    var object = { property:x };
+    return object.load();
+  }
+
+  assertSame(1, f(1));
+  assertSame(2, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertSame(3, f(3));
+})();
+
+// Test for inlined constructors.
+(function() {
+  function c(x) {
+    this.property = x;
+  }
+  function f(x) {
+    var object = new c(x);
+    return object.load();
   }
-  m = Math.floor((k | 0) / p);
-}

-foo(0, 1);
-foo(0, 1);
-%OptimizeFunctionOnNextCall(foo);
-foo(0, 1);
+  assertSame(1, f(1));
+  assertSame(2, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertSame(3, f(3));
+})();


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev


Reply via email to