1 // 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
5 #include "test/cctest/compiler/function-tester.h"
6
7 namespace v8 {
8 namespace internal {
9 namespace compiler {
10
TEST(SimpleCall)11 TEST(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
TEST(SimpleCall2)22 TEST(SimpleCall2) {
23 FunctionTester T("(function(foo,a) { return foo(a); })");
24 Handle<JSFunction> foo = T.NewFunction("(function(a) { return a; })");
25 T.Compile(foo);
26
27 T.CheckCall(T.Val(3), foo, T.Val(3));
28 T.CheckCall(T.Val(3.1), foo, T.Val(3.1));
29 T.CheckCall(foo, foo, foo);
30 T.CheckCall(T.Val("Abba"), foo, T.Val("Abba"));
31 }
32
33
TEST(ConstCall)34 TEST(ConstCall) {
35 FunctionTester T("(function(foo,a) { return foo(a,3); })");
36 Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
37 T.Compile(foo);
38
39 T.CheckCall(T.Val(6), foo, T.Val(3));
40 T.CheckCall(T.Val(6.1), foo, T.Val(3.1));
41 T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
42 T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
43 }
44
45
TEST(ConstCall2)46 TEST(ConstCall2) {
47 FunctionTester T("(function(foo,a) { return foo(a,\"3\"); })");
48 Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
49 T.Compile(foo);
50
51 T.CheckCall(T.Val("33"), foo, T.Val(3));
52 T.CheckCall(T.Val("3.13"), foo, T.Val(3.1));
53 T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
54 T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
55 }
56
57
TEST(PropertyNamedCall)58 TEST(PropertyNamedCall) {
59 FunctionTester T("(function(a,b) { return a.foo(b,23); })");
60 CompileRun("function foo(y,z) { return this.x + y + z; }");
61
62 T.CheckCall(T.Val(32), T.NewObject("({ foo:foo, x:4 })"), T.Val(5));
63 T.CheckCall(T.Val("xy23"), T.NewObject("({ foo:foo, x:'x' })"), T.Val("y"));
64 T.CheckCall(T.nan(), T.NewObject("({ foo:foo, y:0 })"), T.Val(3));
65 }
66
67
TEST(PropertyKeyedCall)68 TEST(PropertyKeyedCall) {
69 FunctionTester T("(function(a,b) { var f = 'foo'; return a[f](b,23); })");
70 CompileRun("function foo(y,z) { return this.x + y + z; }");
71
72 T.CheckCall(T.Val(32), T.NewObject("({ foo:foo, x:4 })"), T.Val(5));
73 T.CheckCall(T.Val("xy23"), T.NewObject("({ foo:foo, x:'x' })"), T.Val("y"));
74 T.CheckCall(T.nan(), T.NewObject("({ foo:foo, y:0 })"), T.Val(3));
75 }
76
77
TEST(GlobalCall)78 TEST(GlobalCall) {
79 FunctionTester T("(function(a,b) { return foo(a,b); })");
80 CompileRun("function foo(a,b) { return a + b + this.c; }");
81 CompileRun("var c = 23;");
82
83 T.CheckCall(T.Val(32), T.Val(4), T.Val(5));
84 T.CheckCall(T.Val("xy23"), T.Val("x"), T.Val("y"));
85 T.CheckCall(T.nan(), T.undefined(), T.Val(3));
86 }
87
88
TEST(LookupCall)89 TEST(LookupCall) {
90 FunctionTester T("(function(a,b) { with (a) { return foo(a,b); } })");
91
92 CompileRun("function f1(a,b) { return a.val + b; }");
93 T.CheckCall(T.Val(5), T.NewObject("({ foo:f1, val:2 })"), T.Val(3));
94 T.CheckCall(T.Val("xy"), T.NewObject("({ foo:f1, val:'x' })"), T.Val("y"));
95
96 CompileRun("function f2(a,b) { return this.val + b; }");
97 T.CheckCall(T.Val(9), T.NewObject("({ foo:f2, val:4 })"), T.Val(5));
98 T.CheckCall(T.Val("xy"), T.NewObject("({ foo:f2, val:'x' })"), T.Val("y"));
99 }
100
101
TEST(MismatchCallTooFew)102 TEST(MismatchCallTooFew) {
103 FunctionTester T("(function(a,b) { return foo(a,b); })");
104 CompileRun("function foo(a,b,c) { return a + b + c; }");
105
106 T.CheckCall(T.nan(), T.Val(23), T.Val(42));
107 T.CheckCall(T.nan(), T.Val(4.2), T.Val(2.3));
108 T.CheckCall(T.Val("abundefined"), T.Val("a"), T.Val("b"));
109 }
110
111
TEST(MismatchCallTooMany)112 TEST(MismatchCallTooMany) {
113 FunctionTester T("(function(a,b) { return foo(a,b); })");
114 CompileRun("function foo(a) { return a; }");
115
116 T.CheckCall(T.Val(23), T.Val(23), T.Val(42));
117 T.CheckCall(T.Val(4.2), T.Val(4.2), T.Val(2.3));
118 T.CheckCall(T.Val("a"), T.Val("a"), T.Val("b"));
119 }
120
121
TEST(ConstructorCall)122 TEST(ConstructorCall) {
123 FunctionTester T("(function(a,b) { return new foo(a,b).value; })");
124 CompileRun("function foo(a,b) { return { value: a + b + this.c }; }");
125 CompileRun("foo.prototype.c = 23;");
126
127 T.CheckCall(T.Val(32), T.Val(4), T.Val(5));
128 T.CheckCall(T.Val("xy23"), T.Val("x"), T.Val("y"));
129 T.CheckCall(T.nan(), T.undefined(), T.Val(3));
130 }
131
132
133 // TODO(titzer): factor these out into test-runtime-calls.cc
TEST(RuntimeCallCPP2)134 TEST(RuntimeCallCPP2) {
135 FLAG_allow_natives_syntax = true;
136 FunctionTester T("(function(a,b) { return %NumberImul(a, b); })");
137
138 T.CheckCall(T.Val(2730), T.Val(42), T.Val(65));
139 T.CheckCall(T.Val(798), T.Val(42), T.Val(19));
140 }
141
142
TEST(RuntimeCallInline)143 TEST(RuntimeCallInline) {
144 FLAG_allow_natives_syntax = true;
145 FunctionTester T("(function(a) { return %_IsJSReceiver(a); })");
146
147 T.CheckCall(T.false_value(), T.Val(23), T.undefined());
148 T.CheckCall(T.false_value(), T.Val(4.2), T.undefined());
149 T.CheckCall(T.false_value(), T.Val("str"), T.undefined());
150 T.CheckCall(T.false_value(), T.true_value(), T.undefined());
151 T.CheckCall(T.false_value(), T.false_value(), T.undefined());
152 T.CheckCall(T.false_value(), T.undefined(), T.undefined());
153 T.CheckCall(T.true_value(), T.NewObject("({})"), T.undefined());
154 T.CheckCall(T.true_value(), T.NewObject("([])"), T.undefined());
155 }
156
157
TEST(EvalCall)158 TEST(EvalCall) {
159 FunctionTester T("(function(a,b) { return eval(a); })");
160 Handle<JSObject> g(T.function->context()->global_object()->global_proxy());
161
162 T.CheckCall(T.Val(23), T.Val("17 + 6"), T.undefined());
163 T.CheckCall(T.Val("'Y'; a"), T.Val("'Y'; a"), T.Val("b-val"));
164 T.CheckCall(T.Val("b-val"), T.Val("'Y'; b"), T.Val("b-val"));
165 T.CheckCall(g, T.Val("this"), T.undefined());
166 T.CheckCall(g, T.Val("'use strict'; this"), T.undefined());
167
168 CompileRun("eval = function(x) { return x; }");
169 T.CheckCall(T.Val("17 + 6"), T.Val("17 + 6"), T.undefined());
170
171 CompileRun("eval = function(x) { return this; }");
172 T.CheckCall(g, T.Val("17 + 6"), T.undefined());
173
174 CompileRun("eval = function(x) { 'use strict'; return this; }");
175 T.CheckCall(T.undefined(), T.Val("17 + 6"), T.undefined());
176 }
177
178
TEST(ReceiverPatching)179 TEST(ReceiverPatching) {
180 // TODO(turbofan): Note that this test only checks that the function prologue
181 // patches an undefined receiver to the global receiver. If this starts to
182 // fail once we fix the calling protocol, just remove this test.
183 FunctionTester T("(function(a) { return this; })");
184 Handle<JSObject> g(T.function->context()->global_object()->global_proxy());
185 T.CheckCall(g, T.undefined());
186 }
187
188
TEST(CallEval)189 TEST(CallEval) {
190 FunctionTester T(
191 "var x = 42;"
192 "(function () {"
193 "function bar() { return eval('x') };"
194 "return bar;"
195 "})();");
196
197 T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
198 }
199
200
TEST(ContextLoadedFromActivation)201 TEST(ContextLoadedFromActivation) {
202 const char* script =
203 "var x = 42;"
204 "(function() {"
205 " return function () { return x };"
206 "})()";
207
208 // Disable context specialization.
209 FunctionTester T(script);
210 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
211 v8::Context::Scope scope(context);
212 v8::Local<v8::Value> value = CompileRun(script);
213 i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
214 i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
215 jsfun->set_code(T.function->code());
216 jsfun->set_shared(T.function->shared());
217 CHECK(context->Global()
218 ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
219 .FromJust());
220 CompileRun("var x = 24;");
221 ExpectInt32("foo();", 24);
222 }
223
224
TEST(BuiltinLoadedFromActivation)225 TEST(BuiltinLoadedFromActivation) {
226 const char* script =
227 "var x = 42;"
228 "(function() {"
229 " return function () { return this; };"
230 "})()";
231
232 // Disable context specialization.
233 FunctionTester T(script);
234 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
235 v8::Context::Scope scope(context);
236 v8::Local<v8::Value> value = CompileRun(script);
237 i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
238 i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
239 jsfun->set_code(T.function->code());
240 jsfun->set_shared(T.function->shared());
241 CHECK(context->Global()
242 ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
243 .FromJust());
244 CompileRun("var x = 24;");
245 ExpectObject("foo()", context->Global());
246 }
247
248 } // namespace compiler
249 } // namespace internal
250 } // namespace v8
251