• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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