super-ic-opt-no-turboprop.js 5.22 KB
Newer Older
1 2 3 4 5
// Copyright 2020 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 --super-ic --opt
6
// Flags: --no-always-opt --no-stress-opt --deopt-every-n-times=0
7 8 9

// This file contains tests which are disabled for TurboProp. TurboProp deopts
// differently than TurboFan, so the assertions about when a function is
10 11
// deoptimized won't hold. In addition, TurboProp doesn't inline, so all
// tests that rely on inlining need to be in this file.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

(function TestPropertyIsConstant() {
  // Test for a case where the property is a constant found in the lookup start
  // object.
  class A {}
  A.prototype.bar = "wrong value: A.prototype.bar";

  class B extends A {};
  B.prototype.bar = "correct value";

  class C extends B {
    foo() { return super.bar; }
  }
  C.prototype.bar = "wrong value: C.prototype.bar";
  %PrepareFunctionForOptimization(C.prototype.foo);

  let o = new C();
  o.bar = "wrong value: o.bar";

  // Fill in the feedback.
  r = o.foo();
  assertEquals("correct value", r);

  %OptimizeFunctionOnNextCall(C.prototype.foo);

  // Test the optimized function.
  r = o.foo();
  assertEquals("correct value", r);

  // Assert that the function was not deoptimized.
  assertOptimized(C.prototype.foo);

  // Change the property value.
  B.prototype.bar = "new value";
  r = o.foo();
  assertEquals("new value", r);

  // Assert that the function was deoptimized (dependency to the constant
  // value).
51 52 53 54 55 56
  // TODO(v8:11457) We don't support inlining JSLoadNamedFromSuper for
  // dictionary mode prototypes, yet. Therefore, if
  // v8_dict_property_const_tracking is enabled, the optimized code only
  // contains a call to the IC handler and doesn't get deopted.
  assertEquals(%IsDictPropertyConstTrackingEnabled(),
               isOptimized(C.prototype.foo));
57
})();
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

(function TestSuperpropertyAccessInlined() {
  class A {}
  A.prototype.bar = "wrong value: A.prototype.bar";

  class B extends A {}
  B.prototype.bar = "correct value";

  class C extends B {}

  let inline_this_is_being_interpreted;
  class D extends C {
    inline_this() {
      inline_this_is_being_interpreted = %IsBeingInterpreted();
      return super.bar;
    }
    foo() { return this.inline_this(); }
  }
  %PrepareFunctionForOptimization(D.prototype.inline_this);
  %PrepareFunctionForOptimization(D.prototype.foo);
  D.prototype.bar = "wrong value: D.prototype.bar";

  const o = new D();

  // Fill in the feedback.
  let r = o.foo();
  assertEquals("correct value", r);

  %OptimizeFunctionOnNextCall(D.prototype.foo);

  // Test the optimized function.
  r = o.foo();
  assertEquals("correct value", r);

  // Assert that the function was not deoptimized.
  assertOptimized(D.prototype.foo);

  // Assert that inline_this really got inlined.
  assertFalse(inline_this_is_being_interpreted);
})();

(function TestMegamorphicInlined() {
  class A {}
  A.prototype.bar = "wrong value: A.prototype.bar";

  class B extends A {}
  B.prototype.bar = "correct value";

  class C extends B {}

  let inline_this_is_being_interpreted;
  class D extends C {
    inline_this() {
      inline_this_is_being_interpreted = %IsBeingInterpreted();
      return super.bar;
    }
    foo() { return this.inline_this(); }
  }
  %PrepareFunctionForOptimization(D.prototype.inline_this);
  %PrepareFunctionForOptimization(D.prototype.foo);
  D.prototype.bar = "wrong value: D.prototype.bar";

  const o = new D();

  // Create objects which will act as the "home object's prototype" later.
  const prototypes = [{"a": 0}, {"b": 0}, {"c": 0}, {"d": 0}, {"e": 0},
  {"f": 0}, {"g": 0}, {"e": 0}];
  for (p of prototypes) {
    p.__proto__ = B.prototype;
  }

  // Fill in the feedback (megamorphic).
  for (p of prototypes) {
    D.prototype.__proto__ = p;
    const r = o.foo();
    assertEquals("correct value", r);
  }

  %OptimizeFunctionOnNextCall(D.prototype.foo);

  // Test the optimized function - don't change the home object's proto any
  // more.
  let r = o.foo();
  assertEquals("correct value", r);

  // Assert that the function was not deoptimized.
  assertOptimized(D.prototype.foo);

  // Assert that inline_this really got inlined.
  assertFalse(inline_this_is_being_interpreted);
})();

(function TestHomeObjectProtoIsGlobalThisGetterPropertyInlined() {
  class A {}

  let inline_this_is_being_interpreted;
  class B extends A {
    inline_this() {
      inline_this_is_being_interpreted = %IsBeingInterpreted();
      return super.bar;
    }
    foo() { return this.inline_this(); }
  }
  B.prototype.__proto__ = globalThis;
  Object.defineProperty(globalThis, "bar",
                        {get: function() { return this.this_value; }});
  %PrepareFunctionForOptimization(B.prototype.inline_this);
  %PrepareFunctionForOptimization(B.prototype.foo);

  let o = new B();
  o.this_value = "correct value";

  // Fill in the feedback.
  let r = o.foo();
  assertEquals("correct value", r);

  %OptimizeFunctionOnNextCall(B.prototype.foo);

  // Test the optimized function.
  r = o.foo();
  assertEquals("correct value", r);

  // Assert that the function was not deoptimized.
  assertOptimized(B.prototype.foo);

  // Assert that inline_this really got inlined.
  assertFalse(inline_this_is_being_interpreted);
})();