From: mstarzinger@chromium.org Date: Tue, 22 Jan 2013 12:03:35 +0000 (+0000) Subject: Allow loading constant function from proto chain. X-Git-Tag: upstream/4.7.83~15237 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f8d5260af7009ca2f9595fc0442d266b1a935f18;p=platform%2Fupstream%2Fv8.git 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. R=svenpanne@chromium.org TEST=mjsunit/compiler/proto-chain-constant Review URL: https://codereview.chromium.org/12052008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13463 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/hydrogen.cc b/src/hydrogen.cc index e19947b..335a40c 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -6290,7 +6290,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 prototype(JSObject::cast(map->prototype())); @@ -6302,6 +6302,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 prototype(JSObject::cast(map->prototype())); + Handle holder(lookup.holder()); + Handle holder_map(holder->map()); + AddCheckMapsWithTransitions(object, map); + AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); + Handle function(lookup.GetConstantFunctionFromMap(*holder_map)); + return new(zone()) HConstant(function, Representation::Tagged()); + } + // No luck, do a generic load. return BuildLoadNamedGeneric(object, name, expr); } diff --git a/test/mjsunit/compiler/proto-chain-constant.js b/test/mjsunit/compiler/proto-chain-constant.js new file mode 100644 index 0000000..0d9e3b0 --- /dev/null +++ b/test/mjsunit/compiler/proto-chain-constant.js @@ -0,0 +1,55 @@ +// 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +// Test loading a constant function on the prototype chain. + +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)()); +%OptimizeFunctionOnNextCall(get4); +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)());