OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 #include "src/v8.h" | |
6 | |
7 #include "test/cctest/compiler/function-tester.h" | |
8 | |
9 using namespace v8::internal; | |
10 using namespace v8::internal::compiler; | |
11 | |
12 // TODO(sigurds) At the moment we do not write optimization frames when | |
13 // inlining, thus the reported stack depth changes depending on inlining. | |
14 // AssertStackDepth checks the stack depth at a simple way to ensure that | |
15 // inlining actually occurs. | |
16 // Once inlining creates optimization frames, all these unit tests need to | |
17 // check that the optimization frame is there. | |
18 | |
19 | |
20 static void AssertStackDepth(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
21 v8::HandleScope scope(args.GetIsolate()); | |
22 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace( | |
23 args.GetIsolate(), 10, v8::StackTrace::kDetailed); | |
24 CHECK_EQ(args[0]->ToInt32()->Value(), stackTrace->GetFrameCount()); | |
25 } | |
26 | |
27 | |
28 static void InstallAssertStackDepthHelper(v8::Isolate* isolate) { | |
29 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
30 v8::Local<v8::FunctionTemplate> t = | |
31 v8::FunctionTemplate::New(isolate, AssertStackDepth); | |
32 context->Global()->Set(v8_str("AssertStackDepth"), t->GetFunction()); | |
33 } | |
34 | |
35 | |
36 TEST(SimpleInlining) { | |
37 i::FLAG_turbo_inlining = true; | |
38 FunctionTester T( | |
39 "(function(){" | |
40 "function foo(s) { AssertStackDepth(1); return s; };" | |
41 "function bar(s, t) { return foo(s); };" | |
42 "return bar;})();"); | |
43 | |
44 InstallAssertStackDepthHelper(CcTest::isolate()); | |
45 T.CheckCall(T.Val(1), T.Val(1), T.Val(2)); | |
46 } | |
47 | |
48 | |
49 TEST(SimpleInliningContext) { | |
50 i::FLAG_turbo_inlining = true; | |
51 FunctionTester T( | |
52 "(function () {" | |
53 "function foo(s) { AssertStackDepth(1); var x = 12; return s + x; };" | |
54 "function bar(s, t) { return foo(s); };" | |
55 "return bar;" | |
56 "})();"); | |
57 | |
58 InstallAssertStackDepthHelper(CcTest::isolate()); | |
59 T.CheckCall(T.Val(13), T.Val(1), T.Val(2)); | |
60 } | |
61 | |
62 | |
63 TEST(CaptureContext) { | |
64 i::FLAG_turbo_inlining = true; | |
65 FunctionTester T( | |
66 "var f = (function () {" | |
67 "var x = 42;" | |
68 "function bar(s) { return x + s; };" | |
69 "return (function (s) { return bar(s); });" | |
70 "})();" | |
71 "(function (s) { return f(s)})"); | |
72 | |
73 InstallAssertStackDepthHelper(CcTest::isolate()); | |
74 T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); | |
75 } | |
76 | |
77 | |
78 // TODO(sigurds) For now we do not inline any native functions. If we do at | |
79 // some point, change this test. | |
80 TEST(DontInlineEval) { | |
81 i::FLAG_turbo_inlining = true; | |
82 FunctionTester T( | |
83 "var x = 42;" | |
84 "(function () {" | |
85 "function bar(s, t) { return eval(\"AssertStackDepth(2); x\") };" | |
86 "return bar;" | |
87 "})();"); | |
88 | |
89 InstallAssertStackDepthHelper(CcTest::isolate()); | |
90 T.CheckCall(T.Val(42), T.Val("x"), T.undefined()); | |
91 } | |
92 | |
93 | |
94 TEST(InlineOmitArguments) { | |
95 i::FLAG_turbo_inlining = true; | |
96 FunctionTester T( | |
97 "(function () {" | |
98 "var x = 42;" | |
99 "function bar(s, t, u, v) { AssertStackDepth(1); return x + s; };" | |
100 "return (function (s,t) { return bar(s); });" | |
101 "})();"); | |
102 | |
103 InstallAssertStackDepthHelper(CcTest::isolate()); | |
104 T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); | |
105 } | |
106 | |
107 | |
108 TEST(InlineSurplusArguments) { | |
109 i::FLAG_turbo_inlining = true; | |
110 FunctionTester T( | |
111 "(function () {" | |
112 "var x = 42;" | |
113 "function foo(s) { AssertStackDepth(1); return x + s; };" | |
114 "function bar(s,t) { return foo(s,t,13); };" | |
115 "return bar;" | |
116 "})();"); | |
117 | |
118 InstallAssertStackDepthHelper(CcTest::isolate()); | |
119 T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); | |
120 } | |
121 | |
122 | |
123 TEST(InlineTwice) { | |
124 i::FLAG_turbo_inlining = true; | |
125 FunctionTester T( | |
126 "(function () {" | |
127 "var x = 42;" | |
128 "function bar(s) { AssertStackDepth(1); return x + s; };" | |
129 "return (function (s,t) { return bar(s) + bar(t); });" | |
130 "})();"); | |
131 | |
132 InstallAssertStackDepthHelper(CcTest::isolate()); | |
133 T.CheckCall(T.Val(2 * 42 + 12 + 4), T.Val(12), T.Val(4)); | |
134 } | |
135 | |
136 | |
137 TEST(InlineTwiceDependent) { | |
138 i::FLAG_turbo_inlining = true; | |
139 FunctionTester T( | |
140 "(function () {" | |
141 "var x = 42;" | |
142 "function foo(s) { AssertStackDepth(1); return x + s; };" | |
143 "function bar(s,t) { return foo(foo(s)); };" | |
144 "return bar;" | |
145 "})();"); | |
146 | |
147 InstallAssertStackDepthHelper(CcTest::isolate()); | |
148 T.CheckCall(T.Val(42 + 42 + 12), T.Val(12), T.Val(4)); | |
149 } | |
150 | |
151 | |
152 TEST(InlineTwiceDependentDiamond) { | |
153 i::FLAG_turbo_inlining = true; | |
154 FunctionTester T( | |
155 "(function () {" | |
156 "function foo(s) { if (true) {" | |
157 " return 12 } else { return 13; } };" | |
158 "function bar(s,t) { return foo(foo(1)); };" | |
159 "return bar;" | |
160 "})();"); | |
161 | |
162 InstallAssertStackDepthHelper(CcTest::isolate()); | |
163 T.CheckCall(T.Val(12), T.undefined(), T.undefined()); | |
164 } | |
165 | |
166 | |
167 TEST(InlineTwiceDependentDiamondReal) { | |
168 i::FLAG_turbo_inlining = true; | |
169 FunctionTester T( | |
170 "(function () {" | |
171 "var x = 41;" | |
172 "function foo(s) { AssertStackDepth(1); if (s % 2 == 0) {" | |
173 " return x - s } else { return x + s; } };" | |
174 "function bar(s,t) { return foo(foo(s)); };" | |
175 "return bar;" | |
176 "})();"); | |
177 | |
178 InstallAssertStackDepthHelper(CcTest::isolate()); | |
179 T.CheckCall(T.Val(-11), T.Val(11), T.Val(4)); | |
180 } | |
OLD | NEW |