blob: c28295857ea38e92521915820fab86f06f4341dd [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "test/cctest/compiler/function-tester.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007namespace v8 {
8namespace internal {
9namespace compiler {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010
11TEST(SimpleCall) {
12 FunctionTester T("(function(foo,a) { return foo(a); })");
13 Handle<JSFunction> foo = T.NewFunction("(function(a) { return a; })");
14
15 T.CheckCall(T.Val(3), foo, T.Val(3));
16 T.CheckCall(T.Val(3.1), foo, T.Val(3.1));
17 T.CheckCall(foo, foo, foo);
18 T.CheckCall(T.Val("Abba"), foo, T.Val("Abba"));
19}
20
21
22TEST(SimpleCall2) {
23 FunctionTester T("(function(foo,a) { return foo(a); })");
Ben Murdoch097c5b22016-05-18 11:27:45 +010024 FunctionTester U("(function(a) { return a; })");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025
Ben Murdoch097c5b22016-05-18 11:27:45 +010026 T.CheckCall(T.Val(3), U.function, T.Val(3));
27 T.CheckCall(T.Val(3.1), U.function, T.Val(3.1));
28 T.CheckCall(U.function, U.function, U.function);
29 T.CheckCall(T.Val("Abba"), U.function, T.Val("Abba"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030}
31
32
33TEST(ConstCall) {
34 FunctionTester T("(function(foo,a) { return foo(a,3); })");
Ben Murdoch097c5b22016-05-18 11:27:45 +010035 FunctionTester U("(function(a,b) { return a + b; })");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036
Ben Murdoch097c5b22016-05-18 11:27:45 +010037 T.CheckCall(T.Val(6), U.function, T.Val(3));
38 T.CheckCall(T.Val(6.1), U.function, T.Val(3.1));
39 T.CheckCall(T.Val("function (a,b) { return a + b; }3"), U.function,
40 U.function);
41 T.CheckCall(T.Val("Abba3"), U.function, T.Val("Abba"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042}
43
44
45TEST(ConstCall2) {
46 FunctionTester T("(function(foo,a) { return foo(a,\"3\"); })");
Ben Murdoch097c5b22016-05-18 11:27:45 +010047 FunctionTester U("(function(a,b) { return a + b; })");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048
Ben Murdoch097c5b22016-05-18 11:27:45 +010049 T.CheckCall(T.Val("33"), U.function, T.Val(3));
50 T.CheckCall(T.Val("3.13"), U.function, T.Val(3.1));
51 T.CheckCall(T.Val("function (a,b) { return a + b; }3"), U.function,
52 U.function);
53 T.CheckCall(T.Val("Abba3"), U.function, T.Val("Abba"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054}
55
56
57TEST(PropertyNamedCall) {
58 FunctionTester T("(function(a,b) { return a.foo(b,23); })");
59 CompileRun("function foo(y,z) { return this.x + y + z; }");
60
61 T.CheckCall(T.Val(32), T.NewObject("({ foo:foo, x:4 })"), T.Val(5));
62 T.CheckCall(T.Val("xy23"), T.NewObject("({ foo:foo, x:'x' })"), T.Val("y"));
63 T.CheckCall(T.nan(), T.NewObject("({ foo:foo, y:0 })"), T.Val(3));
64}
65
66
67TEST(PropertyKeyedCall) {
68 FunctionTester T("(function(a,b) { var f = 'foo'; return a[f](b,23); })");
69 CompileRun("function foo(y,z) { return this.x + y + z; }");
70
71 T.CheckCall(T.Val(32), T.NewObject("({ foo:foo, x:4 })"), T.Val(5));
72 T.CheckCall(T.Val("xy23"), T.NewObject("({ foo:foo, x:'x' })"), T.Val("y"));
73 T.CheckCall(T.nan(), T.NewObject("({ foo:foo, y:0 })"), T.Val(3));
74}
75
76
77TEST(GlobalCall) {
78 FunctionTester T("(function(a,b) { return foo(a,b); })");
79 CompileRun("function foo(a,b) { return a + b + this.c; }");
80 CompileRun("var c = 23;");
81
82 T.CheckCall(T.Val(32), T.Val(4), T.Val(5));
83 T.CheckCall(T.Val("xy23"), T.Val("x"), T.Val("y"));
84 T.CheckCall(T.nan(), T.undefined(), T.Val(3));
85}
86
87
88TEST(LookupCall) {
89 FunctionTester T("(function(a,b) { with (a) { return foo(a,b); } })");
90
91 CompileRun("function f1(a,b) { return a.val + b; }");
92 T.CheckCall(T.Val(5), T.NewObject("({ foo:f1, val:2 })"), T.Val(3));
93 T.CheckCall(T.Val("xy"), T.NewObject("({ foo:f1, val:'x' })"), T.Val("y"));
94
95 CompileRun("function f2(a,b) { return this.val + b; }");
96 T.CheckCall(T.Val(9), T.NewObject("({ foo:f2, val:4 })"), T.Val(5));
97 T.CheckCall(T.Val("xy"), T.NewObject("({ foo:f2, val:'x' })"), T.Val("y"));
98}
99
100
101TEST(MismatchCallTooFew) {
102 FunctionTester T("(function(a,b) { return foo(a,b); })");
103 CompileRun("function foo(a,b,c) { return a + b + c; }");
104
105 T.CheckCall(T.nan(), T.Val(23), T.Val(42));
106 T.CheckCall(T.nan(), T.Val(4.2), T.Val(2.3));
107 T.CheckCall(T.Val("abundefined"), T.Val("a"), T.Val("b"));
108}
109
110
111TEST(MismatchCallTooMany) {
112 FunctionTester T("(function(a,b) { return foo(a,b); })");
113 CompileRun("function foo(a) { return a; }");
114
115 T.CheckCall(T.Val(23), T.Val(23), T.Val(42));
116 T.CheckCall(T.Val(4.2), T.Val(4.2), T.Val(2.3));
117 T.CheckCall(T.Val("a"), T.Val("a"), T.Val("b"));
118}
119
120
121TEST(ConstructorCall) {
122 FunctionTester T("(function(a,b) { return new foo(a,b).value; })");
123 CompileRun("function foo(a,b) { return { value: a + b + this.c }; }");
124 CompileRun("foo.prototype.c = 23;");
125
126 T.CheckCall(T.Val(32), T.Val(4), T.Val(5));
127 T.CheckCall(T.Val("xy23"), T.Val("x"), T.Val("y"));
128 T.CheckCall(T.nan(), T.undefined(), T.Val(3));
129}
130
131
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132TEST(RuntimeCallCPP2) {
133 FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 FunctionTester T("(function(a,b) { return %NumberImul(a, b); })");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 T.CheckCall(T.Val(2730), T.Val(42), T.Val(65));
137 T.CheckCall(T.Val(798), T.Val(42), T.Val(19));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138}
139
140
141TEST(RuntimeCallInline) {
142 FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 FunctionTester T("(function(a) { return %_IsJSReceiver(a); })");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144
145 T.CheckCall(T.false_value(), T.Val(23), T.undefined());
146 T.CheckCall(T.false_value(), T.Val(4.2), T.undefined());
147 T.CheckCall(T.false_value(), T.Val("str"), T.undefined());
148 T.CheckCall(T.false_value(), T.true_value(), T.undefined());
149 T.CheckCall(T.false_value(), T.false_value(), T.undefined());
150 T.CheckCall(T.false_value(), T.undefined(), T.undefined());
151 T.CheckCall(T.true_value(), T.NewObject("({})"), T.undefined());
152 T.CheckCall(T.true_value(), T.NewObject("([])"), T.undefined());
153}
154
155
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156TEST(EvalCall) {
157 FunctionTester T("(function(a,b) { return eval(a); })");
158 Handle<JSObject> g(T.function->context()->global_object()->global_proxy());
159
160 T.CheckCall(T.Val(23), T.Val("17 + 6"), T.undefined());
161 T.CheckCall(T.Val("'Y'; a"), T.Val("'Y'; a"), T.Val("b-val"));
162 T.CheckCall(T.Val("b-val"), T.Val("'Y'; b"), T.Val("b-val"));
163 T.CheckCall(g, T.Val("this"), T.undefined());
164 T.CheckCall(g, T.Val("'use strict'; this"), T.undefined());
165
166 CompileRun("eval = function(x) { return x; }");
167 T.CheckCall(T.Val("17 + 6"), T.Val("17 + 6"), T.undefined());
168
169 CompileRun("eval = function(x) { return this; }");
170 T.CheckCall(g, T.Val("17 + 6"), T.undefined());
171
172 CompileRun("eval = function(x) { 'use strict'; return this; }");
173 T.CheckCall(T.undefined(), T.Val("17 + 6"), T.undefined());
174}
175
176
177TEST(ReceiverPatching) {
178 // TODO(turbofan): Note that this test only checks that the function prologue
179 // patches an undefined receiver to the global receiver. If this starts to
180 // fail once we fix the calling protocol, just remove this test.
181 FunctionTester T("(function(a) { return this; })");
182 Handle<JSObject> g(T.function->context()->global_object()->global_proxy());
183 T.CheckCall(g, T.undefined());
184}
185
186
187TEST(CallEval) {
188 FunctionTester T(
189 "var x = 42;"
190 "(function () {"
191 "function bar() { return eval('x') };"
192 "return bar;"
193 "})();");
194
195 T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
196}
197
198
199TEST(ContextLoadedFromActivation) {
200 const char* script =
201 "var x = 42;"
202 "(function() {"
203 " return function () { return x };"
204 "})()";
205
206 // Disable context specialization.
207 FunctionTester T(script);
208 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
209 v8::Context::Scope scope(context);
210 v8::Local<v8::Value> value = CompileRun(script);
211 i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
212 i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
213 jsfun->set_code(T.function->code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 jsfun->set_shared(T.function->shared());
215 CHECK(context->Global()
216 ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
217 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 CompileRun("var x = 24;");
219 ExpectInt32("foo();", 24);
220}
221
222
223TEST(BuiltinLoadedFromActivation) {
224 const char* script =
225 "var x = 42;"
226 "(function() {"
227 " return function () { return this; };"
228 "})()";
229
230 // Disable context specialization.
231 FunctionTester T(script);
232 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
233 v8::Context::Scope scope(context);
234 v8::Local<v8::Value> value = CompileRun(script);
235 i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
236 i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
237 jsfun->set_code(T.function->code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 jsfun->set_shared(T.function->shared());
239 CHECK(context->Global()
240 ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
241 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 CompileRun("var x = 24;");
243 ExpectObject("foo()", context->Global());
244}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245
246} // namespace compiler
247} // namespace internal
248} // namespace v8