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-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 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 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 g(n - 1); 61 } 62 function g(n){ 63 if (n <= 0) { 64 return "bar"; 65 } 66 return 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 g(n - 1, 42); // Call with arguments adaptor. 83 } 84 function g(n){ 85 if (n <= 0) { 86 return "bar"; 87 } 88 return 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 f_bound(n - 1); 108 } 109 var f_bound = f0.bind({}); 110 function f(n) { 111 return 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 g_bound(n - 1); 126 } 127 function g0(n){ 128 if (n <= 0) { 129 return "bar"; 130 } 131 return f_bound(n - 1); 132 } 133 var f_bound = f0.bind({}); 134 var g_bound = g0.bind({}); 135 function f(n) { 136 return 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