Reviewers: Sven Panne,

Description:
Allow loading constant function from proto chain.

This enables Crankshaft to use HConstant for loading constant functions
on the prototype chain when building a monomorphic load. This pattern
appears in several JavaScript frameworks.

[email protected]
TEST=mjsunit/compiler/proto-chain-constant


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

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

Affected files:
  M src/hydrogen.cc
  A + test/mjsunit/compiler/proto-chain-constant.js


Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 57ba4655e14b9d262a6b9e0e6b62a93fa70a9aba..e19a12e28ab2ed6259a693970f4967f669aabd90 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -6289,7 +6289,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
     return new(zone()) HConstant(function, Representation::Tagged());
   }

-  // Handle a load from a known field somewhere in the protoype chain.
+  // Handle a load from a known field somewhere in the prototype chain.
   LookupInPrototypes(map, name, &lookup);
   if (lookup.IsField()) {
     Handle<JSObject> prototype(JSObject::cast(map->prototype()));
@@ -6301,6 +6301,17 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
     return BuildLoadNamedField(holder_value, holder_map, &lookup);
   }

+  // Handle a load of a constant function somewhere in the prototype chain.
+  if (lookup.IsConstantFunction()) {
+    Handle<JSObject> prototype(JSObject::cast(map->prototype()));
+    Handle<JSObject> holder(lookup.holder());
+    Handle<Map> holder_map(holder->map());
+    AddCheckMapsWithTransitions(object, map);
+    AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder));
+ Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map));
+    return new(zone()) HConstant(function, Representation::Tagged());
+  }
+
   // No luck, do a generic load.
   return BuildLoadNamedGeneric(object, name, expr);
 }
Index: test/mjsunit/compiler/proto-chain-constant.js
diff --git a/test/mjsunit/compiler/proto-chain-load.js b/test/mjsunit/compiler/proto-chain-constant.js
similarity index 63%
copy from test/mjsunit/compiler/proto-chain-load.js
copy to test/mjsunit/compiler/proto-chain-constant.js
index 60c6431d2b180f858abecef650b27ddb6a23f4e4..0d9e3b0e1e10b46737904db6c9b53c702ed9fa25 100644
--- a/test/mjsunit/compiler/proto-chain-load.js
+++ b/test/mjsunit/compiler/proto-chain-constant.js
@@ -1,4 +1,4 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
+// Copyright 2013 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -27,18 +27,29 @@

 // Flags: --allow-natives-syntax

-// Test HLoadNamedField on the proto chain.
+// Test loading a constant function on the prototype chain.

-var obj4 = Object.create(null, { f4: {value: 4} });
-var obj3 = Object.create(obj4, { f3: {value: 3} });
-var obj2 = Object.create(obj3, { f2: {value: 2} });
-var obj1 = Object.create(obj2, { f1: {value: 1} });
-var obj0 = Object.create(obj1, { f0: {value: 0} });
+var c = Object.create;
+var obj4 = c(null, { f4: { value: function() { return 4; }, writable: true }}); +var obj3 = c(obj4, { f3: { value: function() { return 3; }, writable: true }}); +var obj2 = c(obj3, { f2: { value: function() { return 2; }, writable: true }}); +var obj1 = c(obj2, { f1: { value: function() { return 1; }, writable: true }}); +var obj0 = c(obj1, { f0: { value: function() { return 0; }, writable: true }});

 function get4(obj) { return obj.f4; }

-assertEquals(4, get4(obj0));
-assertEquals(4, get4(obj0));
+assertEquals(4, get4(obj0)());
+assertEquals(4, get4(obj0)());
 %OptimizeFunctionOnNextCall(get4);
-assertEquals(4, get4(obj0));
-assertEquals(4, get4(obj0));
+assertEquals(4, get4(obj0)());
+obj4.f4 = function() { return 5; };
+assertEquals(5, get4(obj0)());
+
+function get3(obj) { return obj.f3; }
+
+assertEquals(3, get3(obj0)());
+assertEquals(3, get3(obj0)());
+%OptimizeFunctionOnNextCall(get3);
+assertEquals(3, get3(obj0)());
+obj2.f3 = function() { return 6; };
+assertEquals(6, get3(obj0)());


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

Reply via email to