| 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(i::Isolate* isolate) { | 101 static void NonIncrementalGC() { |
| 102 isolate->heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 102 CcTest::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(CcTest::i_isolate()); | 130 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 146 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 170 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 187 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 212 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 238 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 271 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 293 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 310 NonIncrementalGC(); |
| 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(CcTest::i_isolate()); | 340 NonIncrementalGC(); |
| 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 UNINITIALIZED_TEST(DeoptimizeBinaryOperationADDString) { | 348 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 v8::Isolate* isolate = v8::Isolate::New(); | 352 LocalContext env; |
| 353 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 353 v8::HandleScope scope(env->GetIsolate()); |
| 354 isolate->Enter(); | 354 |
| 355 const char* f_source = "function f(x, y) { return x + y; };"; |
| 356 |
| 355 { | 357 { |
| 356 LocalContext env(isolate); | 358 // Compile function f and collect to type feedback to insert binary op stub |
| 357 v8::HandleScope scope(env->GetIsolate()); | 359 // call in the optimized code. |
| 360 i::FLAG_prepare_always_opt = true; |
| 361 CompileRun("var count = 0;" |
| 362 "var result = 0;" |
| 363 "var deopt = false;" |
| 364 "function X() { };" |
| 365 "X.prototype.toString = function () {" |
| 366 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'" |
| 367 "};"); |
| 368 CompileRun(f_source); |
| 369 CompileRun("for (var i = 0; i < 5; i++) {" |
| 370 " f('a+', new X());" |
| 371 "};"); |
| 358 | 372 |
| 359 const char* f_source = "function f(x, y) { return x + y; };"; | 373 // Compile an optimized version of f. |
| 374 i::FLAG_always_opt = true; |
| 375 CompileRun(f_source); |
| 376 CompileRun("f('a+', new X());"); |
| 377 CHECK(!CcTest::i_isolate()->use_crankshaft() || |
| 378 GetJSFunction(env->Global(), "f")->IsOptimized()); |
| 360 | 379 |
| 361 { | 380 // Call f and force deoptimization while processing the binary operation. |
| 362 // Compile function f and collect to type feedback to insert binary op | 381 CompileRun("deopt = true;" |
| 363 // stub call in the optimized code. | 382 "var result = f('a+', new X());"); |
| 364 i::FLAG_prepare_always_opt = true; | 383 } |
| 365 CompileRun( | 384 NonIncrementalGC(); |
| 366 "var count = 0;" | |
| 367 "var result = 0;" | |
| 368 "var deopt = false;" | |
| 369 "function X() { };" | |
| 370 "X.prototype.toString = function () {" | |
| 371 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'" | |
| 372 "};"); | |
| 373 CompileRun(f_source); | |
| 374 CompileRun( | |
| 375 "for (var i = 0; i < 5; i++) {" | |
| 376 " f('a+', new X());" | |
| 377 "};"); | |
| 378 | 385 |
| 379 // Compile an optimized version of f. | 386 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
| 380 i::FLAG_always_opt = true; | 387 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 381 CompileRun(f_source); | 388 v8::Handle<v8::Value> result = env->Global()->Get(v8_str("result")); |
| 382 CompileRun("f('a+', new X());"); | 389 CHECK(result->IsString()); |
| 383 CHECK(!i_isolate->use_crankshaft() || | 390 v8::String::Utf8Value utf8(result); |
| 384 GetJSFunction(env->Global(), "f")->IsOptimized()); | 391 CHECK_EQ("a+an X", *utf8); |
| 385 | 392 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
| 386 // Call f and force deoptimization while processing the binary operation. | |
| 387 CompileRun( | |
| 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)); | |
| 400 } | |
| 401 isolate->Exit(); | |
| 402 isolate->Dispose(); | |
| 403 } | 393 } |
| 404 | 394 |
| 405 | 395 |
| 406 static void CompileConstructorWithDeoptimizingValueOf() { | 396 static void CompileConstructorWithDeoptimizingValueOf() { |
| 407 CompileRun("var count = 0;" | 397 CompileRun("var count = 0;" |
| 408 "var result = 0;" | 398 "var result = 0;" |
| 409 "var deopt = false;" | 399 "var deopt = false;" |
| 410 "function X() { };" | 400 "function X() { };" |
| 411 "X.prototype.valueOf = function () {" | 401 "X.prototype.valueOf = function () {" |
| 412 " if (deopt) { count++; %DeoptimizeFunction(f); } return 8" | 402 " if (deopt) { count++; %DeoptimizeFunction(f); } return 8" |
| 413 "};"); | 403 "};"); |
| 414 } | 404 } |
| 415 | 405 |
| 416 | 406 |
| 417 static void TestDeoptimizeBinaryOpHelper(LocalContext* env, | 407 static void TestDeoptimizeBinaryOpHelper(LocalContext* env, |
| 418 const char* binary_op) { | 408 const char* binary_op) { |
| 419 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>((*env)->GetIsolate()); | |
| 420 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer; | 409 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer; |
| 421 SNPrintF(f_source_buffer, | 410 SNPrintF(f_source_buffer, |
| 422 "function f(x, y) { return x %s y; };", | 411 "function f(x, y) { return x %s y; };", |
| 423 binary_op); | 412 binary_op); |
| 424 char* f_source = f_source_buffer.start(); | 413 char* f_source = f_source_buffer.start(); |
| 425 | 414 |
| 426 AllowNativesSyntaxNoInlining options; | 415 AllowNativesSyntaxNoInlining options; |
| 427 // Compile function f and collect to type feedback to insert binary op stub | 416 // Compile function f and collect to type feedback to insert binary op stub |
| 428 // call in the optimized code. | 417 // call in the optimized code. |
| 429 i::FLAG_prepare_always_opt = true; | 418 i::FLAG_prepare_always_opt = true; |
| 430 CompileConstructorWithDeoptimizingValueOf(); | 419 CompileConstructorWithDeoptimizingValueOf(); |
| 431 CompileRun(f_source); | 420 CompileRun(f_source); |
| 432 CompileRun("for (var i = 0; i < 5; i++) {" | 421 CompileRun("for (var i = 0; i < 5; i++) {" |
| 433 " f(8, new X());" | 422 " f(8, new X());" |
| 434 "};"); | 423 "};"); |
| 435 | 424 |
| 436 // Compile an optimized version of f. | 425 // Compile an optimized version of f. |
| 437 i::FLAG_always_opt = true; | 426 i::FLAG_always_opt = true; |
| 438 CompileRun(f_source); | 427 CompileRun(f_source); |
| 439 CompileRun("f(7, new X());"); | 428 CompileRun("f(7, new X());"); |
| 440 CHECK(!i_isolate->use_crankshaft() || | 429 CHECK(!CcTest::i_isolate()->use_crankshaft() || |
| 441 GetJSFunction((*env)->Global(), "f")->IsOptimized()); | 430 GetJSFunction((*env)->Global(), "f")->IsOptimized()); |
| 442 | 431 |
| 443 // Call f and force deoptimization while processing the binary operation. | 432 // Call f and force deoptimization while processing the binary operation. |
| 444 CompileRun("deopt = true;" | 433 CompileRun("deopt = true;" |
| 445 "var result = f(7, new X());"); | 434 "var result = f(7, new X());"); |
| 446 NonIncrementalGC(i_isolate); | 435 NonIncrementalGC(); |
| 447 CHECK(!GetJSFunction((*env)->Global(), "f")->IsOptimized()); | 436 CHECK(!GetJSFunction((*env)->Global(), "f")->IsOptimized()); |
| 448 } | 437 } |
| 449 | 438 |
| 450 | 439 |
| 451 UNINITIALIZED_TEST(DeoptimizeBinaryOperationADD) { | 440 TEST(DeoptimizeBinaryOperationADD) { |
| 452 i::FLAG_turbo_deoptimization = true; | 441 i::FLAG_turbo_deoptimization = true; |
| 453 i::FLAG_concurrent_recompilation = false; | 442 i::FLAG_concurrent_recompilation = false; |
| 454 v8::Isolate* isolate = v8::Isolate::New(); | 443 LocalContext env; |
| 455 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 444 v8::HandleScope scope(env->GetIsolate()); |
| 456 isolate->Enter(); | 445 |
| 446 TestDeoptimizeBinaryOpHelper(&env, "+"); |
| 447 |
| 448 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 449 CHECK_EQ(15, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 450 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
| 451 } |
| 452 |
| 453 |
| 454 TEST(DeoptimizeBinaryOperationSUB) { |
| 455 i::FLAG_turbo_deoptimization = true; |
| 456 i::FLAG_concurrent_recompilation = false; |
| 457 LocalContext env; |
| 458 v8::HandleScope scope(env->GetIsolate()); |
| 459 |
| 460 TestDeoptimizeBinaryOpHelper(&env, "-"); |
| 461 |
| 462 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 463 CHECK_EQ(-1, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 464 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
| 465 } |
| 466 |
| 467 |
| 468 TEST(DeoptimizeBinaryOperationMUL) { |
| 469 i::FLAG_turbo_deoptimization = true; |
| 470 i::FLAG_concurrent_recompilation = false; |
| 471 LocalContext env; |
| 472 v8::HandleScope scope(env->GetIsolate()); |
| 473 |
| 474 TestDeoptimizeBinaryOpHelper(&env, "*"); |
| 475 |
| 476 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 477 CHECK_EQ(56, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 478 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
| 479 } |
| 480 |
| 481 |
| 482 TEST(DeoptimizeBinaryOperationDIV) { |
| 483 i::FLAG_turbo_deoptimization = true; |
| 484 i::FLAG_concurrent_recompilation = false; |
| 485 LocalContext env; |
| 486 v8::HandleScope scope(env->GetIsolate()); |
| 487 |
| 488 TestDeoptimizeBinaryOpHelper(&env, "/"); |
| 489 |
| 490 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 491 CHECK_EQ(0, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 492 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
| 493 } |
| 494 |
| 495 |
| 496 TEST(DeoptimizeBinaryOperationMOD) { |
| 497 i::FLAG_turbo_deoptimization = true; |
| 498 i::FLAG_concurrent_recompilation = false; |
| 499 LocalContext env; |
| 500 v8::HandleScope scope(env->GetIsolate()); |
| 501 |
| 502 TestDeoptimizeBinaryOpHelper(&env, "%"); |
| 503 |
| 504 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 505 CHECK_EQ(7, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 506 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
| 507 } |
| 508 |
| 509 |
| 510 TEST(DeoptimizeCompare) { |
| 511 i::FLAG_turbo_deoptimization = true; |
| 512 i::FLAG_concurrent_recompilation = false; |
| 513 LocalContext env; |
| 514 v8::HandleScope scope(env->GetIsolate()); |
| 515 |
| 516 const char* f_source = "function f(x, y) { return x < y; };"; |
| 517 |
| 457 { | 518 { |
| 458 LocalContext env(isolate); | 519 AllowNativesSyntaxNoInlining options; |
| 459 v8::HandleScope scope(env->GetIsolate()); | 520 // Compile function f and collect to type feedback to insert compare ic |
| 460 | 521 // call in the optimized code. |
| 461 TestDeoptimizeBinaryOpHelper(&env, "+"); | 522 i::FLAG_prepare_always_opt = true; |
| 462 | 523 CompileRun("var count = 0;" |
| 463 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 524 "var result = 0;" |
| 464 CHECK_EQ(15, env->Global()->Get(v8_str("result"))->Int32Value()); | 525 "var deopt = false;" |
| 465 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); | 526 "function X() { };" |
| 527 "X.prototype.toString = function () {" |
| 528 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'" |
| 529 "};"); |
| 530 CompileRun(f_source); |
| 531 CompileRun("for (var i = 0; i < 5; i++) {" |
| 532 " f('a', new X());" |
| 533 "};"); |
| 534 |
| 535 // Compile an optimized version of f. |
| 536 i::FLAG_always_opt = true; |
| 537 CompileRun(f_source); |
| 538 CompileRun("f('a', new X());"); |
| 539 CHECK(!CcTest::i_isolate()->use_crankshaft() || |
| 540 GetJSFunction(env->Global(), "f")->IsOptimized()); |
| 541 |
| 542 // Call f and force deoptimization while processing the comparison. |
| 543 CompileRun("deopt = true;" |
| 544 "var result = f('a', new X());"); |
| 466 } | 545 } |
| 467 isolate->Exit(); | 546 NonIncrementalGC(); |
| 468 isolate->Dispose(); | 547 |
| 469 } | 548 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); |
| 470 | 549 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 471 | 550 CHECK_EQ(true, env->Global()->Get(v8_str("result"))->BooleanValue()); |
| 472 UNINITIALIZED_TEST(DeoptimizeBinaryOperationSUB) { | 551 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate())); |
| 473 i::FLAG_turbo_deoptimization = true; | 552 } |
| 474 i::FLAG_concurrent_recompilation = false; | 553 |
| 475 v8::Isolate* isolate = v8::Isolate::New(); | 554 |
| 476 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 555 TEST(DeoptimizeLoadICStoreIC) { |
| 477 isolate->Enter(); | 556 i::FLAG_turbo_deoptimization = true; |
| 557 i::FLAG_concurrent_recompilation = false; |
| 558 LocalContext env; |
| 559 v8::HandleScope scope(env->GetIsolate()); |
| 560 |
| 561 // Functions to generate load/store/keyed load/keyed store IC calls. |
| 562 const char* f1_source = "function f1(x) { return x.y; };"; |
| 563 const char* g1_source = "function g1(x) { x.y = 1; };"; |
| 564 const char* f2_source = "function f2(x, y) { return x[y]; };"; |
| 565 const char* g2_source = "function g2(x, y) { x[y] = 1; };"; |
| 566 |
| 478 { | 567 { |
| 479 LocalContext env(isolate); | 568 AllowNativesSyntaxNoInlining options; |
| 480 v8::HandleScope scope(env->GetIsolate()); | 569 // Compile functions and collect to type feedback to insert ic |
| 481 | 570 // calls in the optimized code. |
| 482 TestDeoptimizeBinaryOpHelper(&env, "-"); | 571 i::FLAG_prepare_always_opt = true; |
| 483 | 572 CompileRun("var count = 0;" |
| 484 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 573 "var result = 0;" |
| 485 CHECK_EQ(-1, env->Global()->Get(v8_str("result"))->Int32Value()); | 574 "var deopt = false;" |
| 486 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); | 575 "function X() { };" |
| 576 "X.prototype.__defineGetter__('y', function () {" |
| 577 " if (deopt) { count++; %DeoptimizeFunction(f1); };" |
| 578 " return 13;" |
| 579 "});" |
| 580 "X.prototype.__defineSetter__('y', function () {" |
| 581 " if (deopt) { count++; %DeoptimizeFunction(g1); };" |
| 582 "});" |
| 583 "X.prototype.__defineGetter__('z', function () {" |
| 584 " if (deopt) { count++; %DeoptimizeFunction(f2); };" |
| 585 " return 13;" |
| 586 "});" |
| 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 } |
| 617 |
| 618 // Call functions and force deoptimization while processing the ics. |
| 619 CompileRun("deopt = true;" |
| 620 "var result = f1(new X());" |
| 621 "g1(new X());" |
| 622 "f2(new X(), 'z');" |
| 623 "g2(new X(), 'z');"); |
| 487 } | 624 } |
| 488 isolate->Exit(); | 625 NonIncrementalGC(); |
| 489 isolate->Dispose(); | 626 |
| 490 } | 627 CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); |
| 491 | 628 CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); |
| 492 | 629 CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized()); |
| 493 UNINITIALIZED_TEST(DeoptimizeBinaryOperationMUL) { | 630 CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); |
| 494 i::FLAG_turbo_deoptimization = true; | 631 CHECK_EQ(4, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 495 i::FLAG_concurrent_recompilation = false; | 632 CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 496 v8::Isolate* isolate = v8::Isolate::New(); | 633 } |
| 497 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 634 |
| 498 isolate->Enter(); | 635 |
| 636 TEST(DeoptimizeLoadICStoreICNested) { |
| 637 i::FLAG_turbo_deoptimization = true; |
| 638 i::FLAG_concurrent_recompilation = false; |
| 639 LocalContext env; |
| 640 v8::HandleScope scope(env->GetIsolate()); |
| 641 |
| 642 // Functions to generate load/store/keyed load/keyed store IC calls. |
| 643 const char* f1_source = "function f1(x) { return x.y; };"; |
| 644 const char* g1_source = "function g1(x) { x.y = 1; };"; |
| 645 const char* f2_source = "function f2(x, y) { return x[y]; };"; |
| 646 const char* g2_source = "function g2(x, y) { x[y] = 1; };"; |
| 647 |
| 499 { | 648 { |
| 500 LocalContext env(isolate); | 649 AllowNativesSyntaxNoInlining options; |
| 501 v8::HandleScope scope(env->GetIsolate()); | 650 // Compile functions and collect to type feedback to insert ic |
| 502 | 651 // calls in the optimized code. |
| 503 TestDeoptimizeBinaryOpHelper(&env, "*"); | 652 i::FLAG_prepare_always_opt = true; |
| 504 | 653 CompileRun("var count = 0;" |
| 505 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | 654 "var result = 0;" |
| 506 CHECK_EQ(56, env->Global()->Get(v8_str("result"))->Int32Value()); | 655 "var deopt = false;" |
| 507 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); | 656 "function X() { };" |
| 657 "X.prototype.__defineGetter__('y', function () {" |
| 658 " g1(this);" |
| 659 " return 13;" |
| 660 "});" |
| 661 "X.prototype.__defineSetter__('y', function () {" |
| 662 " f2(this, 'z');" |
| 663 "});" |
| 664 "X.prototype.__defineGetter__('z', function () {" |
| 665 " g2(this, 'z');" |
| 666 "});" |
| 667 "X.prototype.__defineSetter__('z', function () {" |
| 668 " if (deopt) {" |
| 669 " count++;" |
| 670 " %DeoptimizeFunction(f1);" |
| 671 " %DeoptimizeFunction(g1);" |
| 672 " %DeoptimizeFunction(f2);" |
| 673 " %DeoptimizeFunction(g2); };" |
| 674 "});"); |
| 675 CompileRun(f1_source); |
| 676 CompileRun(g1_source); |
| 677 CompileRun(f2_source); |
| 678 CompileRun(g2_source); |
| 679 CompileRun("for (var i = 0; i < 5; i++) {" |
| 680 " f1(new X());" |
| 681 " g1(new X());" |
| 682 " f2(new X(), 'z');" |
| 683 " g2(new X(), 'z');" |
| 684 "};"); |
| 685 |
| 686 // Compile an optimized version of the functions. |
| 687 i::FLAG_always_opt = true; |
| 688 CompileRun(f1_source); |
| 689 CompileRun(g1_source); |
| 690 CompileRun(f2_source); |
| 691 CompileRun(g2_source); |
| 692 CompileRun("f1(new X());"); |
| 693 CompileRun("g1(new X());"); |
| 694 CompileRun("f2(new X(), 'z');"); |
| 695 CompileRun("g2(new X(), 'z');"); |
| 696 if (CcTest::i_isolate()->use_crankshaft()) { |
| 697 CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); |
| 698 CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); |
| 699 CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); |
| 700 CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized()); |
| 701 } |
| 702 |
| 703 // Call functions and force deoptimization while processing the ics. |
| 704 CompileRun("deopt = true;" |
| 705 "var result = f1(new X());"); |
| 508 } | 706 } |
| 509 isolate->Exit(); | 707 NonIncrementalGC(); |
| 510 isolate->Dispose(); | 708 |
| 511 } | 709 CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); |
| 512 | 710 CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); |
| 513 | 711 CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized()); |
| 514 UNINITIALIZED_TEST(DeoptimizeBinaryOperationDIV) { | 712 CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); |
| 515 i::FLAG_turbo_deoptimization = true; | 713 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); |
| 516 i::FLAG_concurrent_recompilation = false; | 714 CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); |
| 517 v8::Isolate* isolate = v8::Isolate::New(); | 715 } |
| 518 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 519 isolate->Enter(); | |
| 520 { | |
| 521 LocalContext env(isolate); | |
| 522 v8::HandleScope scope(env->GetIsolate()); | |
| 523 | |
| 524 TestDeoptimizeBinaryOpHelper(&env, "/"); | |
| 525 | |
| 526 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | |
| 527 CHECK_EQ(0, env->Global()->Get(v8_str("result"))->Int32Value()); | |
| 528 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); | |
| 529 } | |
| 530 isolate->Exit(); | |
| 531 isolate->Dispose(); | |
| 532 } | |
| 533 | |
| 534 | |
| 535 UNINITIALIZED_TEST(DeoptimizeBinaryOperationMOD) { | |
| 536 i::FLAG_turbo_deoptimization = true; | |
| 537 i::FLAG_concurrent_recompilation = false; | |
| 538 v8::Isolate* isolate = v8::Isolate::New(); | |
| 539 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 540 isolate->Enter(); | |
| 541 { | |
| 542 LocalContext env(isolate); | |
| 543 v8::HandleScope scope(env->GetIsolate()); | |
| 544 | |
| 545 TestDeoptimizeBinaryOpHelper(&env, "%"); | |
| 546 | |
| 547 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | |
| 548 CHECK_EQ(7, env->Global()->Get(v8_str("result"))->Int32Value()); | |
| 549 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); | |
| 550 } | |
| 551 isolate->Exit(); | |
| 552 isolate->Dispose(); | |
| 553 } | |
| 554 | |
| 555 | |
| 556 UNINITIALIZED_TEST(DeoptimizeCompare) { | |
| 557 i::FLAG_turbo_deoptimization = true; | |
| 558 i::FLAG_concurrent_recompilation = false; | |
| 559 v8::Isolate* isolate = v8::Isolate::New(); | |
| 560 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 561 isolate->Enter(); | |
| 562 { | |
| 563 LocalContext env(isolate); | |
| 564 v8::HandleScope scope(env->GetIsolate()); | |
| 565 | |
| 566 const char* f_source = "function f(x, y) { return x < y; };"; | |
| 567 | |
| 568 { | |
| 569 AllowNativesSyntaxNoInlining options; | |
| 570 // Compile function f and collect to type feedback to insert compare ic | |
| 571 // call in the optimized code. | |
| 572 i::FLAG_prepare_always_opt = true; | |
| 573 CompileRun( | |
| 574 "var count = 0;" | |
| 575 "var result = 0;" | |
| 576 "var deopt = false;" | |
| 577 "function X() { };" | |
| 578 "X.prototype.toString = function () {" | |
| 579 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'" | |
| 580 "};"); | |
| 581 CompileRun(f_source); | |
| 582 CompileRun( | |
| 583 "for (var i = 0; i < 5; i++) {" | |
| 584 " f('a', new X());" | |
| 585 "};"); | |
| 586 | |
| 587 // Compile an optimized version of f. | |
| 588 i::FLAG_always_opt = true; | |
| 589 CompileRun(f_source); | |
| 590 CompileRun("f('a', new X());"); | |
| 591 CHECK(!i_isolate->use_crankshaft() || | |
| 592 GetJSFunction(env->Global(), "f")->IsOptimized()); | |
| 593 | |
| 594 // Call f and force deoptimization while processing the comparison. | |
| 595 CompileRun( | |
| 596 "deopt = true;" | |
| 597 "var result = f('a', new X());"); | |
| 598 } | |
| 599 NonIncrementalGC(i_isolate); | |
| 600 | |
| 601 CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized()); | |
| 602 CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value()); | |
| 603 CHECK_EQ(true, env->Global()->Get(v8_str("result"))->BooleanValue()); | |
| 604 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate)); | |
| 605 } | |
| 606 isolate->Exit(); | |
| 607 isolate->Dispose(); | |
| 608 } | |
| 609 | |
| 610 | |
| 611 UNINITIALIZED_TEST(DeoptimizeLoadICStoreIC) { | |
| 612 i::FLAG_turbo_deoptimization = true; | |
| 613 i::FLAG_concurrent_recompilation = false; | |
| 614 v8::Isolate* isolate = v8::Isolate::New(); | |
| 615 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 616 isolate->Enter(); | |
| 617 { | |
| 618 LocalContext env(isolate); | |
| 619 v8::HandleScope scope(env->GetIsolate()); | |
| 620 | |
| 621 // Functions to generate load/store/keyed load/keyed store IC calls. | |
| 622 const char* f1_source = "function f1(x) { return x.y; };"; | |
| 623 const char* g1_source = "function g1(x) { x.y = 1; };"; | |
| 624 const char* f2_source = "function f2(x, y) { return x[y]; };"; | |
| 625 const char* g2_source = "function g2(x, y) { x[y] = 1; };"; | |
| 626 | |
| 627 { | |
| 628 AllowNativesSyntaxNoInlining options; | |
| 629 // Compile functions and collect to type feedback to insert ic | |
| 630 // calls in the optimized code. | |
| 631 i::FLAG_prepare_always_opt = true; | |
| 632 CompileRun( | |
| 633 "var count = 0;" | |
| 634 "var result = 0;" | |
| 635 "var deopt = false;" | |
| 636 "function X() { };" | |
| 637 "X.prototype.__defineGetter__('y', function () {" | |
| 638 " if (deopt) { count++; %DeoptimizeFunction(f1); };" | |
| 639 " return 13;" | |
| 640 "});" | |
| 641 "X.prototype.__defineSetter__('y', function () {" | |
| 642 " if (deopt) { count++; %DeoptimizeFunction(g1); };" | |
| 643 "});" | |
| 644 "X.prototype.__defineGetter__('z', function () {" | |
| 645 " if (deopt) { count++; %DeoptimizeFunction(f2); };" | |
| 646 " return 13;" | |
| 647 "});" | |
| 648 "X.prototype.__defineSetter__('z', function () {" | |
| 649 " if (deopt) { count++; %DeoptimizeFunction(g2); };" | |
| 650 "});"); | |
| 651 CompileRun(f1_source); | |
| 652 CompileRun(g1_source); | |
| 653 CompileRun(f2_source); | |
| 654 CompileRun(g2_source); | |
| 655 CompileRun( | |
| 656 "for (var i = 0; i < 5; i++) {" | |
| 657 " f1(new X());" | |
| 658 " g1(new X());" | |
| 659 " f2(new X(), 'z');" | |
| 660 " g2(new X(), 'z');" | |
| 661 "};"); | |
| 662 | |
| 663 // Compile an optimized version of the functions. | |
| 664 i::FLAG_always_opt = true; | |
| 665 CompileRun(f1_source); | |
| 666 CompileRun(g1_source); | |
| 667 CompileRun(f2_source); | |
| 668 CompileRun(g2_source); | |
| 669 CompileRun("f1(new X());"); | |
| 670 CompileRun("g1(new X());"); | |
| 671 CompileRun("f2(new X(), 'z');"); | |
| 672 CompileRun("g2(new X(), 'z');"); | |
| 673 if (i_isolate->use_crankshaft()) { | |
| 674 CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized()); | |
| 675 CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized()); | |
| 676 CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized()); | |
| 677 CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized()); | |
| 678 } | |
| 679 | |
| 680 // Call functions and force deoptimization while processing the ics. | |
| 681 CompileRun( | |
| 682 "deopt = true;" | |
| 683 "var result = f1(new X());" | |
| 684 "g1(new X());" | |
| 685 "f2(new X(), 'z');" | |
| 686 "g2(new X(), 'z');"); | |
| 687 } | |
| 688 NonIncrementalGC(i_isolate); | |
| 689 | |
| 690 CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized()); | |
| 691 CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized()); | |
| 692 CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized()); | |
| 693 CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized()); | |
| 694 CHECK_EQ(4, env->Global()->Get(v8_str("count"))->Int32Value()); | |
| 695 CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value()); | |
| 696 } | |
| 697 isolate->Exit(); | |
| 698 isolate->Dispose(); | |
| 699 } | |
| 700 | |
| 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 |