| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/execution.h" | 7 #include "src/execution.h" |
| 8 #include "src/handles.h" | 8 #include "src/handles.h" |
| 9 #include "src/interpreter/bytecode-array-builder.h" | 9 #include "src/interpreter/bytecode-array-builder.h" |
| 10 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 InterpreterTester(Isolate* isolate, const char* source, | 59 InterpreterTester(Isolate* isolate, const char* source, |
| 60 MaybeHandle<BytecodeArray> bytecode, | 60 MaybeHandle<BytecodeArray> bytecode, |
| 61 MaybeHandle<TypeFeedbackVector> feedback_vector, | 61 MaybeHandle<TypeFeedbackVector> feedback_vector, |
| 62 const char* filter) | 62 const char* filter) |
| 63 : isolate_(isolate), | 63 : isolate_(isolate), |
| 64 source_(source), | 64 source_(source), |
| 65 bytecode_(bytecode), | 65 bytecode_(bytecode), |
| 66 feedback_vector_(feedback_vector) { | 66 feedback_vector_(feedback_vector) { |
| 67 i::FLAG_ignition = true; | 67 i::FLAG_ignition = true; |
| 68 i::FLAG_ignition_fake_try_catch = true; | 68 i::FLAG_ignition_fake_try_catch = true; |
| 69 i::FLAG_ignition_fallback_on_eval_and_catch = false; |
| 69 i::FLAG_always_opt = false; | 70 i::FLAG_always_opt = false; |
| 70 // Set ignition filter flag via SetFlagsFromString to avoid double-free | 71 // Set ignition filter flag via SetFlagsFromString to avoid double-free |
| 71 // (or potential leak with StrDup() based on ownership confusion). | 72 // (or potential leak with StrDup() based on ownership confusion). |
| 72 ScopedVector<char> ignition_filter(64); | 73 ScopedVector<char> ignition_filter(64); |
| 73 SNPrintF(ignition_filter, "--ignition-filter=%s", filter); | 74 SNPrintF(ignition_filter, "--ignition-filter=%s", filter); |
| 74 FlagList::SetFlagsFromString(ignition_filter.start(), | 75 FlagList::SetFlagsFromString(ignition_filter.start(), |
| 75 ignition_filter.length()); | 76 ignition_filter.length()); |
| 76 // Ensure handler table is generated. | 77 // Ensure handler table is generated. |
| 77 isolate->interpreter()->Initialize(); | 78 isolate->interpreter()->Initialize(); |
| 78 } | 79 } |
| (...skipping 3109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3188 InterpreterTester::SourceForBody(to_name_tests[i].first)); | 3189 InterpreterTester::SourceForBody(to_name_tests[i].first)); |
| 3189 InterpreterTester tester(handles.main_isolate(), source.c_str()); | 3190 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3190 auto callable = tester.GetCallable<>(); | 3191 auto callable = tester.GetCallable<>(); |
| 3191 | 3192 |
| 3192 Handle<i::Object> return_value = callable().ToHandleChecked(); | 3193 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3193 CHECK(return_value->SameValue(*to_name_tests[i].second)); | 3194 CHECK(return_value->SameValue(*to_name_tests[i].second)); |
| 3194 } | 3195 } |
| 3195 } | 3196 } |
| 3196 | 3197 |
| 3197 | 3198 |
| 3199 TEST(TemporaryRegisterAllocation) { |
| 3200 HandleAndZoneScope handles; |
| 3201 i::Isolate* isolate = handles.main_isolate(); |
| 3202 i::Factory* factory = isolate->factory(); |
| 3203 |
| 3204 std::pair<const char*, Handle<Object>> reg_tests[] = { |
| 3205 {"function add(a, b, c) {" |
| 3206 " return a + b + c;" |
| 3207 "}" |
| 3208 "function f() {" |
| 3209 " var a = 10, b = 10;" |
| 3210 " return add(a, b++, b);" |
| 3211 "}", |
| 3212 factory->NewNumberFromInt(31)}, |
| 3213 {"function add(a, b, c, d) {" |
| 3214 " return a + b + c + d;" |
| 3215 "}" |
| 3216 "function f() {" |
| 3217 " var x = 10, y = 20, z = 30;" |
| 3218 " return x + add(x, (y= x++), x, z);" |
| 3219 "}", |
| 3220 factory->NewNumberFromInt(71)}, |
| 3221 }; |
| 3222 |
| 3223 for (size_t i = 0; i < arraysize(reg_tests); i++) { |
| 3224 InterpreterTester tester(handles.main_isolate(), reg_tests[i].first); |
| 3225 auto callable = tester.GetCallable<>(); |
| 3226 |
| 3227 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3228 CHECK(return_value->SameValue(*reg_tests[i].second)); |
| 3229 } |
| 3230 } |
| 3231 |
| 3232 |
| 3198 TEST(InterpreterLookupSlot) { | 3233 TEST(InterpreterLookupSlot) { |
| 3199 HandleAndZoneScope handles; | 3234 HandleAndZoneScope handles; |
| 3200 i::Isolate* isolate = handles.main_isolate(); | 3235 i::Isolate* isolate = handles.main_isolate(); |
| 3201 i::Factory* factory = isolate->factory(); | 3236 i::Factory* factory = isolate->factory(); |
| 3202 | 3237 |
| 3203 // TODO(mythria): Add more tests when we have support for eval/with. | 3238 // TODO(mythria): Add more tests when we have support for eval/with. |
| 3204 const char* function_prologue = "var f;" | 3239 const char* function_prologue = "var f;" |
| 3205 "var x = 1;" | 3240 "var x = 1;" |
| 3206 "function f1() {" | 3241 "function f1() {" |
| 3207 " eval(\"function t() {"; | 3242 " eval(\"function t() {"; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3269 | 3304 |
| 3270 InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); | 3305 InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); |
| 3271 auto callable = tester.GetCallable<>(); | 3306 auto callable = tester.GetCallable<>(); |
| 3272 | 3307 |
| 3273 Handle<i::Object> return_value = callable().ToHandleChecked(); | 3308 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3274 CHECK(return_value->SameValue(*lookup_slot[i].second)); | 3309 CHECK(return_value->SameValue(*lookup_slot[i].second)); |
| 3275 } | 3310 } |
| 3276 } | 3311 } |
| 3277 | 3312 |
| 3278 | 3313 |
| 3279 TEST(TemporaryRegisterAllocation) { | |
| 3280 HandleAndZoneScope handles; | |
| 3281 i::Isolate* isolate = handles.main_isolate(); | |
| 3282 i::Factory* factory = isolate->factory(); | |
| 3283 | |
| 3284 std::pair<const char*, Handle<Object>> reg_tests[] = { | |
| 3285 {"function add(a, b, c) {" | |
| 3286 " return a + b + c;" | |
| 3287 "}" | |
| 3288 "function f() {" | |
| 3289 " var a = 10, b = 10;" | |
| 3290 " return add(a, b++, b);" | |
| 3291 "}", | |
| 3292 factory->NewNumberFromInt(31)}, | |
| 3293 {"function add(a, b, c, d) {" | |
| 3294 " return a + b + c + d;" | |
| 3295 "}" | |
| 3296 "function f() {" | |
| 3297 " var x = 10, y = 20, z = 30;" | |
| 3298 " return x + add(x, (y= x++), x, z);" | |
| 3299 "}", | |
| 3300 factory->NewNumberFromInt(71)}, | |
| 3301 }; | |
| 3302 | |
| 3303 for (size_t i = 0; i < arraysize(reg_tests); i++) { | |
| 3304 InterpreterTester tester(handles.main_isolate(), reg_tests[i].first); | |
| 3305 auto callable = tester.GetCallable<>(); | |
| 3306 | |
| 3307 Handle<i::Object> return_value = callable().ToHandleChecked(); | |
| 3308 CHECK(return_value->SameValue(*reg_tests[i].second)); | |
| 3309 } | |
| 3310 } | |
| 3311 | |
| 3312 | |
| 3313 TEST(InterpreterDeleteLookupSlot) { | 3314 TEST(InterpreterDeleteLookupSlot) { |
| 3314 HandleAndZoneScope handles; | 3315 HandleAndZoneScope handles; |
| 3315 i::Isolate* isolate = handles.main_isolate(); | 3316 i::Isolate* isolate = handles.main_isolate(); |
| 3316 i::Factory* factory = isolate->factory(); | 3317 i::Factory* factory = isolate->factory(); |
| 3317 | 3318 |
| 3318 // TODO(mythria): Add more tests when we have support for eval/with. | 3319 // TODO(mythria): Add more tests when we have support for eval/with. |
| 3319 const char* function_prologue = "var f;" | 3320 const char* function_prologue = "var f;" |
| 3320 "var x = 1;" | 3321 "var x = 1;" |
| 3321 "y = 10;" | 3322 "y = 10;" |
| 3322 "var obj = {val:10};" | 3323 "var obj = {val:10};" |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3380 InterpreterTester tester(handles.main_isolate(), script.c_str()); | 3381 InterpreterTester tester(handles.main_isolate(), script.c_str()); |
| 3381 auto callable = tester.GetCallable<Handle<Object>>(); | 3382 auto callable = tester.GetCallable<Handle<Object>>(); |
| 3382 Handle<Object> return_val = | 3383 Handle<Object> return_val = |
| 3383 callable(factory->NewNumberFromInt(a)).ToHandleChecked(); | 3384 callable(factory->NewNumberFromInt(a)).ToHandleChecked(); |
| 3384 static const int results[] = {11, 12, 2}; | 3385 static const int results[] = {11, 12, 2}; |
| 3385 CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]); | 3386 CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]); |
| 3386 } | 3387 } |
| 3387 } | 3388 } |
| 3388 } | 3389 } |
| 3389 | 3390 |
| 3391 |
| 3392 TEST(InterpreterEval) { |
| 3393 HandleAndZoneScope handles; |
| 3394 i::Isolate* isolate = handles.main_isolate(); |
| 3395 i::Factory* factory = isolate->factory(); |
| 3396 |
| 3397 std::pair<const char*, Handle<Object>> eval[] = { |
| 3398 {"return eval('1;');", handle(Smi::FromInt(1), isolate)}, |
| 3399 {"return eval('100 * 20;');", handle(Smi::FromInt(2000), isolate)}, |
| 3400 {"var x = 10; return eval('x + 20;');", |
| 3401 handle(Smi::FromInt(30), isolate)}, |
| 3402 {"var x = 10; eval('x = 33;'); return x;", |
| 3403 handle(Smi::FromInt(33), isolate)}, |
| 3404 {"'use strict'; var x = 20; var z = 0;\n" |
| 3405 "eval('var x = 33; z = x;'); return x + z;", |
| 3406 handle(Smi::FromInt(53), isolate)}, |
| 3407 {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;", |
| 3408 handle(Smi::FromInt(86), isolate)}, |
| 3409 {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x", |
| 3410 handle(Smi::FromInt(11), isolate)}, |
| 3411 {"var x = 10; eval('var x = 20;'); return x;", |
| 3412 handle(Smi::FromInt(20), isolate)}, |
| 3413 {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;", |
| 3414 handle(Smi::FromInt(1), isolate)}, |
| 3415 {"'use strict'; var x = 1; eval('var x = 2;'); return x;", |
| 3416 handle(Smi::FromInt(1), isolate)}, |
| 3417 {"var x = 10; eval('x + 20;'); return typeof x;", |
| 3418 factory->NewStringFromStaticChars("number")}, |
| 3419 {"eval('var y = 10;'); return typeof unallocated;", |
| 3420 factory->NewStringFromStaticChars("undefined")}, |
| 3421 {"'use strict'; eval('var y = 10;'); return typeof unallocated;", |
| 3422 factory->NewStringFromStaticChars("undefined")}, |
| 3423 {"eval('var x = 10;'); return typeof x;", |
| 3424 factory->NewStringFromStaticChars("number")}, |
| 3425 {"var x = {}; eval('var x = 10;'); return typeof x;", |
| 3426 factory->NewStringFromStaticChars("number")}, |
| 3427 {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;", |
| 3428 factory->NewStringFromStaticChars("object")}, |
| 3429 }; |
| 3430 |
| 3431 for (size_t i = 0; i < arraysize(eval); i++) { |
| 3432 std::string source(InterpreterTester::SourceForBody(eval[i].first)); |
| 3433 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3434 auto callable = tester.GetCallable<>(); |
| 3435 |
| 3436 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3437 CHECK(return_value->SameValue(*eval[i].second)); |
| 3438 } |
| 3439 } |
| 3440 |
| 3441 |
| 3442 TEST(InterpreterEvalParams) { |
| 3443 HandleAndZoneScope handles; |
| 3444 i::Isolate* isolate = handles.main_isolate(); |
| 3445 |
| 3446 std::pair<const char*, Handle<Object>> eval_params[] = { |
| 3447 {"var x = 10; return eval('x + p1;');", |
| 3448 handle(Smi::FromInt(30), isolate)}, |
| 3449 {"var x = 10; eval('p1 = x;'); return p1;", |
| 3450 handle(Smi::FromInt(10), isolate)}, |
| 3451 {"var a = 10;" |
| 3452 "function inner() { return eval('a + p1;');}" |
| 3453 "return inner();", |
| 3454 handle(Smi::FromInt(30), isolate)}, |
| 3455 }; |
| 3456 |
| 3457 for (size_t i = 0; i < arraysize(eval_params); i++) { |
| 3458 std::string source = "function " + InterpreterTester::function_name() + |
| 3459 "(p1) {" + eval_params[i].first + "}"; |
| 3460 InterpreterTester tester(handles.main_isolate(), source.c_str()); |
| 3461 auto callable = tester.GetCallable<Handle<Object>>(); |
| 3462 |
| 3463 Handle<i::Object> return_value = |
| 3464 callable(handle(Smi::FromInt(20), isolate)).ToHandleChecked(); |
| 3465 CHECK(return_value->SameValue(*eval_params[i].second)); |
| 3466 } |
| 3467 } |
| 3468 |
| 3469 |
| 3470 TEST(InterpreterEvalGlobal) { |
| 3471 HandleAndZoneScope handles; |
| 3472 i::Isolate* isolate = handles.main_isolate(); |
| 3473 i::Factory* factory = isolate->factory(); |
| 3474 |
| 3475 std::pair<const char*, Handle<Object>> eval_global[] = { |
| 3476 {"function add_global() { eval('function test() { z = 33; }; test()'); };" |
| 3477 "function f() { add_global(); return z; }; f();", |
| 3478 handle(Smi::FromInt(33), isolate)}, |
| 3479 {"function add_global() {\n" |
| 3480 " eval('\"use strict\"; function test() { y = 33; };" |
| 3481 " try { test() } catch(e) {}');\n" |
| 3482 "}\n" |
| 3483 "function f() { add_global(); return typeof y; } f();", |
| 3484 factory->NewStringFromStaticChars("undefined")}, |
| 3485 }; |
| 3486 |
| 3487 for (size_t i = 0; i < arraysize(eval_global); i++) { |
| 3488 InterpreterTester tester(handles.main_isolate(), eval_global[i].first, |
| 3489 "test"); |
| 3490 auto callable = tester.GetCallable<>(); |
| 3491 |
| 3492 Handle<i::Object> return_value = callable().ToHandleChecked(); |
| 3493 CHECK(return_value->SameValue(*eval_global[i].second)); |
| 3494 } |
| 3495 } |
| 3496 |
| 3390 } // namespace interpreter | 3497 } // namespace interpreter |
| 3391 } // namespace internal | 3498 } // namespace internal |
| 3392 } // namespace v8 | 3499 } // namespace v8 |
| OLD | NEW |