13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without
3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are
4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met:
5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions of source code must retain the above copyright
7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       notice, this list of conditions and the following disclaimer.
8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions in binary form must reproduce the above
9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       copyright notice, this list of conditions and the following
10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       disclaimer in the documentation and/or other materials provided
11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       with the distribution.
12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       contributors may be used to endorse or promote products derived
14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       from this software without specific prior written permission.
15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include <stdlib.h>
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "v8.h"
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "api.h"
3344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "cctest.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "compilation-cache.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "debug.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h"
3744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "isolate.h"
38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "platform.h"
39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "stub-cache.h"
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochusing ::v8::internal::Deoptimizer;
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochusing ::v8::internal::EmbeddedVector;
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::internal::Handle;
4444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::internal::Isolate;
4544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::internal::JSFunction;
46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochusing ::v8::internal::OS;
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockusing ::v8::internal::Object;
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Size of temp buffer for formatting small strings.
50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define SMALL_STRING_BUFFER_SIZE 80
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Utility class to set --allow-natives-syntax --always-opt and --nouse-inlining
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// when constructed and return to their default state when destroyed.
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass AlwaysOptimizeAllowNativesSyntaxNoInlining {
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AlwaysOptimizeAllowNativesSyntaxNoInlining()
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : always_opt_(i::FLAG_always_opt),
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        allow_natives_syntax_(i::FLAG_allow_natives_syntax),
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        use_inlining_(i::FLAG_use_inlining) {
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_always_opt = true;
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_allow_natives_syntax = true;
62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_use_inlining = false;
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~AlwaysOptimizeAllowNativesSyntaxNoInlining() {
66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_allow_natives_syntax = allow_natives_syntax_;
67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_always_opt = always_opt_;
68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_use_inlining = use_inlining_;
69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool always_opt_;
73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool allow_natives_syntax_;
74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool use_inlining_;
75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Utility class to set --allow-natives-syntax and --nouse-inlining when
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// constructed and return to their default state when destroyed.
80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass AllowNativesSyntaxNoInlining {
81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AllowNativesSyntaxNoInlining()
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : allow_natives_syntax_(i::FLAG_allow_natives_syntax),
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        use_inlining_(i::FLAG_use_inlining) {
85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_allow_natives_syntax = true;
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_use_inlining = false;
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ~AllowNativesSyntaxNoInlining() {
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_allow_natives_syntax = allow_natives_syntax_;
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_use_inlining = use_inlining_;
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool allow_natives_syntax_;
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool use_inlining_;
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Abort any ongoing incremental marking to make sure that all weak global
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// handle callbacks are processed.
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void NonIncrementalGC() {
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
107053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Blockstatic Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj,
108053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block                                        const char* property_name) {
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Local<v8::Function> fun =
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name)));
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return v8::Utils::OpenHandle(*fun);
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeSimple) {
116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Test lazy deoptimization of a simple function.
120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function h() { %DeoptimizeFunction(f); }"
125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g() { count++; h(); }"
126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f() { g(); };"
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f();");
128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Test lazy deoptimization of a simple function. Call the function after the
136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // deoptimization while it is still activated further down the stack.
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g() { count++; %DeoptimizeFunction(f); f(false); }"
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f(x) { if (x) { g(); } else { return } };"
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f(true);");
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeSimpleWithArguments) {
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Test lazy deoptimization of a simple function with some arguments.
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function h(x) { %DeoptimizeFunction(f); }"
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g(x, y) { count++; h(x); }"
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f(x, y, z) { g(1,x); y+z; };"
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f(1, \"2\", false);");
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Test lazy deoptimization of a simple function with some arguments. Call the
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // function after the deoptimization while it is still activated further down
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the stack.
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g(x, y) { count++; %DeoptimizeFunction(f); f(false, 1, y); }"
181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f(x, y, z) { if (x) { g(x, y); } else { return y + z; } };"
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f(true, 1, \"2\");");
183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeSimpleNested) {
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Test lazy deoptimization of a simple function. Have a nested function call
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // do the deoptimization.
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var result = 0;"
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function h(x, y, z) { return x + y + z; }"
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g(z) { count++; %DeoptimizeFunction(f); return z;}"
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f(x,y,z) { return h(x, y, g(z)); };"
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "result = f(1, 2, 3);");
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    NonIncrementalGC();
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(6, env->Global()->Get(v8_str("result"))->Int32Value());
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
21244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeRecursive) {
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Test lazy deoptimization of a simple function called recursively. Call
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // the function recursively a number of times before deoptimizing it.
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var calls = 0;"
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g() { count++; %DeoptimizeFunction(f); }"
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f(x) { calls++; if (x > 0) { f(x - 1); } else { g(); } };"
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "f(10);");
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(11, env->Global()->Get(v8_str("calls"))->Int32Value());
23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Local<v8::Function> fun =
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!fun.IsEmpty());
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeMultiple) {
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var result = 0;"
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g() { count++;"
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f1);"
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f2);"
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f3);"
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f4);}"
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f4(x) { g(); };"
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f3(x, y, z) { f4(); return x + y + z; };"
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f2(x, y) { return x + f3(y + 1, y + 1, y + 1) + y; };"
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f1(x) { return f2(x + 1, x + 1) + x; };"
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "result = f1(1);");
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value());
26844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeConstructor) {
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g() { count++;"
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f); }"
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f() {  g(); };"
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "result = new f() instanceof f;");
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(env->Global()->Get(v8_str("result"))->IsTrue());
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var result = 0;"
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g() { count++;"
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f); }"
298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f(x, y) { this.x = x; g(); this.y = y; };"
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "result = new f(1, 2);"
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "result = result.x + result.y;");
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(3, env->Global()->Get(v8_str("result"))->Int32Value());
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeConstructorMultiple) {
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AlwaysOptimizeAllowNativesSyntaxNoInlining options;
316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(
317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var count = 0;"
318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "var result = 0;"
319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function g() { count++;"
320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f1);"
321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f2);"
322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f3);"
323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "               %DeoptimizeFunction(f4);}"
324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f4(x) { this.result = x; g(); };"
325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f3(x, y, z) { this.result = new f4(x + y + z).result; };"
326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f2(x, y) {"
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "    this.result = x + new f3(y + 1, y + 1, y + 1).result + y; };"
328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        "function f1(x) { this.result = new f2(x + 1, x + 1).result + x; };"
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        "result = new f1(1).result;");
330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(14, env->Global()->Get(v8_str("result"))->Int32Value());
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeBinaryOperationADDString) {
340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* f_source = "function f(x, y) { return x + y; };";
344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AllowNativesSyntaxNoInlining options;
347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile function f and collect to type feedback to insert binary op stub
348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // call in the optimized code.
349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_prepare_always_opt = true;
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("var count = 0;"
351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var result = 0;"
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var deopt = false;"
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "function X() { };"
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.toString = function () {"
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'"
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "};");
357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f_source);
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("for (var i = 0; i < 5; i++) {"
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  f('a+', new X());"
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "};");
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile an optimized version of f.
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_always_opt = true;
364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f_source);
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f('a+', new X());");
366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK(!i::V8::UseCrankshaft() ||
367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          GetJSFunction(env->Global(), "f")->IsOptimized());
368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call f and force deoptimization while processing the binary operation.
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("deopt = true;"
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               "var result = f('a+', new X());");
372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::Handle<v8::Value> result = env->Global()->Get(v8_str("result"));
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(result->IsString());
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::String::AsciiValue ascii(result);
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ("a+an X", *ascii);
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void CompileConstructorWithDeoptimizingValueOf() {
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("var count = 0;"
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "var result = 0;"
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "var deopt = false;"
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "function X() { };"
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "X.prototype.valueOf = function () {"
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "  if (deopt) { count++; %DeoptimizeFunction(f); } return 8"
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "};");
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic void TestDeoptimizeBinaryOpHelper(LocalContext* env,
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         const char* binary_op) {
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer;
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  OS::SNPrintF(f_source_buffer,
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "function f(x, y) { return x %s y; };",
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               binary_op);
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  char* f_source = f_source_buffer.start();
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AllowNativesSyntaxNoInlining options;
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compile function f and collect to type feedback to insert binary op stub
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // call in the optimized code.
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  i::FLAG_prepare_always_opt = true;
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileConstructorWithDeoptimizingValueOf();
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun(f_source);
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("for (var i = 0; i < 5; i++) {"
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "  f(8, new X());"
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             "};");
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compile an optimized version of f.
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  i::FLAG_always_opt = true;
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun(f_source);
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("f(7, new X());");
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!i::V8::UseCrankshaft() ||
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        GetJSFunction((*env)->Global(), "f")->IsOptimized());
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Call f and force deoptimization while processing the binary operation.
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CompileRun("deopt = true;"
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "var result = f(7, new X());");
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction((*env)->Global(), "f")->IsOptimized());
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeBinaryOperationADD) {
430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestDeoptimizeBinaryOpHelper(&env, "+");
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(15, env->Global()->Get(v8_str("result"))->Int32Value());
43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeBinaryOperationSUB) {
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestDeoptimizeBinaryOpHelper(&env, "-");
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(-1, env->Global()->Get(v8_str("result"))->Int32Value());
44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeBinaryOperationMUL) {
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestDeoptimizeBinaryOpHelper(&env, "*");
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(56, env->Global()->Get(v8_str("result"))->Int32Value());
46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeBinaryOperationDIV) {
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestDeoptimizeBinaryOpHelper(&env, "/");
470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(0, env->Global()->Get(v8_str("result"))->Int32Value());
47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeBinaryOperationMOD) {
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestDeoptimizeBinaryOpHelper(&env, "%");
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(7, env->Global()->Get(v8_str("result"))->Int32Value());
48544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeCompare) {
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* f_source = "function f(x, y) { return x < y; };";
494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AllowNativesSyntaxNoInlining options;
497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile function f and collect to type feedback to insert compare ic
498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // call in the optimized code.
499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_prepare_always_opt = true;
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("var count = 0;"
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var result = 0;"
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var deopt = false;"
503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "function X() { };"
504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.toString = function () {"
505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'"
506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "};");
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f_source);
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("for (var i = 0; i < 5; i++) {"
509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  f('a', new X());"
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "};");
511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile an optimized version of f.
513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_always_opt = true;
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f_source);
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f('a', new X());");
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK(!i::V8::UseCrankshaft() ||
517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          GetJSFunction(env->Global(), "f")->IsOptimized());
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call f and force deoptimization while processing the comparison.
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("deopt = true;"
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               "var result = f('a', new X());");
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f")->IsOptimized());
526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(true, env->Global()->Get(v8_str("result"))->BooleanValue());
52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeLoadICStoreIC) {
533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Functions to generate load/store/keyed load/keyed store IC calls.
537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* f1_source = "function f1(x) { return x.y; };";
538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* g1_source = "function g1(x) { x.y = 1; };";
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* f2_source = "function f2(x, y) { return x[y]; };";
540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* g2_source = "function g2(x, y) { x[y] = 1; };";
541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AllowNativesSyntaxNoInlining options;
544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile functions and collect to type feedback to insert ic
545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // calls in the optimized code.
546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_prepare_always_opt = true;
547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("var count = 0;"
548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var result = 0;"
549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var deopt = false;"
550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "function X() { };"
551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineGetter__('y', function () {"
552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  if (deopt) { count++; %DeoptimizeFunction(f1); };"
553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  return 13;"
554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});"
555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineSetter__('y', function () {"
556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  if (deopt) { count++; %DeoptimizeFunction(g1); };"
557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});"
558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineGetter__('z', function () {"
559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  if (deopt) { count++; %DeoptimizeFunction(f2); };"
560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  return 13;"
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});"
562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineSetter__('z', function () {"
563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  if (deopt) { count++; %DeoptimizeFunction(g2); };"
564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});");
565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f1_source);
566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g1_source);
567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f2_source);
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g2_source);
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("for (var i = 0; i < 5; i++) {"
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  f1(new X());"
571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  g1(new X());"
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  f2(new X(), 'z');"
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  g2(new X(), 'z');"
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "};");
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile an optimized version of the functions.
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_always_opt = true;
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f1_source);
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g1_source);
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f2_source);
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g2_source);
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f1(new X());");
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("g1(new X());");
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f2(new X(), 'z');");
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("g2(new X(), 'z');");
586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i::V8::UseCrankshaft()) {
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized());
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized());
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized());
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized());
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call functions and force deoptimization while processing the ics.
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("deopt = true;"
595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var result = f1(new X());"
596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "g1(new X());"
597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "f2(new X(), 'z');"
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               "g2(new X(), 'z');");
599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized());
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized());
604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized());
605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized());
606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(4, env->Global()->Get(v8_str("count"))->Int32Value());
607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value());
60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(DeoptimizeLoadICStoreICNested) {
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Functions to generate load/store/keyed load/keyed store IC calls.
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* f1_source = "function f1(x) { return x.y; };";
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* g1_source = "function g1(x) { x.y = 1; };";
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* f2_source = "function f2(x, y) { return x[y]; };";
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const char* g2_source = "function g2(x, y) { x[y] = 1; };";
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AllowNativesSyntaxNoInlining options;
624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile functions and collect to type feedback to insert ic
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // calls in the optimized code.
626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_prepare_always_opt = true;
627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("var count = 0;"
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var result = 0;"
629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "var deopt = false;"
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "function X() { };"
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineGetter__('y', function () {"
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  g1(this);"
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  return 13;"
634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});"
635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineSetter__('y', function () {"
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  f2(this, 'z');"
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});"
638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineGetter__('z', function () {"
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  g2(this, 'z');"
640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});"
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "X.prototype.__defineSetter__('z', function () {"
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  if (deopt) {"
643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "    count++;"
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "    %DeoptimizeFunction(f1);"
645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "    %DeoptimizeFunction(g1);"
646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "    %DeoptimizeFunction(f2);"
647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "    %DeoptimizeFunction(g2); };"
648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "});");
649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f1_source);
650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g1_source);
651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f2_source);
652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g2_source);
653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("for (var i = 0; i < 5; i++) {"
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  f1(new X());"
655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  g1(new X());"
656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  f2(new X(), 'z');"
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "  g2(new X(), 'z');"
658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               "};");
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Compile an optimized version of the functions.
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    i::FLAG_always_opt = true;
662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f1_source);
663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g1_source);
664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(f2_source);
665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun(g2_source);
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f1(new X());");
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("g1(new X());");
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("f2(new X(), 'z');");
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("g2(new X(), 'z');");
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (i::V8::UseCrankshaft()) {
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "f1")->IsOptimized());
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "g1")->IsOptimized());
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "f2")->IsOptimized());
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CHECK(GetJSFunction(env->Global(), "g2")->IsOptimized());
675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Call functions and force deoptimization while processing the ics.
678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CompileRun("deopt = true;"
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               "var result = f1(new X());");
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  NonIncrementalGC();
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f1")->IsOptimized());
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "g1")->IsOptimized());
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "f2")->IsOptimized());
686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!GetJSFunction(env->Global(), "g2")->IsOptimized());
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(1, env->Global()->Get(v8_str("count"))->Int32Value());
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(13, env->Global()->Get(v8_str("result"))->Int32Value());
68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
691