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 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 22 TEST(SimpleCall2) { 23 FunctionTester T("(function(foo,a) { return foo(a); })"); 24 FunctionTester U("(function(a) { return a; })"); 25 26 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")); 30 } 31 32 33 TEST(ConstCall) { 34 FunctionTester T("(function(foo,a) { return foo(a,3); })"); 35 FunctionTester U("(function(a,b) { return a + b; })"); 36 37 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")); 42 } 43 44 45 TEST(ConstCall2) { 46 FunctionTester T("(function(foo,a) { return foo(a,\"3\"); })"); 47 FunctionTester U("(function(a,b) { return a + b; })"); 48 49 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")); 54 } 55 56 57 TEST(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 67 TEST(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 77 TEST(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 88 TEST(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 101 TEST(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 111 TEST(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 121 TEST(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 132 TEST(RuntimeCall) { 133 FLAG_allow_natives_syntax = true; 134 FunctionTester T("(function(a) { return %IsJSReceiver(a); })"); 135 136 T.CheckCall(T.false_value(), T.Val(23), T.undefined()); 137 T.CheckCall(T.false_value(), T.Val(4.2), T.undefined()); 138 T.CheckCall(T.false_value(), T.Val("str"), T.undefined()); 139 T.CheckCall(T.false_value(), T.true_value(), T.undefined()); 140 T.CheckCall(T.false_value(), T.false_value(), T.undefined()); 141 T.CheckCall(T.false_value(), T.undefined(), T.undefined()); 142 T.CheckCall(T.true_value(), T.NewObject("({})"), T.undefined()); 143 T.CheckCall(T.true_value(), T.NewObject("([])"), T.undefined()); 144 } 145 146 147 TEST(RuntimeCallInline) { 148 FLAG_allow_natives_syntax = true; 149 FunctionTester T("(function(a) { return %_IsJSReceiver(a); })"); 150 151 T.CheckCall(T.false_value(), T.Val(23), T.undefined()); 152 T.CheckCall(T.false_value(), T.Val(4.2), T.undefined()); 153 T.CheckCall(T.false_value(), T.Val("str"), T.undefined()); 154 T.CheckCall(T.false_value(), T.true_value(), T.undefined()); 155 T.CheckCall(T.false_value(), T.false_value(), T.undefined()); 156 T.CheckCall(T.false_value(), T.undefined(), T.undefined()); 157 T.CheckCall(T.true_value(), T.NewObject("({})"), T.undefined()); 158 T.CheckCall(T.true_value(), T.NewObject("([])"), T.undefined()); 159 } 160 161 162 TEST(EvalCall) { 163 FunctionTester T("(function(a,b) { return eval(a); })"); 164 Handle<JSObject> g(T.function->context()->global_object()->global_proxy()); 165 166 T.CheckCall(T.Val(23), T.Val("17 + 6"), T.undefined()); 167 T.CheckCall(T.Val("'Y'; a"), T.Val("'Y'; a"), T.Val("b-val")); 168 T.CheckCall(T.Val("b-val"), T.Val("'Y'; b"), T.Val("b-val")); 169 T.CheckCall(g, T.Val("this"), T.undefined()); 170 T.CheckCall(g, T.Val("'use strict'; this"), T.undefined()); 171 172 CompileRun("eval = function(x) { return x; }"); 173 T.CheckCall(T.Val("17 + 6"), T.Val("17 + 6"), T.undefined()); 174 175 CompileRun("eval = function(x) { return this; }"); 176 T.CheckCall(g, T.Val("17 + 6"), T.undefined()); 177 178 CompileRun("eval = function(x) { 'use strict'; return this; }"); 179 T.CheckCall(T.undefined(), T.Val("17 + 6"), T.undefined()); 180 } 181 182 183 TEST(ReceiverPatching) { 184 // TODO(turbofan): Note that this test only checks that the function prologue 185 // patches an undefined receiver to the global receiver. If this starts to 186 // fail once we fix the calling protocol, just remove this test. 187 FunctionTester T("(function(a) { return this; })"); 188 Handle<JSObject> g(T.function->context()->global_object()->global_proxy()); 189 T.CheckCall(g, T.undefined()); 190 } 191 192 193 TEST(CallEval) { 194 FunctionTester T( 195 "var x = 42;" 196 "(function () {" 197 "function bar() { return eval('x') };" 198 "return bar;" 199 "})();"); 200 201 T.CheckCall(T.Val(42), T.Val("x"), T.undefined()); 202 } 203 204 205 TEST(ContextLoadedFromActivation) { 206 const char* script = 207 "var x = 42;" 208 "(function() {" 209 " return function () { return x };" 210 "})()"; 211 212 // Disable context specialization. 213 FunctionTester T(script); 214 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 215 v8::Context::Scope scope(context); 216 v8::Local<v8::Value> value = CompileRun(script); 217 i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value); 218 i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun); 219 jsfun->set_code(T.function->code()); 220 jsfun->set_shared(T.function->shared()); 221 jsfun->set_literals(T.function->literals()); 222 CHECK(context->Global() 223 ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun)) 224 .FromJust()); 225 CompileRun("var x = 24;"); 226 ExpectInt32("foo();", 24); 227 } 228 229 230 TEST(BuiltinLoadedFromActivation) { 231 const char* script = 232 "var x = 42;" 233 "(function() {" 234 " return function () { return this; };" 235 "})()"; 236 237 // Disable context specialization. 238 FunctionTester T(script); 239 v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); 240 v8::Context::Scope scope(context); 241 v8::Local<v8::Value> value = CompileRun(script); 242 i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value); 243 i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun); 244 jsfun->set_code(T.function->code()); 245 jsfun->set_shared(T.function->shared()); 246 jsfun->set_literals(T.function->literals()); 247 CHECK(context->Global() 248 ->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun)) 249 .FromJust()); 250 CompileRun("var x = 24;"); 251 ExpectObject("foo()", context->Global()); 252 } 253 254 } // namespace compiler 255 } // namespace internal 256 } // namespace v8 257