From 3d7c45371e26a3ca7b688ed73892cba44cb23c0d Mon Sep 17 00:00:00 2001 From: bmeurer Date: Mon, 21 Sep 2015 21:07:53 -0700 Subject: [PATCH] [crankshaft] Handle @@toStringTag accessor correctly for BuildCompareInstruction. If @@toStringTag is an accessor property, we cannot assume that the result of calling Object.prototype.toString() for objects with the same map. R=adamk@chromium.org BUG=chromium:534200 LOG=n Review URL: https://codereview.chromium.org/1360723002 Cr-Commit-Position: refs/heads/master@{#30856} --- src/hydrogen.cc | 7 ++- .../compare-known-objects-tostringtag.js | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 test/mjsunit/compare-known-objects-tostringtag.js diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 2796754fc..949562f3a 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -11600,7 +11600,12 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( this, LOAD, map, isolate()->factory()->to_primitive_symbol()); PropertyAccessInfo to_string(this, LOAD, map, isolate()->factory()->toString_string()); + PropertyAccessInfo to_string_tag( + this, LOAD, map, isolate()->factory()->to_string_tag_symbol()); if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() && + to_string_tag.CanAccessMonomorphic() && + (!to_string_tag.IsFound() || to_string_tag.IsData() || + to_string_tag.IsDataConstant()) && value_of.CanAccessMonomorphic() && value_of.IsDataConstant() && value_of.constant().is_identical_to(isolate()->object_value_of()) && to_string.CanAccessMonomorphic() && to_string.IsDataConstant() && @@ -11608,7 +11613,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( isolate()->object_to_string())) { // We depend on the prototype chain to stay the same, because we // also need to deoptimize when someone installs @@toPrimitive - // somewhere in the prototype chain. + // or @@toStringTag somewhere in the prototype chain. BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())), Handle::null()); AddCheckMap(left, map); diff --git a/test/mjsunit/compare-known-objects-tostringtag.js b/test/mjsunit/compare-known-objects-tostringtag.js new file mode 100644 index 000000000..81544ca69 --- /dev/null +++ b/test/mjsunit/compare-known-objects-tostringtag.js @@ -0,0 +1,57 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --harmony-tostring + +function le(a, b) { + return a <= b; +} + +function lt(a, b) { + return a < b; +} + +function ge(a, b) { + return a >= b; +} + +function gt(a, b) { + return a > b; +} + +function test(a, b) { + // Check CompareIC for less than or equal of known objects. + assertThrows(function() {le(a, a)}); + assertThrows(function() {le(a, b)}); + assertThrows(function() {le(b, a)}); + // Check CompareIC for less than of known objects. + assertThrows(function() {lt(a, a)}); + assertThrows(function() {lt(a, b)}); + assertThrows(function() {lt(b, a)}); + // Check CompareIC for greater than or equal of known objects. + assertThrows(function() {ge(a, a)}); + assertThrows(function() {ge(a, b)}); + assertThrows(function() {ge(b, a)}); + // Check CompareIC for greater than of known objects. + assertThrows(function() {gt(a, a)}); + assertThrows(function() {gt(a, b)}); + assertThrows(function() {gt(b, a)}); +} + +function O() { } +Object.defineProperty(O.prototype, Symbol.toStringTag, { + get: function() { throw "@@toStringTag called!" } +}); + +var obj1 = new O; +var obj2 = new O; + +assertTrue(%HaveSameMap(obj1, obj2)); +test(obj1, obj2); +test(obj1, obj2); +%OptimizeFunctionOnNextCall(le); +%OptimizeFunctionOnNextCall(lt); +%OptimizeFunctionOnNextCall(ge); +%OptimizeFunctionOnNextCall(gt); +test(obj1, obj2); -- 2.34.1