| Index: test/mjsunit/array-constructor-feedback.js | 
| diff --git a/test/mjsunit/array-constructor-feedback.js b/test/mjsunit/array-constructor-feedback.js | 
| index 302239b79c173c9987fb0a2127278c6a57caa6c9..e29e7694654ea0b3e4ceb2cb3e9c06ecfe0d8dab 100644 | 
| --- a/test/mjsunit/array-constructor-feedback.js | 
| +++ b/test/mjsunit/array-constructor-feedback.js | 
| @@ -81,19 +81,137 @@ function assertKind(expected, obj, name_opt) { | 
| } | 
|  | 
| if (support_smi_only_arrays) { | 
| -  function bar0(t) { | 
| -    return new t(); | 
| -  } | 
|  | 
| -  a = bar0(Array); | 
| -  a[0] = 3.5; | 
| -  b = bar0(Array); | 
| -  assertKind(elements_kind.fast_double, b); | 
| -  %OptimizeFunctionOnNextCall(bar0); | 
| -  b = bar0(Array); | 
| -  assertKind(elements_kind.fast_double, b); | 
| -  assertTrue(2 != %GetOptimizationStatus(bar0)); | 
| -  // bar0 should deopt | 
| -  b = bar0(Object); | 
| -  assertTrue(1 != %GetOptimizationStatus(bar0)); | 
| +  // Test: If a call site goes megamorphic, it loses the ability to | 
| +  // use allocation site feedback. | 
| +  (function() { | 
| +    function bar(t, len) { | 
| +      return new t(len); | 
| +    } | 
| + | 
| +    a = bar(Array, 10); | 
| +    a[0] = 3.5; | 
| +    b = bar(Array, 1); | 
| +    assertKind(elements_kind.fast_double, b); | 
| +    c = bar(Object, 3); | 
| +    b = bar(Array, 10); | 
| +    assertKind(elements_kind.fast_smi_only, b); | 
| +    b[0] = 3.5; | 
| +    c = bar(Array, 10); | 
| +    assertKind(elements_kind.fast_smi_only, c); | 
| +  })(); | 
| + | 
| + | 
| +  // Test: ensure that crankshafted array constructor sites are deopted | 
| +  // if another function is used. | 
| +  (function() { | 
| +    function bar0(t) { | 
| +      return new t(); | 
| +    } | 
| +    a = bar0(Array); | 
| +    a[0] = 3.5; | 
| +    b = bar0(Array); | 
| +    assertKind(elements_kind.fast_double, b); | 
| +    %OptimizeFunctionOnNextCall(bar0); | 
| +    b = bar0(Array); | 
| +    assertKind(elements_kind.fast_double, b); | 
| +    assertTrue(2 != %GetOptimizationStatus(bar0)); | 
| +    // bar0 should deopt | 
| +    b = bar0(Object); | 
| +    assertTrue(1 != %GetOptimizationStatus(bar0)); | 
| +    // When it's re-optimized, we should call through the full stub | 
| +    bar0(Array); | 
| +    %OptimizeFunctionOnNextCall(bar0); | 
| +    b = bar0(Array); | 
| +    // We also lost our ability to record kind feedback, as the site | 
| +    // is megamorphic now. | 
| +    assertKind(elements_kind.fast_smi_only, b); | 
| +    assertTrue(2 != %GetOptimizationStatus(bar0)); | 
| +    b[0] = 3.5; | 
| +    c = bar0(Array); | 
| +    assertKind(elements_kind.fast_smi_only, c); | 
| +  })(); | 
| + | 
| + | 
| +  // Test: Ensure that bailouts from the stub don't deopt a crankshafted | 
| +  // method with a call to that stub. | 
| +  (function() { | 
| +    function bar(len) { | 
| +      return new Array(len); | 
| +    } | 
| +    a = bar(10); | 
| +    a[0] = "a string"; | 
| +    a = bar(10); | 
| +    assertKind(elements_kind.fast, a); | 
| +    %OptimizeFunctionOnNextCall(bar); | 
| +    a = bar(10); | 
| +    assertKind(elements_kind.fast, a); | 
| +    assertTrue(2 != %GetOptimizationStatus(bar)); | 
| +    // The stub bails out, but the method call should be fine. | 
| +    a = bar(100000); | 
| +    assertTrue(2 != %GetOptimizationStatus(bar)); | 
| +    assertKind(elements_kind.dictionary, a); | 
| + | 
| +    // If the argument isn't a smi, it bails out as well | 
| +    a = bar("oops"); | 
| +    assertTrue(2 != %GetOptimizationStatus(bar)); | 
| +    assertKind(elements_kind.fast, a); | 
| + | 
| +    function barn(one, two, three) { | 
| +      return new Array(one, two, three); | 
| +    } | 
| + | 
| +    barn(1, 2, 3); | 
| +    barn(1, 2, 3); | 
| +    %OptimizeFunctionOnNextCall(barn); | 
| +    barn(1, 2, 3); | 
| +    assertTrue(2 != %GetOptimizationStatus(barn)); | 
| +    a = barn(1, "oops", 3); | 
| +    // The stub should bail out but the method should remain optimized. | 
| +    assertKind(elements_kind.fast, a); | 
| +    assertTrue(2 != %GetOptimizationStatus(barn)); | 
| +  })(); | 
| + | 
| + | 
| +  // Test: When a method with array constructor is crankshafted, the type | 
| +  // feedback for elements kind is baked in. Verify that transitions don't | 
| +  // change it anymore | 
| +  (function() { | 
| +    function bar() { | 
| +      return new Array(); | 
| +    } | 
| +    a = bar(); | 
| +    bar(); | 
| +    %OptimizeFunctionOnNextCall(bar); | 
| +    b = bar(); | 
| +    // This only makes sense to test if we allow crankshafting | 
| +    if (4 != %GetOptimizationStatus(bar)) { | 
| +      assertTrue(2 != %GetOptimizationStatus(bar)); | 
| +      %DebugPrint(3); | 
| +      b[0] = 3.5; | 
| +      c = bar(); | 
| +      assertKind(elements_kind.fast_smi_only, c); | 
| +      assertTrue(2 != %GetOptimizationStatus(bar)); | 
| +    } | 
| +  })(); | 
| + | 
| + | 
| +  // Test: create arrays in two contexts, verifying that the correct | 
| +  // map for Array in that context will be used. | 
| +  (function() { | 
| +    function bar() { return new Array(); } | 
| +    bar(); | 
| +    bar(); | 
| +    %OptimizeFunctionOnNextCall(bar); | 
| +    a = bar(); | 
| +    assertTrue(a instanceof Array); | 
| + | 
| +    var contextB = Realm.create(); | 
| +    Realm.eval(contextB, "function bar2() { return new Array(); };"); | 
| +    Realm.eval(contextB, "bar2(); bar2();"); | 
| +    Realm.eval(contextB, "%OptimizeFunctionOnNextCall(bar2);"); | 
| +    Realm.eval(contextB, "bar2();"); | 
| +    assertFalse(Realm.eval(contextB, "bar2();") instanceof Array); | 
| +    assertTrue(Realm.eval(contextB, "bar2() instanceof Array")); | 
| +  })(); | 
| } | 
|  |