OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 91 } |
92 | 92 |
93 private: | 93 private: |
94 bool allow_natives_syntax_; | 94 bool allow_natives_syntax_; |
95 bool use_inlining_; | 95 bool use_inlining_; |
96 }; | 96 }; |
97 | 97 |
98 | 98 |
99 // Abort any ongoing incremental marking to make sure that all weak global | 99 // Abort any ongoing incremental marking to make sure that all weak global |
100 // handle callbacks are processed. | 100 // handle callbacks are processed. |
101 static void NonIncrementalGC() { | 101 static void NonIncrementalGC(i::Isolate* isolate) { |
102 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 102 isolate->heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
103 } | 103 } |
104 | 104 |
105 | 105 |
106 static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, | 106 static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, |
107 const char* property_name) { | 107 const char* property_name) { |
108 v8::Local<v8::Function> fun = | 108 v8::Local<v8::Function> fun = |
109 v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name))); | 109 v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name))); |
110 return v8::Utils::OpenHandle(*fun); | 110 return v8::Utils::OpenHandle(*fun); |
111 } | 111 } |
112 | 112 |
113 | 113 |
114 TEST(DeoptimizeSimple) { | 114 TEST(DeoptimizeSimple) { |
115 i::FLAG_turbo_deoptimization = true; | 115 i::FLAG_turbo_deoptimization = true; |
116 | 116 |
117 LocalContext env; | 117 LocalContext env; |
118 v8::HandleScope scope(env->GetIsolate()); | 118 v8::HandleScope scope(env->GetIsolate()); |
119 | 119 |
120 // Test lazy deoptimization of a simple function. | 120 // Test lazy deoptimization of a simple function. |
121 { | 121 { |
122 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 122 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
123 CompileRun( | 123 CompileRun( |
124 "var count = 0;" | 124 "var count = 0;" |
125 "function h() { %DeoptimizeFunction(f); }" | 125 "function h() { %DeoptimizeFunction(f); }" |
126 "function g() { count++; h(); }" | 126 "function g() { count++; h(); }" |
127 "function f() { g(); };" | 127 "function f() { g(); };" |
128 "f();"); | 128 "f();"); |
129 } | 129 } |
130 NonIncrementalGC(); | 130 NonIncrementalGC(CcTest::i_isolate()); |
131 | 131 |
132 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 132 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
133 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | 133 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
134 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 134 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
135 | 135 |
136 // Test lazy deoptimization of a simple function. Call the function after the | 136 // Test lazy deoptimization of a simple function. Call the function after the |
137 // deoptimization while it is still activated further down the stack. | 137 // deoptimization while it is still activated further down the stack. |
138 { | 138 { |
139 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 139 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
140 CompileRun( | 140 CompileRun( |
141 "var count = 0;" | 141 "var count = 0;" |
142 "function g() { count++; %DeoptimizeFunction(f); f(false); }" | 142 "function g() { count++; %DeoptimizeFunction(f); f(false); }" |
143 "function f(x) { if (x) { g(); } else { return } };" | 143 "function f(x) { if (x) { g(); } else { return } };" |
144 "f(true);"); | 144 "f(true);"); |
145 } | 145 } |
146 NonIncrementalGC(); | 146 NonIncrementalGC(CcTest::i_isolate()); |
147 | 147 |
148 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 148 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
149 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | 149 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
150 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 150 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
151 } | 151 } |
152 | 152 |
153 | 153 |
154 TEST(DeoptimizeSimpleWithArguments) { | 154 TEST(DeoptimizeSimpleWithArguments) { |
155 i::FLAG_turbo_deoptimization = true; | 155 i::FLAG_turbo_deoptimization = true; |
156 | 156 |
157 LocalContext env; | 157 LocalContext env; |
158 v8::HandleScope scope(env->GetIsolate()); | 158 v8::HandleScope scope(env->GetIsolate()); |
159 | 159 |
160 // Test lazy deoptimization of a simple function with some arguments. | 160 // Test lazy deoptimization of a simple function with some arguments. |
161 { | 161 { |
162 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 162 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
163 CompileRun( | 163 CompileRun( |
164 "var count = 0;" | 164 "var count = 0;" |
165 "function h(x) { %DeoptimizeFunction(f); }" | 165 "function h(x) { %DeoptimizeFunction(f); }" |
166 "function g(x, y) { count++; h(x); }" | 166 "function g(x, y) { count++; h(x); }" |
167 "function f(x, y, z) { g(1,x); y+z; };" | 167 "function f(x, y, z) { g(1,x); y+z; };" |
168 "f(1, \"2\", false);"); | 168 "f(1, \"2\", false);"); |
169 } | 169 } |
170 NonIncrementalGC(); | 170 NonIncrementalGC(CcTest::i_isolate()); |
171 | 171 |
172 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 172 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
173 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | 173 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
174 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 174 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
175 | 175 |
176 // Test lazy deoptimization of a simple function with some arguments. Call the | 176 // Test lazy deoptimization of a simple function with some arguments. Call the |
177 // function after the deoptimization while it is still activated further down | 177 // function after the deoptimization while it is still activated further down |
178 // the stack. | 178 // the stack. |
179 { | 179 { |
180 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 180 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
181 CompileRun( | 181 CompileRun( |
182 "var count = 0;" | 182 "var count = 0;" |
183 "function g(x, y) { count++; %DeoptimizeFunction(f); f(false, 1, y); }" | 183 "function g(x, y) { count++; %DeoptimizeFunction(f); f(false, 1, y); }" |
184 "function f(x, y, z) { if (x) { g(x, y); } else { return y + z; } };" | 184 "function f(x, y, z) { if (x) { g(x, y); } else { return y + z; } };" |
185 "f(true, 1, \"2\");"); | 185 "f(true, 1, \"2\");"); |
186 } | 186 } |
187 NonIncrementalGC(); | 187 NonIncrementalGC(CcTest::i_isolate()); |
188 | 188 |
189 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 189 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
190 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | 190 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
191 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 191 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
192 } | 192 } |
193 | 193 |
194 | 194 |
195 TEST(DeoptimizeSimpleNested) { | 195 TEST(DeoptimizeSimpleNested) { |
196 i::FLAG_turbo_deoptimization = true; | 196 i::FLAG_turbo_deoptimization = true; |
197 | 197 |
198 LocalContext env; | 198 LocalContext env; |
199 v8::HandleScope scope(env->GetIsolate()); | 199 v8::HandleScope scope(env->GetIsolate()); |
200 | 200 |
201 // Test lazy deoptimization of a simple function. Have a nested function call | 201 // Test lazy deoptimization of a simple function. Have a nested function call |
202 // do the deoptimization. | 202 // do the deoptimization. |
203 { | 203 { |
204 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 204 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
205 CompileRun( | 205 CompileRun( |
206 "var count = 0;" | 206 "var count = 0;" |
207 "var result = 0;" | 207 "var result = 0;" |
208 "function h(x, y, z) { return x + y + z; }" | 208 "function h(x, y, z) { return x + y + z; }" |
209 "function g(z) { count++; %DeoptimizeFunction(f); return z;}" | 209 "function g(z) { count++; %DeoptimizeFunction(f); return z;}" |
210 "function f(x,y,z) { return h(x, y, g(z)); };" | 210 "function f(x,y,z) { return h(x, y, g(z)); };" |
211 "result = f(1, 2, 3);"); | 211 "result = f(1, 2, 3);"); |
212 NonIncrementalGC(); | 212 NonIncrementalGC(CcTest::i_isolate()); |
213 | 213 |
214 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 214 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
215 CHECK_EQ(6, env->Global()->Get(v8_str("result"))->Int32Value()); | 215 CHECK_EQ(6, env->Global()->Get(v8_str("result"))->Int32Value()); |
216 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | 216 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
217 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 217 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
218 } | 218 } |
219 } | 219 } |
220 | 220 |
221 | 221 |
222 TEST(DeoptimizeRecursive) { | 222 TEST(DeoptimizeRecursive) { |
223 i::FLAG_turbo_deoptimization = true; | 223 i::FLAG_turbo_deoptimization = true; |
224 LocalContext env; | 224 LocalContext env; |
225 v8::HandleScope scope(env->GetIsolate()); | 225 v8::HandleScope scope(env->GetIsolate()); |
226 | 226 |
227 { | 227 { |
228 // Test lazy deoptimization of a simple function called recursively. Call | 228 // Test lazy deoptimization of a simple function called recursively. Call |
229 // the function recursively a number of times before deoptimizing it. | 229 // the function recursively a number of times before deoptimizing it. |
230 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 230 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
231 CompileRun( | 231 CompileRun( |
232 "var count = 0;" | 232 "var count = 0;" |
233 "var calls = 0;" | 233 "var calls = 0;" |
234 "function g() { count++; %DeoptimizeFunction(f); }" | 234 "function g() { count++; %DeoptimizeFunction(f); }" |
235 "function f(x) { calls++; if (x > 0) { f(x - 1); } else { g(); } };" | 235 "function f(x) { calls++; if (x > 0) { f(x - 1); } else { g(); } };" |
236 "f(10);"); | 236 "f(10);"); |
237 } | 237 } |
238 NonIncrementalGC(); | 238 NonIncrementalGC(CcTest::i_isolate()); |
239 | 239 |
240 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 240 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
241 CHECK_EQ(11, env->Global()->Get(v8_str("calls"))->Int32Value()); | 241 CHECK_EQ(11, env->Global()->Get(v8_str("calls"))->Int32Value()); |
242 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 242 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
243 | 243 |
244 v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast( | 244 v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast( |
245 env->Global()->Get(v8::String::NewFromUtf8(CcTest::isolate(), "f"))); | 245 env->Global()->Get(v8::String::NewFromUtf8(CcTest::isolate(), "f"))); |
246 CHECK(!fun.IsEmpty()); | 246 CHECK(!fun.IsEmpty()); |
247 } | 247 } |
248 | 248 |
(...skipping 12 matching lines...) Expand all Loading... |
261 " %DeoptimizeFunction(f1);" | 261 " %DeoptimizeFunction(f1);" |
262 " %DeoptimizeFunction(f2);" | 262 " %DeoptimizeFunction(f2);" |
263 " %DeoptimizeFunction(f3);" | 263 " %DeoptimizeFunction(f3);" |
264 " %DeoptimizeFunction(f4);}" | 264 " %DeoptimizeFunction(f4);}" |
265 "function f4(x) { g(); };" | 265 "function f4(x) { g(); };" |
266 "function f3(x, y, z) { f4(); return x + y + z; };" | 266 "function f3(x, y, z) { f4(); return x + y + z; };" |
267 "function f2(x, y) { return x + f3(y + 1, y + 1, y + 1) + y; };" | 267 "function f2(x, y) { return x + f3(y + 1, y + 1, y + 1) + y; };" |
268 "function f1(x) { return f2(x + 1, x + 1) + x; };" | 268 "function f1(x) { return f2(x + 1, x + 1) + x; };" |
269 "result = f1(1);"); | 269 "result = f1(1);"); |
270 } | 270 } |
271 NonIncrementalGC(); | 271 NonIncrementalGC(CcTest::i_isolate()); |
272 | 272 |
273 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 273 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
274 CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); | 274 CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); |
275 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 275 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
276 } | 276 } |
277 | 277 |
278 | 278 |
279 TEST(DeoptimizeConstructor) { | 279 TEST(DeoptimizeConstructor) { |
280 i::FLAG_turbo_deoptimization = true; | 280 i::FLAG_turbo_deoptimization = true; |
281 LocalContext env; | 281 LocalContext env; |
282 v8::HandleScope scope(env->GetIsolate()); | 282 v8::HandleScope scope(env->GetIsolate()); |
283 | 283 |
284 { | 284 { |
285 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 285 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
286 CompileRun( | 286 CompileRun( |
287 "var count = 0;" | 287 "var count = 0;" |
288 "function g() { count++;" | 288 "function g() { count++;" |
289 " %DeoptimizeFunction(f); }" | 289 " %DeoptimizeFunction(f); }" |
290 "function f() { g(); };" | 290 "function f() { g(); };" |
291 "result = new f() instanceof f;"); | 291 "result = new f() instanceof f;"); |
292 } | 292 } |
293 NonIncrementalGC(); | 293 NonIncrementalGC(CcTest::i_isolate()); |
294 | 294 |
295 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 295 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
296 CHECK(env->Global()->Get(v8_str("result"))->IsTrue()); | 296 CHECK(env->Global()->Get(v8_str("result"))->IsTrue()); |
297 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 297 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
298 | 298 |
299 { | 299 { |
300 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 300 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
301 CompileRun( | 301 CompileRun( |
302 "var count = 0;" | 302 "var count = 0;" |
303 "var result = 0;" | 303 "var result = 0;" |
304 "function g() { count++;" | 304 "function g() { count++;" |
305 " %DeoptimizeFunction(f); }" | 305 " %DeoptimizeFunction(f); }" |
306 "function f(x, y) { this.x = x; g(); this.y = y; };" | 306 "function f(x, y) { this.x = x; g(); this.y = y; };" |
307 "result = new f(1, 2);" | 307 "result = new f(1, 2);" |
308 "result = result.x + result.y;"); | 308 "result = result.x + result.y;"); |
309 } | 309 } |
310 NonIncrementalGC(); | 310 NonIncrementalGC(CcTest::i_isolate()); |
311 | 311 |
312 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 312 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
313 CHECK_EQ(3, env->Global()->Get(v8_str("result"))->Int32Value()); | 313 CHECK_EQ(3, env->Global()->Get(v8_str("result"))->Int32Value()); |
314 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 314 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
315 } | 315 } |
316 | 316 |
317 | 317 |
318 TEST(DeoptimizeConstructorMultiple) { | 318 TEST(DeoptimizeConstructorMultiple) { |
319 i::FLAG_turbo_deoptimization = true; | 319 i::FLAG_turbo_deoptimization = true; |
320 LocalContext env; | 320 LocalContext env; |
321 v8::HandleScope scope(env->GetIsolate()); | 321 v8::HandleScope scope(env->GetIsolate()); |
322 | 322 |
323 { | 323 { |
324 AlwaysOptimizeAllowNativesSyntaxNoInlining options; | 324 AlwaysOptimizeAllowNativesSyntaxNoInlining options; |
325 CompileRun( | 325 CompileRun( |
326 "var count = 0;" | 326 "var count = 0;" |
327 "var result = 0;" | 327 "var result = 0;" |
328 "function g() { count++;" | 328 "function g() { count++;" |
329 " %DeoptimizeFunction(f1);" | 329 " %DeoptimizeFunction(f1);" |
330 " %DeoptimizeFunction(f2);" | 330 " %DeoptimizeFunction(f2);" |
331 " %DeoptimizeFunction(f3);" | 331 " %DeoptimizeFunction(f3);" |
332 " %DeoptimizeFunction(f4);}" | 332 " %DeoptimizeFunction(f4);}" |
333 "function f4(x) { this.result = x; g(); };" | 333 "function f4(x) { this.result = x; g(); };" |
334 "function f3(x, y, z) { this.result = new f4(x + y + z).result; };" | 334 "function f3(x, y, z) { this.result = new f4(x + y + z).result; };" |
335 "function f2(x, y) {" | 335 "function f2(x, y) {" |
336 " this.result = x + new f3(y + 1, y + 1, y + 1).result + y; };" | 336 " this.result = x + new f3(y + 1, y + 1, y + 1).result + y; };" |
337 "function f1(x) { this.result = new f2(x + 1, x + 1).result + x; };" | 337 "function f1(x) { this.result = new f2(x + 1, x + 1).result + x; };" |
338 "result = new f1(1).result;"); | 338 "result = new f1(1).result;"); |
339 } | 339 } |
340 NonIncrementalGC(); | 340 NonIncrementalGC(CcTest::i_isolate()); |
341 | 341 |
342 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 342 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
343 CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); | 343 CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value()); |
344 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 344 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
345 } | 345 } |
346 | 346 |
347 | 347 |
348 TEST(DeoptimizeBinaryOperationADDString) { | 348 UNINITIALIZED_TEST(DeoptimizeBinaryOperationADDString) { |
349 i::FLAG_turbo_deoptimization = true; | 349 i::FLAG_turbo_deoptimization = true; |
350 i::FLAG_concurrent_recompilation = false; | 350 i::FLAG_concurrent_recompilation = false; |
351 AllowNativesSyntaxNoInlining options; | 351 AllowNativesSyntaxNoInlining options; |
352 LocalContext env; | 352 v8::Isolate* isolate = v8::Isolate::New(); |
353 v8::HandleScope scope(env->GetIsolate()); | 353 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 354 isolate->Enter(); |
| 355 { |
| 356 LocalContext env(isolate); |
| 357 v8::HandleScope scope(env->GetIsolate()); |
354 | 358 |
355 const char* f_source = "function f(x, y) { return x + y; };"; | 359 const char* f_source = "function f(x, y) { return x + y; };"; |
356 | 360 |
357 { | 361 { |
358 // Compile function f and collect to type feedback to insert binary op stub | 362 // Compile function f and collect to type feedback to insert binary op |
359 // call in the optimized code. | 363 // stub call in the optimized code. |
360 i::FLAG_prepare_always_opt = true; | 364 i::FLAG_prepare_always_opt = true; |
361 CompileRun("var count = 0;" | 365 CompileRun( |
362 "var result = 0;" | 366 "var count = 0;" |
363 "var deopt = false;" | 367 "var result = 0;" |
364 "function X() { };" | 368 "var deopt = false;" |
365 "X.prototype.toString = function () {" | 369 "function X() { };" |
366 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'" | 370 "X.prototype.toString = function () {" |
367 "};"); | 371 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'" |
368 CompileRun(f_source); | 372 "};"); |
369 CompileRun("for (var i = 0; i < 5; i++) {" | 373 CompileRun(f_source); |
370 " f('a+', new X());" | 374 CompileRun( |
371 "};"); | 375 "for (var i = 0; i < 5; i++) {" |
| 376 " f('a+', new X());" |
| 377 "};"); |
372 | 378 |
373 // Compile an optimized version of f. | 379 // Compile an optimized version of f. |
374 i::FLAG_always_opt = true; | 380 i::FLAG_always_opt = true; |
375 CompileRun(f_source); | 381 CompileRun(f_source); |
376 CompileRun("f('a+', new X());"); | 382 CompileRun("f('a+', new X());"); |
377 CHECK(!CcTest::i_isolate()->use_crankshaft() || | 383 CHECK(!i_isolate->use_crankshaft() || |
378 GetJSFunction(env->Global(), "f")->IsOptimized()); | 384 GetJSFunction(env->Global(), "f")->IsOptimized()); |
379 | 385 |
380 // Call f and force deoptimization while processing the binary operation. | 386 // Call f and force deoptimization while processing the binary operation. |
381 CompileRun("deopt = true;" | 387 CompileRun( |
382 "var result = f('a+', new X());"); | 388 "deopt = true;" |
| 389 "var result = f('a+', new X());"); |
| 390 } |
| 391 NonIncrementalGC(i_isolate); |
| 392 |
| 393 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
| 394 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 395 v8::Handle<v8::Value> result = env->Global()->Get(v8_str("result")); |
| 396 CHECK(result->IsString()); |
| 397 v8::String::Utf8Value utf8(result); |
| 398 CHECK_EQ("a+an X", *utf8); |
| 399 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); |
383 } | 400 } |
384 NonIncrementalGC(); | 401 isolate->Exit(); |
385 | 402 isolate->Dispose(); |
386 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | |
387 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | |
388 v8::Handle<v8::Value> result = env->Global()->Get(v8_str("result")); | |
389 CHECK(result->IsString()); | |
390 v8::String::Utf8Value utf8(result); | |
391 CHECK_EQ("a+an X", *utf8); | |
392 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | |
393 } | 403 } |
394 | 404 |
395 | 405 |
396 static void CompileConstructorWithDeoptimizingValueOf() { | 406 static void CompileConstructorWithDeoptimizingValueOf() { |
397 CompileRun("var count = 0;" | 407 CompileRun("var count = 0;" |
398 "var result = 0;" | 408 "var result = 0;" |
399 "var deopt = false;" | 409 "var deopt = false;" |
400 "function X() { };" | 410 "function X() { };" |
401 "X.prototype.valueOf = function () {" | 411 "X.prototype.valueOf = function () {" |
402 " if (deopt) { count++; %DeoptimizeFunction(f); } return 8" | 412 " if (deopt) { count++; %DeoptimizeFunction(f); } return 8" |
403 "};"); | 413 "};"); |
404 } | 414 } |
405 | 415 |
406 | 416 |
407 static void TestDeoptimizeBinaryOpHelper(LocalContext* env, | 417 static void TestDeoptimizeBinaryOpHelper(LocalContext* env, |
408 const char* binary_op) { | 418 const char* binary_op) { |
| 419 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>((*env)->GetIsolate()); |
409 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer; | 420 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer; |
410 SNPrintF(f_source_buffer, | 421 SNPrintF(f_source_buffer, |
411 "function f(x, y) { return x %s y; };", | 422 "function f(x, y) { return x %s y; };", |
412 binary_op); | 423 binary_op); |
413 char* f_source = f_source_buffer.start(); | 424 char* f_source = f_source_buffer.start(); |
414 | 425 |
415 AllowNativesSyntaxNoInlining options; | 426 AllowNativesSyntaxNoInlining options; |
416 // Compile function f and collect to type feedback to insert binary op stub | 427 // Compile function f and collect to type feedback to insert binary op stub |
417 // call in the optimized code. | 428 // call in the optimized code. |
418 i::FLAG_prepare_always_opt = true; | 429 i::FLAG_prepare_always_opt = true; |
419 CompileConstructorWithDeoptimizingValueOf(); | 430 CompileConstructorWithDeoptimizingValueOf(); |
420 CompileRun(f_source); | 431 CompileRun(f_source); |
421 CompileRun("for (var i = 0; i < 5; i++) {" | 432 CompileRun("for (var i = 0; i < 5; i++) {" |
422 " f(8, new X());" | 433 " f(8, new X());" |
423 "};"); | 434 "};"); |
424 | 435 |
425 // Compile an optimized version of f. | 436 // Compile an optimized version of f. |
426 i::FLAG_always_opt = true; | 437 i::FLAG_always_opt = true; |
427 CompileRun(f_source); | 438 CompileRun(f_source); |
428 CompileRun("f(7, new X());"); | 439 CompileRun("f(7, new X());"); |
429 CHECK(!CcTest::i_isolate()->use_crankshaft() || | 440 CHECK(!i_isolate->use_crankshaft() || |
430 GetJSFunction((*env)->Global(), "f")->IsOptimized()); | 441 GetJSFunction((*env)->Global(), "f")->IsOptimized()); |
431 | 442 |
432 // Call f and force deoptimization while processing the binary operation. | 443 // Call f and force deoptimization while processing the binary operation. |
433 CompileRun("deopt = true;" | 444 CompileRun("deopt = true;" |
434 "var result = f(7, new X());"); | 445 "var result = f(7, new X());"); |
435 NonIncrementalGC(); | 446 NonIncrementalGC(i_isolate); |
436 CHECK(!GetJSFunction((*env)->Global(), "f")->IsOptimized()); | 447 CHECK(!GetJSFunction((*env)->Global(), "f")->IsOptimized()); |
437 } | 448 } |
438 | 449 |
439 | 450 |
440 TEST(DeoptimizeBinaryOperationADD) { | 451 UNINITIALIZED_TEST(DeoptimizeBinaryOperationADD) { |
441 i::FLAG_turbo_deoptimization = true; | 452 i::FLAG_turbo_deoptimization = true; |
442 i::FLAG_concurrent_recompilation = false; | 453 i::FLAG_concurrent_recompilation = false; |
443 LocalContext env; | 454 v8::Isolate* isolate = v8::Isolate::New(); |
444 v8::HandleScope scope(env->GetIsolate()); | 455 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
445 | 456 isolate->Enter(); |
446 TestDeoptimizeBinaryOpHelper(&env, "+"); | 457 { |
447 | 458 LocalContext env(isolate); |
448 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 459 v8::HandleScope scope(env->GetIsolate()); |
449 CHECK_EQ(15, env->Global()->Get(v8_str("result"))->Int32Value()); | 460 |
450 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 461 TestDeoptimizeBinaryOpHelper(&env, "+"); |
451 } | 462 |
452 | 463 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
453 | 464 CHECK_EQ(15, env->Global()->Get(v8_str("result"))->Int32Value()); |
454 TEST(DeoptimizeBinaryOperationSUB) { | 465 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); |
455 i::FLAG_turbo_deoptimization = true; | 466 } |
456 i::FLAG_concurrent_recompilation = false; | 467 isolate->Exit(); |
457 LocalContext env; | 468 isolate->Dispose(); |
458 v8::HandleScope scope(env->GetIsolate()); | 469 } |
459 | 470 |
460 TestDeoptimizeBinaryOpHelper(&env, "-"); | 471 |
461 | 472 UNINITIALIZED_TEST(DeoptimizeBinaryOperationSUB) { |
462 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 473 i::FLAG_turbo_deoptimization = true; |
463 CHECK_EQ(-1, env->Global()->Get(v8_str("result"))->Int32Value()); | 474 i::FLAG_concurrent_recompilation = false; |
464 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 475 v8::Isolate* isolate = v8::Isolate::New(); |
465 } | 476 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
466 | 477 isolate->Enter(); |
467 | 478 { |
468 TEST(DeoptimizeBinaryOperationMUL) { | 479 LocalContext env(isolate); |
469 i::FLAG_turbo_deoptimization = true; | 480 v8::HandleScope scope(env->GetIsolate()); |
470 i::FLAG_concurrent_recompilation = false; | 481 |
471 LocalContext env; | 482 TestDeoptimizeBinaryOpHelper(&env, "-"); |
472 v8::HandleScope scope(env->GetIsolate()); | 483 |
473 | 484 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
474 TestDeoptimizeBinaryOpHelper(&env, "*"); | 485 CHECK_EQ(-1, env->Global()->Get(v8_str("result"))->Int32Value()); |
475 | 486 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); |
476 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 487 } |
477 CHECK_EQ(56, env->Global()->Get(v8_str("result"))->Int32Value()); | 488 isolate->Exit(); |
478 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 489 isolate->Dispose(); |
479 } | 490 } |
480 | 491 |
481 | 492 |
482 TEST(DeoptimizeBinaryOperationDIV) { | 493 UNINITIALIZED_TEST(DeoptimizeBinaryOperationMUL) { |
483 i::FLAG_turbo_deoptimization = true; | 494 i::FLAG_turbo_deoptimization = true; |
484 i::FLAG_concurrent_recompilation = false; | 495 i::FLAG_concurrent_recompilation = false; |
485 LocalContext env; | 496 v8::Isolate* isolate = v8::Isolate::New(); |
486 v8::HandleScope scope(env->GetIsolate()); | 497 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
487 | 498 isolate->Enter(); |
488 TestDeoptimizeBinaryOpHelper(&env, "/"); | 499 { |
489 | 500 LocalContext env(isolate); |
490 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 501 v8::HandleScope scope(env->GetIsolate()); |
491 CHECK_EQ(0, env->Global()->Get(v8_str("result"))->Int32Value()); | 502 |
492 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 503 TestDeoptimizeBinaryOpHelper(&env, "*"); |
493 } | 504 |
494 | 505 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
495 | 506 CHECK_EQ(56, env->Global()->Get(v8_str("result"))->Int32Value()); |
496 TEST(DeoptimizeBinaryOperationMOD) { | 507 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); |
497 i::FLAG_turbo_deoptimization = true; | 508 } |
498 i::FLAG_concurrent_recompilation = false; | 509 isolate->Exit(); |
499 LocalContext env; | 510 isolate->Dispose(); |
500 v8::HandleScope scope(env->GetIsolate()); | 511 } |
501 | 512 |
502 TestDeoptimizeBinaryOpHelper(&env, "%"); | 513 |
503 | 514 UNINITIALIZED_TEST(DeoptimizeBinaryOperationDIV) { |
504 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 515 i::FLAG_turbo_deoptimization = true; |
505 CHECK_EQ(7, env->Global()->Get(v8_str("result"))->Int32Value()); | 516 i::FLAG_concurrent_recompilation = false; |
506 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 517 v8::Isolate* isolate = v8::Isolate::New(); |
507 } | 518 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
508 | 519 isolate->Enter(); |
509 | 520 { |
510 TEST(DeoptimizeCompare) { | 521 LocalContext env(isolate); |
511 i::FLAG_turbo_deoptimization = true; | 522 v8::HandleScope scope(env->GetIsolate()); |
512 i::FLAG_concurrent_recompilation = false; | 523 |
513 LocalContext env; | 524 TestDeoptimizeBinaryOpHelper(&env, "/"); |
514 v8::HandleScope scope(env->GetIsolate()); | 525 |
515 | 526 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
516 const char* f_source = "function f(x, y) { return x < y; };"; | 527 CHECK_EQ(0, env->Global()->Get(v8_str("result"))->Int32Value()); |
517 | 528 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); |
518 { | 529 } |
519 AllowNativesSyntaxNoInlining options; | 530 isolate->Exit(); |
520 // Compile function f and collect to type feedback to insert compare ic | 531 isolate->Dispose(); |
521 // call in the optimized code. | 532 } |
522 i::FLAG_prepare_always_opt = true; | 533 |
523 CompileRun("var count = 0;" | 534 |
524 "var result = 0;" | 535 UNINITIALIZED_TEST(DeoptimizeBinaryOperationMOD) { |
525 "var deopt = false;" | 536 i::FLAG_turbo_deoptimization = true; |
526 "function X() { };" | 537 i::FLAG_concurrent_recompilation = false; |
527 "X.prototype.toString = function () {" | 538 v8::Isolate* isolate = v8::Isolate::New(); |
528 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'" | 539 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
529 "};"); | 540 isolate->Enter(); |
530 CompileRun(f_source); | 541 { |
531 CompileRun("for (var i = 0; i < 5; i++) {" | 542 LocalContext env(isolate); |
532 " f('a', new X());" | 543 v8::HandleScope scope(env->GetIsolate()); |
533 "};"); | 544 |
534 | 545 TestDeoptimizeBinaryOpHelper(&env, "%"); |
535 // Compile an optimized version of f. | 546 |
536 i::FLAG_always_opt = true; | 547 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
537 CompileRun(f_source); | 548 CHECK_EQ(7, env->Global()->Get(v8_str("result"))->Int32Value()); |
538 CompileRun("f('a', new X());"); | 549 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); |
539 CHECK(!CcTest::i_isolate()->use_crankshaft() || | 550 } |
540 GetJSFunction(env->Global(), "f")->IsOptimized()); | 551 isolate->Exit(); |
541 | 552 isolate->Dispose(); |
542 // Call f and force deoptimization while processing the comparison. | 553 } |
543 CompileRun("deopt = true;" | 554 |
544 "var result = f('a', new X());"); | 555 |
545 } | 556 UNINITIALIZED_TEST(DeoptimizeCompare) { |
546 NonIncrementalGC(); | 557 i::FLAG_turbo_deoptimization = true; |
547 | 558 i::FLAG_concurrent_recompilation = false; |
548 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | 559 v8::Isolate* isolate = v8::Isolate::New(); |
549 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 560 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
550 CHECK_EQ(true, env->Global()->Get(v8_str("result"))->BooleanValue()); | 561 isolate->Enter(); |
551 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); | 562 { |
552 } | 563 LocalContext env(isolate); |
553 | 564 v8::HandleScope scope(env->GetIsolate()); |
554 | 565 |
555 TEST(DeoptimizeLoadICStoreIC) { | 566 const char* f_source = "function f(x, y) { return x < y; };"; |
556 i::FLAG_turbo_deoptimization = true; | 567 |
557 i::FLAG_concurrent_recompilation = false; | 568 { |
558 LocalContext env; | 569 AllowNativesSyntaxNoInlining options; |
559 v8::HandleScope scope(env->GetIsolate()); | 570 // Compile function f and collect to type feedback to insert compare ic |
560 | 571 // call in the optimized code. |
561 // Functions to generate load/store/keyed load/keyed store IC calls. | 572 i::FLAG_prepare_always_opt = true; |
562 const char* f1_source = "function f1(x) { return x.y; };"; | 573 CompileRun( |
563 const char* g1_source = "function g1(x) { x.y = 1; };"; | 574 "var count = 0;" |
564 const char* f2_source = "function f2(x, y) { return x[y]; };"; | 575 "var result = 0;" |
565 const char* g2_source = "function g2(x, y) { x[y] = 1; };"; | 576 "var deopt = false;" |
566 | 577 "function X() { };" |
567 { | 578 "X.prototype.toString = function () {" |
568 AllowNativesSyntaxNoInlining options; | 579 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'" |
569 // Compile functions and collect to type feedback to insert ic | 580 "};"); |
570 // calls in the optimized code. | 581 CompileRun(f_source); |
571 i::FLAG_prepare_always_opt = true; | 582 CompileRun( |
572 CompileRun("var count = 0;" | 583 "for (var i = 0; i < 5; i++) {" |
573 "var result = 0;" | 584 " f('a', new X());" |
574 "var deopt = false;" | 585 "};"); |
575 "function X() { };" | 586 |
576 "X.prototype.__defineGetter__('y', function () {" | 587 // Compile an optimized version of f. |
577 " if (deopt) { count++; %DeoptimizeFunction(f1); };" | 588 i::FLAG_always_opt = true; |
578 " return 13;" | 589 CompileRun(f_source); |
579 "});" | 590 CompileRun("f('a', new X());"); |
580 "X.prototype.__defineSetter__('y', function () {" | 591 CHECK(!i_isolate->use_crankshaft() || |
581 " if (deopt) { count++; %DeoptimizeFunction(g1); };" | 592 GetJSFunction(env->Global(), "f")->IsOptimized()); |
582 "});" | 593 |
583 "X.prototype.__defineGetter__('z', function () {" | 594 // Call f and force deoptimization while processing the comparison. |
584 " if (deopt) { count++; %DeoptimizeFunction(f2); };" | 595 CompileRun( |
585 " return 13;" | 596 "deopt = true;" |
586 "});" | 597 "var result = f('a', new X());"); |
587 "X.prototype.__defineSetter__('z', function () {" | |
588 " if (deopt) { count++; %DeoptimizeFunction(g2); };" | |
589 "});"); | |
590 CompileRun(f1_source); | |
591 CompileRun(g1_source); | |
592 CompileRun(f2_source); | |
593 CompileRun(g2_source); | |
594 CompileRun("for (var i = 0; i < 5; i++) {" | |
595 " f1(new X());" | |
596 " g1(new X());" | |
597 " f2(new X(), 'z');" | |
598 " g2(new X(), 'z');" | |
599 "};"); | |
600 | |
601 // Compile an optimized version of the functions. | |
602 i::FLAG_always_opt = true; | |
603 CompileRun(f1_source); | |
604 CompileRun(g1_source); | |
605 CompileRun(f2_source); | |
606 CompileRun(g2_source); | |
607 CompileRun("f1(new X());"); | |
608 CompileRun("g1(new X());"); | |
609 CompileRun("f2(new X(), 'z');"); | |
610 CompileRun("g2(new X(), 'z');"); | |
611 if (CcTest::i_isolate()->use_crankshaft()) { | |
612 CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); | |
613 CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); | |
614 CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); | |
615 CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized()); | |
616 } | 598 } |
617 | 599 NonIncrementalGC(i_isolate); |
618 // Call functions and force deoptimization while processing the ics. | 600 |
619 CompileRun("deopt = true;" | 601 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
620 "var result = f1(new X());" | 602 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
621 "g1(new X());" | 603 CHECK_EQ(true, env->Global()->Get(v8_str("result"))->BooleanValue()); |
622 "f2(new X(), 'z');" | 604 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); |
623 "g2(new X(), 'z');"); | 605 } |
624 } | 606 isolate->Exit(); |
625 NonIncrementalGC(); | 607 isolate->Dispose(); |
626 | 608 } |
627 CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); | 609 |
628 CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); | 610 |
629 CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized()); | 611 UNINITIALIZED_TEST(DeoptimizeLoadICStoreIC) { |
630 CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); | 612 i::FLAG_turbo_deoptimization = true; |
631 CHECK_EQ(4, env->Global()->Get(v8_str("count"))->Int32Value()); | 613 i::FLAG_concurrent_recompilation = false; |
632 CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); | 614 v8::Isolate* isolate = v8::Isolate::New(); |
633 } | 615 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
634 | 616 isolate->Enter(); |
635 | 617 { |
636 TEST(DeoptimizeLoadICStoreICNested) { | 618 LocalContext env(isolate); |
637 i::FLAG_turbo_deoptimization = true; | 619 v8::HandleScope scope(env->GetIsolate()); |
638 i::FLAG_concurrent_recompilation = false; | 620 |
639 LocalContext env; | 621 // Functions to generate load/store/keyed load/keyed store IC calls. |
640 v8::HandleScope scope(env->GetIsolate()); | 622 const char* f1_source = "function f1(x) { return x.y; };"; |
641 | 623 const char* g1_source = "function g1(x) { x.y = 1; };"; |
642 // Functions to generate load/store/keyed load/keyed store IC calls. | 624 const char* f2_source = "function f2(x, y) { return x[y]; };"; |
643 const char* f1_source = "function f1(x) { return x.y; };"; | 625 const char* g2_source = "function g2(x, y) { x[y] = 1; };"; |
644 const char* g1_source = "function g1(x) { x.y = 1; };"; | 626 |
645 const char* f2_source = "function f2(x, y) { return x[y]; };"; | 627 { |
646 const char* g2_source = "function g2(x, y) { x[y] = 1; };"; | 628 AllowNativesSyntaxNoInlining options; |
647 | 629 // Compile functions and collect to type feedback to insert ic |
648 { | 630 // calls in the optimized code. |
649 AllowNativesSyntaxNoInlining options; | 631 i::FLAG_prepare_always_opt = true; |
650 // Compile functions and collect to type feedback to insert ic | 632 CompileRun( |
651 // calls in the optimized code. | 633 "var count = 0;" |
652 i::FLAG_prepare_always_opt = true; | 634 "var result = 0;" |
653 CompileRun("var count = 0;" | 635 "var deopt = false;" |
654 "var result = 0;" | 636 "function X() { };" |
655 "var deopt = false;" | 637 "X.prototype.__defineGetter__('y', function () {" |
656 "function X() { };" | 638 " if (deopt) { count++; %DeoptimizeFunction(f1); };" |
657 "X.prototype.__defineGetter__('y', function () {" | 639 " return 13;" |
658 " g1(this);" | 640 "});" |
659 " return 13;" | 641 "X.prototype.__defineSetter__('y', function () {" |
660 "});" | 642 " if (deopt) { count++; %DeoptimizeFunction(g1); };" |
661 "X.prototype.__defineSetter__('y', function () {" | 643 "});" |
662 " f2(this, 'z');" | 644 "X.prototype.__defineGetter__('z', function () {" |
663 "});" | 645 " if (deopt) { count++; %DeoptimizeFunction(f2); };" |
664 "X.prototype.__defineGetter__('z', function () {" | 646 " return 13;" |
665 " g2(this, 'z');" | 647 "});" |
666 "});" | 648 "X.prototype.__defineSetter__('z', function () {" |
667 "X.prototype.__defineSetter__('z', function () {" | 649 " if (deopt) { count++; %DeoptimizeFunction(g2); };" |
668 " if (deopt) {" | 650 "});"); |
669 " count++;" | 651 CompileRun(f1_source); |
670 " %DeoptimizeFunction(f1);" | 652 CompileRun(g1_source); |
671 " %DeoptimizeFunction(g1);" | 653 CompileRun(f2_source); |
672 " %DeoptimizeFunction(f2);" | 654 CompileRun(g2_source); |
673 " %DeoptimizeFunction(g2); };" | 655 CompileRun( |
674 "});"); | 656 "for (var i = 0; i < 5; i++) {" |
675 CompileRun(f1_source); | 657 " f1(new X());" |
676 CompileRun(g1_source); | 658 " g1(new X());" |
677 CompileRun(f2_source); | 659 " f2(new X(), 'z');" |
678 CompileRun(g2_source); | 660 " g2(new X(), 'z');" |
679 CompileRun("for (var i = 0; i < 5; i++) {" | 661 "};"); |
680 " f1(new X());" | 662 |
681 " g1(new X());" | 663 // Compile an optimized version of the functions. |
682 " f2(new X(), 'z');" | 664 i::FLAG_always_opt = true; |
683 " g2(new X(), 'z');" | 665 CompileRun(f1_source); |
684 "};"); | 666 CompileRun(g1_source); |
685 | 667 CompileRun(f2_source); |
686 // Compile an optimized version of the functions. | 668 CompileRun(g2_source); |
687 i::FLAG_always_opt = true; | 669 CompileRun("f1(new X());"); |
688 CompileRun(f1_source); | 670 CompileRun("g1(new X());"); |
689 CompileRun(g1_source); | 671 CompileRun("f2(new X(), 'z');"); |
690 CompileRun(f2_source); | 672 CompileRun("g2(new X(), 'z');"); |
691 CompileRun(g2_source); | 673 if (i_isolate->use_crankshaft()) { |
692 CompileRun("f1(new X());"); | 674 CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); |
693 CompileRun("g1(new X());"); | 675 CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); |
694 CompileRun("f2(new X(), 'z');"); | 676 CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); |
695 CompileRun("g2(new X(), 'z');"); | 677 CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized()); |
696 if (CcTest::i_isolate()->use_crankshaft()) { | 678 } |
697 CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); | 679 |
698 CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); | 680 // Call functions and force deoptimization while processing the ics. |
699 CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); | 681 CompileRun( |
700 CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized()); | 682 "deopt = true;" |
| 683 "var result = f1(new X());" |
| 684 "g1(new X());" |
| 685 "f2(new X(), 'z');" |
| 686 "g2(new X(), 'z');"); |
701 } | 687 } |
702 | 688 NonIncrementalGC(i_isolate); |
703 // Call functions and force deoptimization while processing the ics. | 689 |
704 CompileRun("deopt = true;" | 690 CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); |
705 "var result = f1(new X());"); | 691 CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); |
706 } | 692 CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized()); |
707 NonIncrementalGC(); | 693 CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); |
708 | 694 CHECK_EQ(4, env->Global()->Get(v8_str("count"))->Int32Value()); |
709 CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); | 695 CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); |
710 CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); | 696 } |
711 CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized()); | 697 isolate->Exit(); |
712 CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); | 698 isolate->Dispose(); |
713 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 699 } |
714 CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); | 700 |
715 } | 701 |
| 702 UNINITIALIZED_TEST(DeoptimizeLoadICStoreICNested) { |
| 703 i::FLAG_turbo_deoptimization = true; |
| 704 i::FLAG_concurrent_recompilation = false; |
| 705 v8::Isolate* isolate = v8::Isolate::New(); |
| 706 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 707 isolate->Enter(); |
| 708 { |
| 709 LocalContext env(isolate); |
| 710 v8::HandleScope scope(env->GetIsolate()); |
| 711 |
| 712 // Functions to generate load/store/keyed load/keyed store IC calls. |
| 713 const char* f1_source = "function f1(x) { return x.y; };"; |
| 714 const char* g1_source = "function g1(x) { x.y = 1; };"; |
| 715 const char* f2_source = "function f2(x, y) { return x[y]; };"; |
| 716 const char* g2_source = "function g2(x, y) { x[y] = 1; };"; |
| 717 |
| 718 { |
| 719 AllowNativesSyntaxNoInlining options; |
| 720 // Compile functions and collect to type feedback to insert ic |
| 721 // calls in the optimized code. |
| 722 i::FLAG_prepare_always_opt = true; |
| 723 CompileRun( |
| 724 "var count = 0;" |
| 725 "var result = 0;" |
| 726 "var deopt = false;" |
| 727 "function X() { };" |
| 728 "X.prototype.__defineGetter__('y', function () {" |
| 729 " g1(this);" |
| 730 " return 13;" |
| 731 "});" |
| 732 "X.prototype.__defineSetter__('y', function () {" |
| 733 " f2(this, 'z');" |
| 734 "});" |
| 735 "X.prototype.__defineGetter__('z', function () {" |
| 736 " g2(this, 'z');" |
| 737 "});" |
| 738 "X.prototype.__defineSetter__('z', function () {" |
| 739 " if (deopt) {" |
| 740 " count++;" |
| 741 " %DeoptimizeFunction(f1);" |
| 742 " %DeoptimizeFunction(g1);" |
| 743 " %DeoptimizeFunction(f2);" |
| 744 " %DeoptimizeFunction(g2); };" |
| 745 "});"); |
| 746 CompileRun(f1_source); |
| 747 CompileRun(g1_source); |
| 748 CompileRun(f2_source); |
| 749 CompileRun(g2_source); |
| 750 CompileRun( |
| 751 "for (var i = 0; i < 5; i++) {" |
| 752 " f1(new X());" |
| 753 " g1(new X());" |
| 754 " f2(new X(), 'z');" |
| 755 " g2(new X(), 'z');" |
| 756 "};"); |
| 757 |
| 758 // Compile an optimized version of the functions. |
| 759 i::FLAG_always_opt = true; |
| 760 CompileRun(f1_source); |
| 761 CompileRun(g1_source); |
| 762 CompileRun(f2_source); |
| 763 CompileRun(g2_source); |
| 764 CompileRun("f1(new X());"); |
| 765 CompileRun("g1(new X());"); |
| 766 CompileRun("f2(new X(), 'z');"); |
| 767 CompileRun("g2(new X(), 'z');"); |
| 768 if (i_isolate->use_crankshaft()) { |
| 769 CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); |
| 770 CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); |
| 771 CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); |
| 772 CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized()); |
| 773 } |
| 774 |
| 775 // Call functions and force deoptimization while processing the ics. |
| 776 CompileRun( |
| 777 "deopt = true;" |
| 778 "var result = f1(new X());"); |
| 779 } |
| 780 NonIncrementalGC(i_isolate); |
| 781 |
| 782 CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); |
| 783 CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); |
| 784 CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized()); |
| 785 CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); |
| 786 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 787 CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 788 } |
| 789 isolate->Exit(); |
| 790 isolate->Dispose(); |
| 791 } |
OLD | NEW |