blob: 7ba16b59f8847332d809edd8edc5e42a9875e9df [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/api.h"
33#include "src/base/platform/platform.h"
34#include "src/compilation-cache.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035#include "src/debug/debug.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036#include "src/deoptimizer.h"
37#include "src/isolate.h"
38#include "test/cctest/cctest.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010039
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040using ::v8::base::OS;
Ben Murdochb0fe1622011-05-05 13:52:32 +010041using ::v8::internal::Deoptimizer;
42using ::v8::internal::EmbeddedVector;
Steve Block44f0eee2011-05-26 01:26:41 +010043using ::v8::internal::Handle;
44using ::v8::internal::Isolate;
45using ::v8::internal::JSFunction;
Steve Block44f0eee2011-05-26 01:26:41 +010046using ::v8::internal::Object;
Ben Murdochb0fe1622011-05-05 13:52:32 +010047
48// Size of temp buffer for formatting small strings.
49#define SMALL_STRING_BUFFER_SIZE 80
50
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051// Utility class to set the following runtime flags when constructed and return
52// to their default state when destroyed:
53// --allow-natives-syntax --always-opt --noturbo-inlining --nouse-inlining
Ben Murdochb0fe1622011-05-05 13:52:32 +010054class AlwaysOptimizeAllowNativesSyntaxNoInlining {
55 public:
56 AlwaysOptimizeAllowNativesSyntaxNoInlining()
57 : always_opt_(i::FLAG_always_opt),
58 allow_natives_syntax_(i::FLAG_allow_natives_syntax),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 turbo_inlining_(i::FLAG_turbo_inlining),
Ben Murdochb0fe1622011-05-05 13:52:32 +010060 use_inlining_(i::FLAG_use_inlining) {
61 i::FLAG_always_opt = true;
62 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 i::FLAG_turbo_inlining = false;
Ben Murdochb0fe1622011-05-05 13:52:32 +010064 i::FLAG_use_inlining = false;
65 }
66
67 ~AlwaysOptimizeAllowNativesSyntaxNoInlining() {
Ben Murdochb0fe1622011-05-05 13:52:32 +010068 i::FLAG_always_opt = always_opt_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069 i::FLAG_allow_natives_syntax = allow_natives_syntax_;
70 i::FLAG_turbo_inlining = turbo_inlining_;
Ben Murdochb0fe1622011-05-05 13:52:32 +010071 i::FLAG_use_inlining = use_inlining_;
72 }
73
74 private:
75 bool always_opt_;
76 bool allow_natives_syntax_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 bool turbo_inlining_;
Ben Murdochb0fe1622011-05-05 13:52:32 +010078 bool use_inlining_;
79};
80
81
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082// Utility class to set the following runtime flags when constructed and return
83// to their default state when destroyed:
84// --allow-natives-syntax --noturbo-inlining --nouse-inlining
Ben Murdochb0fe1622011-05-05 13:52:32 +010085class AllowNativesSyntaxNoInlining {
86 public:
87 AllowNativesSyntaxNoInlining()
88 : allow_natives_syntax_(i::FLAG_allow_natives_syntax),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 turbo_inlining_(i::FLAG_turbo_inlining),
Ben Murdochb0fe1622011-05-05 13:52:32 +010090 use_inlining_(i::FLAG_use_inlining) {
91 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 i::FLAG_turbo_inlining = false;
Ben Murdochb0fe1622011-05-05 13:52:32 +010093 i::FLAG_use_inlining = false;
94 }
95
96 ~AllowNativesSyntaxNoInlining() {
97 i::FLAG_allow_natives_syntax = allow_natives_syntax_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 i::FLAG_turbo_inlining = turbo_inlining_;
Ben Murdochb0fe1622011-05-05 13:52:32 +010099 i::FLAG_use_inlining = use_inlining_;
100 }
101
102 private:
103 bool allow_natives_syntax_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 bool turbo_inlining_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100105 bool use_inlining_;
106};
107
108
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100109// Abort any ongoing incremental marking to make sure that all weak global
110// handle callbacks are processed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111static void NonIncrementalGC(i::Isolate* isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 isolate->heap()->CollectAllGarbage();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100113}
114
115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116static Handle<JSFunction> GetJSFunction(v8::Local<v8::Context> context,
Steve Block053d10c2011-06-13 19:13:29 +0100117 const char* property_name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast(
119 context->Global()->Get(context, v8_str(property_name)).ToLocalChecked());
120 return i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*fun));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100121}
122
123
124TEST(DeoptimizeSimple) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100125 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100127
128 // Test lazy deoptimization of a simple function.
129 {
130 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
131 CompileRun(
132 "var count = 0;"
133 "function h() { %DeoptimizeFunction(f); }"
134 "function g() { count++; h(); }"
135 "function f() { g(); };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100136 "f();");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100137 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 CHECK_EQ(1, env->Global()
141 ->Get(env.local(), v8_str("count"))
142 .ToLocalChecked()
143 ->Int32Value(env.local())
144 .FromJust());
145 CHECK(!GetJSFunction(env.local(), "f")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100147
148 // Test lazy deoptimization of a simple function. Call the function after the
149 // deoptimization while it is still activated further down the stack.
150 {
151 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
152 CompileRun(
153 "var count = 0;"
154 "function g() { count++; %DeoptimizeFunction(f); f(false); }"
155 "function f(x) { if (x) { g(); } else { return } };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100156 "f(true);");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100157 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 CHECK_EQ(1, env->Global()
161 ->Get(env.local(), v8_str("count"))
162 .ToLocalChecked()
163 ->Int32Value(env.local())
164 .FromJust());
165 CHECK(!GetJSFunction(env.local(), "f")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100167}
168
169
170TEST(DeoptimizeSimpleWithArguments) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100171 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000172 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100173
174 // Test lazy deoptimization of a simple function with some arguments.
175 {
176 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
177 CompileRun(
178 "var count = 0;"
179 "function h(x) { %DeoptimizeFunction(f); }"
180 "function g(x, y) { count++; h(x); }"
181 "function f(x, y, z) { g(1,x); y+z; };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100182 "f(1, \"2\", false);");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100183 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 CHECK_EQ(1, env->Global()
187 ->Get(env.local(), v8_str("count"))
188 .ToLocalChecked()
189 ->Int32Value(env.local())
190 .FromJust());
191 CHECK(!GetJSFunction(env.local(), "f")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100193
194 // Test lazy deoptimization of a simple function with some arguments. Call the
195 // function after the deoptimization while it is still activated further down
196 // the stack.
197 {
198 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
199 CompileRun(
200 "var count = 0;"
201 "function g(x, y) { count++; %DeoptimizeFunction(f); f(false, 1, y); }"
202 "function f(x, y, z) { if (x) { g(x, y); } else { return y + z; } };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100203 "f(true, 1, \"2\");");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100204 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 CHECK_EQ(1, env->Global()
208 ->Get(env.local(), v8_str("count"))
209 .ToLocalChecked()
210 ->Int32Value(env.local())
211 .FromJust());
212 CHECK(!GetJSFunction(env.local(), "f")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100214}
215
216
217TEST(DeoptimizeSimpleNested) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100218 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100220
221 // Test lazy deoptimization of a simple function. Have a nested function call
222 // do the deoptimization.
223 {
224 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
225 CompileRun(
226 "var count = 0;"
227 "var result = 0;"
228 "function h(x, y, z) { return x + y + z; }"
229 "function g(z) { count++; %DeoptimizeFunction(f); return z;}"
230 "function f(x,y,z) { return h(x, y, g(z)); };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100231 "result = f(1, 2, 3);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 CHECK_EQ(1, env->Global()
235 ->Get(env.local(), v8_str("count"))
236 .ToLocalChecked()
237 ->Int32Value(env.local())
238 .FromJust());
239 CHECK_EQ(6, env->Global()
240 ->Get(env.local(), v8_str("result"))
241 .ToLocalChecked()
242 ->Int32Value(env.local())
243 .FromJust());
244 CHECK(!GetJSFunction(env.local(), "f")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100246 }
247}
248
249
250TEST(DeoptimizeRecursive) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100251 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100253
254 {
255 // Test lazy deoptimization of a simple function called recursively. Call
256 // the function recursively a number of times before deoptimizing it.
257 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
258 CompileRun(
259 "var count = 0;"
260 "var calls = 0;"
261 "function g() { count++; %DeoptimizeFunction(f); }"
262 "function f(x) { calls++; if (x > 0) { f(x - 1); } else { g(); } };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100263 "f(10);");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100264 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100266
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 CHECK_EQ(1, env->Global()
268 ->Get(env.local(), v8_str("count"))
269 .ToLocalChecked()
270 ->Int32Value(env.local())
271 .FromJust());
272 CHECK_EQ(11, env->Global()
273 ->Get(env.local(), v8_str("calls"))
274 .ToLocalChecked()
275 ->Int32Value(env.local())
276 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100278
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 v8::Local<v8::Function> fun = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 env->Global()
281 ->Get(env.local(), v8_str(CcTest::isolate(), "f"))
282 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100283 CHECK(!fun.IsEmpty());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100284}
285
286
287TEST(DeoptimizeMultiple) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100288 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100290
291 {
292 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
293 CompileRun(
294 "var count = 0;"
295 "var result = 0;"
296 "function g() { count++;"
297 " %DeoptimizeFunction(f1);"
298 " %DeoptimizeFunction(f2);"
299 " %DeoptimizeFunction(f3);"
300 " %DeoptimizeFunction(f4);}"
301 "function f4(x) { g(); };"
302 "function f3(x, y, z) { f4(); return x + y + z; };"
303 "function f2(x, y) { return x + f3(y + 1, y + 1, y + 1) + y; };"
304 "function f1(x) { return f2(x + 1, x + 1) + x; };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100305 "result = f1(1);");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100306 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 CHECK_EQ(1, env->Global()
310 ->Get(env.local(), v8_str("count"))
311 .ToLocalChecked()
312 ->Int32Value(env.local())
313 .FromJust());
314 CHECK_EQ(14, env->Global()
315 ->Get(env.local(), v8_str("result"))
316 .ToLocalChecked()
317 ->Int32Value(env.local())
318 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100320}
321
322
323TEST(DeoptimizeConstructor) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100324 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100326
327 {
328 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
329 CompileRun(
330 "var count = 0;"
331 "function g() { count++;"
332 " %DeoptimizeFunction(f); }"
333 "function f() { g(); };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100334 "result = new f() instanceof f;");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100335 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100337
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 CHECK_EQ(1, env->Global()
339 ->Get(env.local(), v8_str("count"))
340 .ToLocalChecked()
341 ->Int32Value(env.local())
342 .FromJust());
343 CHECK(env->Global()
344 ->Get(env.local(), v8_str("result"))
345 .ToLocalChecked()
346 ->IsTrue());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100348
349 {
350 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
351 CompileRun(
352 "var count = 0;"
353 "var result = 0;"
354 "function g() { count++;"
355 " %DeoptimizeFunction(f); }"
356 "function f(x, y) { this.x = x; g(); this.y = y; };"
357 "result = new f(1, 2);"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100358 "result = result.x + result.y;");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100359 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100361
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 CHECK_EQ(1, env->Global()
363 ->Get(env.local(), v8_str("count"))
364 .ToLocalChecked()
365 ->Int32Value(env.local())
366 .FromJust());
367 CHECK_EQ(3, env->Global()
368 ->Get(env.local(), v8_str("result"))
369 .ToLocalChecked()
370 ->Int32Value(env.local())
371 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000372 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100373}
374
375
376TEST(DeoptimizeConstructorMultiple) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100377 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100379
380 {
381 AlwaysOptimizeAllowNativesSyntaxNoInlining options;
382 CompileRun(
383 "var count = 0;"
384 "var result = 0;"
385 "function g() { count++;"
386 " %DeoptimizeFunction(f1);"
387 " %DeoptimizeFunction(f2);"
388 " %DeoptimizeFunction(f3);"
389 " %DeoptimizeFunction(f4);}"
390 "function f4(x) { this.result = x; g(); };"
391 "function f3(x, y, z) { this.result = new f4(x + y + z).result; };"
392 "function f2(x, y) {"
393 " this.result = x + new f3(y + 1, y + 1, y + 1).result + y; };"
394 "function f1(x) { this.result = new f2(x + 1, x + 1).result + x; };"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100395 "result = new f1(1).result;");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100396 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 NonIncrementalGC(CcTest::i_isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100398
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 CHECK_EQ(1, env->Global()
400 ->Get(env.local(), v8_str("count"))
401 .ToLocalChecked()
402 ->Int32Value(env.local())
403 .FromJust());
404 CHECK_EQ(14, env->Global()
405 ->Get(env.local(), v8_str("result"))
406 .ToLocalChecked()
407 ->Int32Value(env.local())
408 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(CcTest::i_isolate()));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100410}
411
412
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413UNINITIALIZED_TEST(DeoptimizeBinaryOperationADDString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414 i::FLAG_concurrent_recompilation = false;
415 AllowNativesSyntaxNoInlining options;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 v8::Isolate::CreateParams create_params;
417 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
418 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
420 isolate->Enter();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100421 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 LocalContext env(isolate);
423 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100424
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 const char* f_source = "function f(x, y) { return x + y; };";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100426
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 {
428 // Compile function f and collect to type feedback to insert binary op
429 // stub call in the optimized code.
430 i::FLAG_prepare_always_opt = true;
431 CompileRun(
432 "var count = 0;"
433 "var result = 0;"
434 "var deopt = false;"
435 "function X() { };"
436 "X.prototype.toString = function () {"
437 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'"
438 "};");
439 CompileRun(f_source);
440 CompileRun(
441 "for (var i = 0; i < 5; i++) {"
442 " f('a+', new X());"
443 "};");
444
445 // Compile an optimized version of f.
446 i::FLAG_always_opt = true;
447 CompileRun(f_source);
448 CompileRun("f('a+', new X());");
449 CHECK(!i_isolate->use_crankshaft() ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 GetJSFunction(env.local(), "f")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451
452 // Call f and force deoptimization while processing the binary operation.
453 CompileRun(
454 "deopt = true;"
455 "var result = f('a+', new X());");
456 }
457 NonIncrementalGC(i_isolate);
458
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 CHECK(!GetJSFunction(env.local(), "f")->IsOptimized());
460 CHECK_EQ(1, env->Global()
461 ->Get(env.local(), v8_str("count"))
462 .ToLocalChecked()
463 ->Int32Value(env.local())
464 .FromJust());
465 v8::Local<v8::Value> result =
466 env->Global()->Get(env.local(), v8_str("result")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467 CHECK(result->IsString());
468 v8::String::Utf8Value utf8(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 CHECK_EQ(0, strcmp("a+an X", *utf8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100471 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472 isolate->Exit();
473 isolate->Dispose();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100474}
475
476
477static void CompileConstructorWithDeoptimizingValueOf() {
478 CompileRun("var count = 0;"
479 "var result = 0;"
480 "var deopt = false;"
481 "function X() { };"
482 "X.prototype.valueOf = function () {"
483 " if (deopt) { count++; %DeoptimizeFunction(f); } return 8"
484 "};");
485}
486
487
488static void TestDeoptimizeBinaryOpHelper(LocalContext* env,
489 const char* binary_op) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000490 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>((*env)->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100491 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000492 SNPrintF(f_source_buffer,
493 "function f(x, y) { return x %s y; };",
494 binary_op);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100495 char* f_source = f_source_buffer.start();
496
497 AllowNativesSyntaxNoInlining options;
498 // Compile function f and collect to type feedback to insert binary op stub
499 // call in the optimized code.
500 i::FLAG_prepare_always_opt = true;
501 CompileConstructorWithDeoptimizingValueOf();
502 CompileRun(f_source);
503 CompileRun("for (var i = 0; i < 5; i++) {"
504 " f(8, new X());"
505 "};");
506
507 // Compile an optimized version of f.
508 i::FLAG_always_opt = true;
509 CompileRun(f_source);
510 CompileRun("f(7, new X());");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 CHECK(!i_isolate->use_crankshaft() ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 GetJSFunction((*env).local(), "f")->IsOptimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513
514 // Call f and force deoptimization while processing the binary operation.
515 CompileRun("deopt = true;"
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100516 "var result = f(7, new X());");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 NonIncrementalGC(i_isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 CHECK(!GetJSFunction((*env).local(), "f")->IsOptimized());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100519}
520
521
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522UNINITIALIZED_TEST(DeoptimizeBinaryOperationADD) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524 v8::Isolate::CreateParams create_params;
525 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
526 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
528 isolate->Enter();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100529 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 LocalContext env(isolate);
531 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100532
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 TestDeoptimizeBinaryOpHelper(&env, "+");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000535 CHECK_EQ(1, env->Global()
536 ->Get(env.local(), v8_str("count"))
537 .ToLocalChecked()
538 ->Int32Value(env.local())
539 .FromJust());
540 CHECK_EQ(15, env->Global()
541 ->Get(env.local(), v8_str("result"))
542 .ToLocalChecked()
543 ->Int32Value(env.local())
544 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100546 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 isolate->Exit();
548 isolate->Dispose();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100549}
550
551
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552UNINITIALIZED_TEST(DeoptimizeBinaryOperationSUB) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000553 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 v8::Isolate::CreateParams create_params;
555 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
556 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
558 isolate->Enter();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100559 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000560 LocalContext env(isolate);
561 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100562
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563 TestDeoptimizeBinaryOpHelper(&env, "-");
564
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 CHECK_EQ(1, env->Global()
566 ->Get(env.local(), v8_str("count"))
567 .ToLocalChecked()
568 ->Int32Value(env.local())
569 .FromJust());
570 CHECK_EQ(-1, env->Global()
571 ->Get(env.local(), v8_str("result"))
572 .ToLocalChecked()
573 ->Int32Value(env.local())
574 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate));
576 }
577 isolate->Exit();
578 isolate->Dispose();
579}
580
581
582UNINITIALIZED_TEST(DeoptimizeBinaryOperationMUL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 v8::Isolate::CreateParams create_params;
585 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
586 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
588 isolate->Enter();
589 {
590 LocalContext env(isolate);
591 v8::HandleScope scope(env->GetIsolate());
592
593 TestDeoptimizeBinaryOpHelper(&env, "*");
594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595 CHECK_EQ(1, env->Global()
596 ->Get(env.local(), v8_str("count"))
597 .ToLocalChecked()
598 ->Int32Value(env.local())
599 .FromJust());
600 CHECK_EQ(56, env->Global()
601 ->Get(env.local(), v8_str("result"))
602 .ToLocalChecked()
603 ->Int32Value(env.local())
604 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate));
606 }
607 isolate->Exit();
608 isolate->Dispose();
609}
610
611
612UNINITIALIZED_TEST(DeoptimizeBinaryOperationDIV) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614 v8::Isolate::CreateParams create_params;
615 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
616 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
618 isolate->Enter();
619 {
620 LocalContext env(isolate);
621 v8::HandleScope scope(env->GetIsolate());
622
623 TestDeoptimizeBinaryOpHelper(&env, "/");
624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625 CHECK_EQ(1, env->Global()
626 ->Get(env.local(), v8_str("count"))
627 .ToLocalChecked()
628 ->Int32Value(env.local())
629 .FromJust());
630 CHECK_EQ(0, env->Global()
631 ->Get(env.local(), v8_str("result"))
632 .ToLocalChecked()
633 ->Int32Value(env.local())
634 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000635 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate));
636 }
637 isolate->Exit();
638 isolate->Dispose();
639}
640
641
642UNINITIALIZED_TEST(DeoptimizeBinaryOperationMOD) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644 v8::Isolate::CreateParams create_params;
645 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
646 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
648 isolate->Enter();
649 {
650 LocalContext env(isolate);
651 v8::HandleScope scope(env->GetIsolate());
652
653 TestDeoptimizeBinaryOpHelper(&env, "%");
654
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 CHECK_EQ(1, env->Global()
656 ->Get(env.local(), v8_str("count"))
657 .ToLocalChecked()
658 ->Int32Value(env.local())
659 .FromJust());
660 CHECK_EQ(7, env->Global()
661 ->Get(env.local(), v8_str("result"))
662 .ToLocalChecked()
663 ->Int32Value(env.local())
664 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate));
666 }
667 isolate->Exit();
668 isolate->Dispose();
669}
670
671
672UNINITIALIZED_TEST(DeoptimizeCompare) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 v8::Isolate::CreateParams create_params;
675 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
676 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
678 isolate->Enter();
679 {
680 LocalContext env(isolate);
681 v8::HandleScope scope(env->GetIsolate());
682
683 const char* f_source = "function f(x, y) { return x < y; };";
684
685 {
686 AllowNativesSyntaxNoInlining options;
687 // Compile function f and collect to type feedback to insert compare ic
688 // call in the optimized code.
689 i::FLAG_prepare_always_opt = true;
690 CompileRun(
691 "var count = 0;"
692 "var result = 0;"
693 "var deopt = false;"
694 "function X() { };"
695 "X.prototype.toString = function () {"
696 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'"
697 "};");
698 CompileRun(f_source);
699 CompileRun(
700 "for (var i = 0; i < 5; i++) {"
701 " f('a', new X());"
702 "};");
703
704 // Compile an optimized version of f.
705 i::FLAG_always_opt = true;
706 CompileRun(f_source);
707 CompileRun("f('a', new X());");
708 CHECK(!i_isolate->use_crankshaft() ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709 GetJSFunction(env.local(), "f")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710
711 // Call f and force deoptimization while processing the comparison.
712 CompileRun(
713 "deopt = true;"
714 "var result = f('a', new X());");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100715 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 NonIncrementalGC(i_isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 CHECK(!GetJSFunction(env.local(), "f")->IsOptimized());
719 CHECK_EQ(1, env->Global()
720 ->Get(env.local(), v8_str("count"))
721 .ToLocalChecked()
722 ->Int32Value(env.local())
723 .FromJust());
724 CHECK_EQ(true, env->Global()
725 ->Get(env.local(), v8_str("result"))
726 .ToLocalChecked()
727 ->BooleanValue(env.local())
728 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000729 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(i_isolate));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100730 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731 isolate->Exit();
732 isolate->Dispose();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100733}
734
735
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736UNINITIALIZED_TEST(DeoptimizeLoadICStoreIC) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 v8::Isolate::CreateParams create_params;
739 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
740 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000741 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
742 isolate->Enter();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100743 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744 LocalContext env(isolate);
745 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100746
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747 // Functions to generate load/store/keyed load/keyed store IC calls.
748 const char* f1_source = "function f1(x) { return x.y; };";
749 const char* g1_source = "function g1(x) { x.y = 1; };";
750 const char* f2_source = "function f2(x, y) { return x[y]; };";
751 const char* g2_source = "function g2(x, y) { x[y] = 1; };";
752
753 {
754 AllowNativesSyntaxNoInlining options;
755 // Compile functions and collect to type feedback to insert ic
756 // calls in the optimized code.
757 i::FLAG_prepare_always_opt = true;
758 CompileRun(
759 "var count = 0;"
760 "var result = 0;"
761 "var deopt = false;"
762 "function X() { };"
763 "X.prototype.__defineGetter__('y', function () {"
764 " if (deopt) { count++; %DeoptimizeFunction(f1); };"
765 " return 13;"
766 "});"
767 "X.prototype.__defineSetter__('y', function () {"
768 " if (deopt) { count++; %DeoptimizeFunction(g1); };"
769 "});"
770 "X.prototype.__defineGetter__('z', function () {"
771 " if (deopt) { count++; %DeoptimizeFunction(f2); };"
772 " return 13;"
773 "});"
774 "X.prototype.__defineSetter__('z', function () {"
775 " if (deopt) { count++; %DeoptimizeFunction(g2); };"
776 "});");
777 CompileRun(f1_source);
778 CompileRun(g1_source);
779 CompileRun(f2_source);
780 CompileRun(g2_source);
781 CompileRun(
782 "for (var i = 0; i < 5; i++) {"
783 " f1(new X());"
784 " g1(new X());"
785 " f2(new X(), 'z');"
786 " g2(new X(), 'z');"
787 "};");
788
789 // Compile an optimized version of the functions.
790 i::FLAG_always_opt = true;
791 CompileRun(f1_source);
792 CompileRun(g1_source);
793 CompileRun(f2_source);
794 CompileRun(g2_source);
795 CompileRun("f1(new X());");
796 CompileRun("g1(new X());");
797 CompileRun("f2(new X(), 'z');");
798 CompileRun("g2(new X(), 'z');");
799 if (i_isolate->use_crankshaft()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 CHECK(GetJSFunction(env.local(), "f1")->IsOptimized());
801 CHECK(GetJSFunction(env.local(), "g1")->IsOptimized());
802 CHECK(GetJSFunction(env.local(), "f2")->IsOptimized());
803 CHECK(GetJSFunction(env.local(), "g2")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 }
805
806 // Call functions and force deoptimization while processing the ics.
807 CompileRun(
808 "deopt = true;"
809 "var result = f1(new X());"
810 "g1(new X());"
811 "f2(new X(), 'z');"
812 "g2(new X(), 'z');");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100813 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 NonIncrementalGC(i_isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100815
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 CHECK(!GetJSFunction(env.local(), "f1")->IsOptimized());
817 CHECK(!GetJSFunction(env.local(), "g1")->IsOptimized());
818 CHECK(!GetJSFunction(env.local(), "f2")->IsOptimized());
819 CHECK(!GetJSFunction(env.local(), "g2")->IsOptimized());
820 CHECK_EQ(4, env->Global()
821 ->Get(env.local(), v8_str("count"))
822 .ToLocalChecked()
823 ->Int32Value(env.local())
824 .FromJust());
825 CHECK_EQ(13, env->Global()
826 ->Get(env.local(), v8_str("result"))
827 .ToLocalChecked()
828 ->Int32Value(env.local())
829 .FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100830 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831 isolate->Exit();
832 isolate->Dispose();
833}
Ben Murdochb0fe1622011-05-05 13:52:32 +0100834
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835
836UNINITIALIZED_TEST(DeoptimizeLoadICStoreICNested) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837 i::FLAG_concurrent_recompilation = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000838 v8::Isolate::CreateParams create_params;
839 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
840 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
842 isolate->Enter();
843 {
844 LocalContext env(isolate);
845 v8::HandleScope scope(env->GetIsolate());
846
847 // Functions to generate load/store/keyed load/keyed store IC calls.
848 const char* f1_source = "function f1(x) { return x.y; };";
849 const char* g1_source = "function g1(x) { x.y = 1; };";
850 const char* f2_source = "function f2(x, y) { return x[y]; };";
851 const char* g2_source = "function g2(x, y) { x[y] = 1; };";
852
853 {
854 AllowNativesSyntaxNoInlining options;
855 // Compile functions and collect to type feedback to insert ic
856 // calls in the optimized code.
857 i::FLAG_prepare_always_opt = true;
858 CompileRun(
859 "var count = 0;"
860 "var result = 0;"
861 "var deopt = false;"
862 "function X() { };"
863 "X.prototype.__defineGetter__('y', function () {"
864 " g1(this);"
865 " return 13;"
866 "});"
867 "X.prototype.__defineSetter__('y', function () {"
868 " f2(this, 'z');"
869 "});"
870 "X.prototype.__defineGetter__('z', function () {"
871 " g2(this, 'z');"
872 "});"
873 "X.prototype.__defineSetter__('z', function () {"
874 " if (deopt) {"
875 " count++;"
876 " %DeoptimizeFunction(f1);"
877 " %DeoptimizeFunction(g1);"
878 " %DeoptimizeFunction(f2);"
879 " %DeoptimizeFunction(g2); };"
880 "});");
881 CompileRun(f1_source);
882 CompileRun(g1_source);
883 CompileRun(f2_source);
884 CompileRun(g2_source);
885 CompileRun(
886 "for (var i = 0; i < 5; i++) {"
887 " f1(new X());"
888 " g1(new X());"
889 " f2(new X(), 'z');"
890 " g2(new X(), 'z');"
891 "};");
892
893 // Compile an optimized version of the functions.
894 i::FLAG_always_opt = true;
895 CompileRun(f1_source);
896 CompileRun(g1_source);
897 CompileRun(f2_source);
898 CompileRun(g2_source);
899 CompileRun("f1(new X());");
900 CompileRun("g1(new X());");
901 CompileRun("f2(new X(), 'z');");
902 CompileRun("g2(new X(), 'z');");
903 if (i_isolate->use_crankshaft()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000904 CHECK(GetJSFunction(env.local(), "f1")->IsOptimized());
905 CHECK(GetJSFunction(env.local(), "g1")->IsOptimized());
906 CHECK(GetJSFunction(env.local(), "f2")->IsOptimized());
907 CHECK(GetJSFunction(env.local(), "g2")->IsOptimized());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 }
909
910 // Call functions and force deoptimization while processing the ics.
911 CompileRun(
912 "deopt = true;"
913 "var result = f1(new X());");
914 }
915 NonIncrementalGC(i_isolate);
916
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000917 CHECK(!GetJSFunction(env.local(), "f1")->IsOptimized());
918 CHECK(!GetJSFunction(env.local(), "g1")->IsOptimized());
919 CHECK(!GetJSFunction(env.local(), "f2")->IsOptimized());
920 CHECK(!GetJSFunction(env.local(), "g2")->IsOptimized());
921 CHECK_EQ(1, env->Global()
922 ->Get(env.local(), v8_str("count"))
923 .ToLocalChecked()
924 ->Int32Value(env.local())
925 .FromJust());
926 CHECK_EQ(13, env->Global()
927 ->Get(env.local(), v8_str("result"))
928 .ToLocalChecked()
929 ->Int32Value(env.local())
930 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931 }
932 isolate->Exit();
933 isolate->Dispose();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100934}