Home | History | Annotate | Download | only in es8
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Flags: --allow-natives-syntax --harmony-explicit-tailcalls --stack-size=100
      6 
      7 //
      8 // Tail calls work only in strict mode.
      9 //
     10 (function() {
     11   function f(n) {
     12     if (n <= 0) {
     13       return "foo";
     14     }
     15     return f(n - 1);
     16   }
     17   assertThrows(()=>{ f(1e5) });
     18   %OptimizeFunctionOnNextCall(f);
     19   assertThrows(()=>{ f(1e5) });
     20 })();
     21 
     22 
     23 //
     24 // Tail call normal functions.
     25 //
     26 (function() {
     27   "use strict";
     28   function f(n) {
     29     if (n <= 0) {
     30       return "foo";
     31     }
     32     return continue f(n - 1);
     33   }
     34   assertEquals("foo", f(1e5));
     35   %OptimizeFunctionOnNextCall(f);
     36   assertEquals("foo", f(1e5));
     37 })();
     38 
     39 
     40 (function() {
     41   "use strict";
     42   function f(n) {
     43     if (n <= 0) {
     44       return  "foo";
     45     }
     46     return continue f(n - 1, 42);  // Call with arguments adaptor.
     47   }
     48   assertEquals("foo", f(1e5));
     49   %OptimizeFunctionOnNextCall(f);
     50   assertEquals("foo", f(1e5));
     51 })();
     52 
     53 
     54 (function() {
     55   "use strict";
     56   function f(n){
     57     if (n <= 0) {
     58       return "foo";
     59     }
     60     return continue g(n - 1);
     61   }
     62   function g(n){
     63     if (n <= 0) {
     64       return "bar";
     65     }
     66     return continue f(n - 1);
     67   }
     68   assertEquals("foo", f(1e5));
     69   assertEquals("bar", f(1e5 + 1));
     70   %OptimizeFunctionOnNextCall(f);
     71   assertEquals("foo", f(1e5));
     72   assertEquals("bar", f(1e5 + 1));
     73 })();
     74 
     75 
     76 (function() {
     77   "use strict";
     78   function f(n){
     79     if (n <= 0) {
     80       return "foo";
     81     }
     82     return continue g(n - 1, 42);  // Call with arguments adaptor.
     83   }
     84   function g(n){
     85     if (n <= 0) {
     86       return "bar";
     87     }
     88     return continue f(n - 1, 42);  // Call with arguments adaptor.
     89   }
     90   assertEquals("foo", f(1e5));
     91   assertEquals("bar", f(1e5 + 1));
     92   %OptimizeFunctionOnNextCall(f);
     93   assertEquals("foo", f(1e5));
     94   assertEquals("bar", f(1e5 + 1));
     95 })();
     96 
     97 
     98 //
     99 // Tail call bound functions.
    100 //
    101 (function() {
    102   "use strict";
    103   function f0(n) {
    104     if (n <= 0) {
    105       return "foo";
    106     }
    107     return continue f_bound(n - 1);
    108   }
    109   var f_bound = f0.bind({});
    110   function f(n) {
    111     return continue f_bound(n);
    112   }
    113   assertEquals("foo", f(1e5));
    114   %OptimizeFunctionOnNextCall(f);
    115   assertEquals("foo", f(1e5));
    116 })();
    117 
    118 
    119 (function() {
    120   "use strict";
    121   function f0(n){
    122     if (n <= 0) {
    123       return "foo";
    124     }
    125     return continue g_bound(n - 1);
    126   }
    127   function g0(n){
    128     if (n <= 0) {
    129       return "bar";
    130     }
    131     return continue f_bound(n - 1);
    132   }
    133   var f_bound = f0.bind({});
    134   var g_bound = g0.bind({});
    135   function f(n) {
    136     return continue f_bound(n);
    137   }
    138   assertEquals("foo", f(1e5));
    139   assertEquals("bar", f(1e5 + 1));
    140   %OptimizeFunctionOnNextCall(f);
    141   assertEquals("foo", f(1e5));
    142   assertEquals("bar", f(1e5 + 1));
    143 })();
    144