Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1401)

Side by Side Diff: test/cctest/interpreter/test-interpreter.cc

Issue 1634153002: [Interpreter] Adds support for const/let variables to interpreter. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased the patch Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 : InterpreterTester(isolate, source, MaybeHandle<BytecodeArray>(), 89 : InterpreterTester(isolate, source, MaybeHandle<BytecodeArray>(),
90 MaybeHandle<TypeFeedbackVector>(), filter) {} 90 MaybeHandle<TypeFeedbackVector>(), filter) {}
91 91
92 virtual ~InterpreterTester() {} 92 virtual ~InterpreterTester() {}
93 93
94 template <class... A> 94 template <class... A>
95 InterpreterCallable<A...> GetCallable() { 95 InterpreterCallable<A...> GetCallable() {
96 return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>()); 96 return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>());
97 } 97 }
98 98
99 template <class... A>
100 InterpreterCallable<A...> GetCallableWithLegacyConstants() {
101 i::FLAG_legacy_const = true;
102 Handle<JSFunction> function = GetBytecodeFunction<A...>();
103 auto interpreter_callable = InterpreterCallable<A...>(isolate_, function);
104 i::FLAG_legacy_const = false;
105 return interpreter_callable;
106 }
107
108 Local<Message> CheckThrowsReturnMessage() {
109 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
110 auto callable = GetCallable<>();
111 MaybeHandle<Object> no_result = callable();
112 CHECK(isolate_->has_pending_exception());
113 CHECK(try_catch.HasCaught());
114 CHECK(no_result.is_null());
115 isolate_->OptionalRescheduleException(true);
116 CHECK(!try_catch.Message().IsEmpty());
117 return try_catch.Message();
118 }
119
99 static Handle<Object> NewObject(const char* script) { 120 static Handle<Object> NewObject(const char* script) {
100 return v8::Utils::OpenHandle(*CompileRun(script)); 121 return v8::Utils::OpenHandle(*CompileRun(script));
101 } 122 }
102 123
103 static Handle<String> GetName(Isolate* isolate, const char* name) { 124 static Handle<String> GetName(Isolate* isolate, const char* name) {
104 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(name); 125 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(name);
105 return isolate->factory()->string_table()->LookupString(isolate, result); 126 return isolate->factory()->string_table()->LookupString(isolate, result);
106 } 127 }
107 128
108 static std::string SourceForBody(const char* body) { 129 static std::string SourceForBody(const char* body) {
(...skipping 3564 matching lines...) Expand 10 before | Expand all | Expand 10 after
3673 for (size_t i = 0; i < arraysize(eval_func_decl); i++) { 3694 for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
3674 InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first, 3695 InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first,
3675 "*"); 3696 "*");
3676 auto callable = tester.GetCallable<>(); 3697 auto callable = tester.GetCallable<>();
3677 3698
3678 Handle<i::Object> return_value = callable().ToHandleChecked(); 3699 Handle<i::Object> return_value = callable().ToHandleChecked();
3679 CHECK(return_value->SameValue(*eval_func_decl[i].second)); 3700 CHECK(return_value->SameValue(*eval_func_decl[i].second));
3680 } 3701 }
3681 } 3702 }
3682 3703
3704 TEST(InterpreterConstDeclaration) {
3705 HandleAndZoneScope handles;
3706 i::Isolate* isolate = handles.main_isolate();
3707 i::Factory* factory = isolate->factory();
3708
3709 std::pair<const char*, Handle<Object>> const_decl[] = {
3710 {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
3711 {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
3712 {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
3713 {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
3714 {"let x; return x;", factory->undefined_value()},
3715 {"var x = 10; { let x = 30; } return x;",
3716 handle(Smi::FromInt(10), isolate)},
3717 {"let x = 10; { let x = 20; } return x;",
3718 handle(Smi::FromInt(10), isolate)},
3719 {"var x = 10; eval('let x = 20;'); return x;",
3720 handle(Smi::FromInt(10), isolate)},
3721 {"var x = 10; eval('const x = 20;'); return x;",
3722 handle(Smi::FromInt(10), isolate)},
3723 {"var x = 10; { const x = 20; } return x;",
3724 handle(Smi::FromInt(10), isolate)},
3725 {"var x = 10; { const x = 20; return x;} return -1;",
3726 handle(Smi::FromInt(20), isolate)},
3727 {"var a = 10;\n"
3728 "for (var i = 0; i < 10; ++i) {\n"
3729 " const x = i;\n" // const declarations are block scoped.
3730 " a = a + x;\n"
3731 "}\n"
3732 "return a;\n",
3733 handle(Smi::FromInt(55), isolate)},
3734 };
3735
3736 for (size_t i = 0; i < arraysize(const_decl); i++) {
3737 std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
3738 InterpreterTester tester(handles.main_isolate(), source.c_str());
3739 auto callable = tester.GetCallable<>();
3740
3741 Handle<i::Object> return_value = callable().ToHandleChecked();
3742 CHECK(return_value->SameValue(*const_decl[i].second));
3743 }
3744
3745 // Tests for strict mode.
3746 for (size_t i = 0; i < arraysize(const_decl); i++) {
3747 std::string strict_body =
3748 "'use strict'; " + std::string(const_decl[i].first);
3749 std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
3750 InterpreterTester tester(handles.main_isolate(), source.c_str());
3751 auto callable = tester.GetCallable<>();
3752
3753 Handle<i::Object> return_value = callable().ToHandleChecked();
3754 CHECK(return_value->SameValue(*const_decl[i].second));
3755 }
3756 }
3757
3758 TEST(InterpreterConstDeclarationLookupSlots) {
3759 HandleAndZoneScope handles;
3760 i::Isolate* isolate = handles.main_isolate();
3761 i::Factory* factory = isolate->factory();
3762
3763 std::pair<const char*, Handle<Object>> const_decl[] = {
3764 {"const x = 3; function f1() {return x;}; return x;",
3765 handle(Smi::FromInt(3), isolate)},
3766 {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
3767 handle(Smi::FromInt(30), isolate)},
3768 {"let x; x = 20; function f1() {return x;}; return x;",
3769 handle(Smi::FromInt(20), isolate)},
3770 {"let x; function f1() {return x;}; return x;",
3771 factory->undefined_value()},
3772 };
3773
3774 for (size_t i = 0; i < arraysize(const_decl); i++) {
3775 std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
3776 InterpreterTester tester(handles.main_isolate(), source.c_str());
3777 auto callable = tester.GetCallable<>();
3778
3779 Handle<i::Object> return_value = callable().ToHandleChecked();
3780 CHECK(return_value->SameValue(*const_decl[i].second));
3781 }
3782
3783 // Tests for strict mode.
3784 for (size_t i = 0; i < arraysize(const_decl); i++) {
3785 std::string strict_body =
3786 "'use strict'; " + std::string(const_decl[i].first);
3787 std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
3788 InterpreterTester tester(handles.main_isolate(), source.c_str());
3789 auto callable = tester.GetCallable<>();
3790
3791 Handle<i::Object> return_value = callable().ToHandleChecked();
3792 CHECK(return_value->SameValue(*const_decl[i].second));
3793 }
3794 }
3795
3796 TEST(InterpreterConstInLookupContextChain) {
3797 HandleAndZoneScope handles;
3798 i::Isolate* isolate = handles.main_isolate();
3799
3800 const char* prologue =
3801 "function OuterMost() {\n"
3802 " const outerConst = 10;\n"
3803 " let outerLet = 20;\n"
3804 " function Outer() {\n"
3805 " function Inner() {\n"
3806 " this.innerFunc = function() { ";
3807 const char* epilogue =
3808 " }\n"
3809 " }\n"
3810 " this.getInnerFunc ="
3811 " function() {return new Inner().innerFunc;}\n"
3812 " }\n"
3813 " this.getOuterFunc ="
3814 " function() {return new Outer().getInnerFunc();}"
3815 "}\n"
3816 "var f = new OuterMost().getOuterFunc();\n"
3817 "f();\n";
3818 std::pair<const char*, Handle<Object>> const_decl[] = {
3819 {"return outerConst;", handle(Smi::FromInt(10), isolate)},
3820 {"return outerLet;", handle(Smi::FromInt(20), isolate)},
3821 {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
3822 {"var outerLet = 40; return outerLet;",
3823 handle(Smi::FromInt(40), isolate)},
3824 {"var outerConst = 50; return outerConst;",
3825 handle(Smi::FromInt(50), isolate)},
3826 {"try { outerConst = 30 } catch(e) { return -1; }",
3827 handle(Smi::FromInt(-1), isolate)}};
3828
3829 for (size_t i = 0; i < arraysize(const_decl); i++) {
3830 std::string script = std::string(prologue) +
3831 std::string(const_decl[i].first) +
3832 std::string(epilogue);
3833 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
3834 auto callable = tester.GetCallable<>();
3835
3836 Handle<i::Object> return_value = callable().ToHandleChecked();
3837 CHECK(return_value->SameValue(*const_decl[i].second));
3838 }
3839
3840 // Tests for Legacy constant.
3841 std::pair<const char*, Handle<Object>> legacy_const_decl[] = {
3842 {"return outerConst = 23;", handle(Smi::FromInt(23), isolate)},
3843 {"outerConst = 30; return outerConst;",
3844 handle(Smi::FromInt(10), isolate)},
3845 };
3846
3847 for (size_t i = 0; i < arraysize(legacy_const_decl); i++) {
3848 std::string script = std::string(prologue) +
3849 std::string(legacy_const_decl[i].first) +
3850 std::string(epilogue);
3851 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
3852 auto callable = tester.GetCallableWithLegacyConstants<>();
3853
3854 Handle<i::Object> return_value = callable().ToHandleChecked();
3855 CHECK(return_value->SameValue(*legacy_const_decl[i].second));
3856 }
3857 }
3858
3859 TEST(InterpreterIllegalConstDeclaration) {
3860 HandleAndZoneScope handles;
3861
3862 std::pair<const char*, const char*> const_decl[] = {
3863 {"const x = x = 10 + 3; return x;",
3864 "Uncaught ReferenceError: x is not defined"},
3865 {"const x = 10; x = 20; return x;",
3866 "Uncaught TypeError: Assignment to constant variable."},
3867 {"const x = 10; { x = 20; } return x;",
3868 "Uncaught TypeError: Assignment to constant variable."},
3869 {"const x = 10; eval('x = 20;'); return x;",
3870 "Uncaught TypeError: Assignment to constant variable."},
3871 {"let x = x + 10; return x;",
3872 "Uncaught ReferenceError: x is not defined"},
3873 {"'use strict'; (function f1() { f1 = 123; })() ",
3874 "Uncaught TypeError: Assignment to constant variable."},
3875 };
3876
3877 for (size_t i = 0; i < arraysize(const_decl); i++) {
3878 std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
3879 InterpreterTester tester(handles.main_isolate(), source.c_str());
3880 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
3881 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
3882 char msg[100];
3883 message->WriteUtf8(msg);
3884 printf("%s\n", msg);
3885 CHECK(
3886 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
3887 .FromJust());
3888 }
3889
3890 // Tests for strict mode.
3891 for (size_t i = 0; i < arraysize(const_decl); i++) {
3892 std::string strict_body =
3893 "'use strict'; " + std::string(const_decl[i].first);
3894 std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
3895 InterpreterTester tester(handles.main_isolate(), source.c_str());
3896 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
3897 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
3898 CHECK(
3899 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
3900 .FromJust());
3901 }
3902 }
3903
3904 TEST(InterpreterLegacyConstDeclaration) {
3905 HandleAndZoneScope handles;
3906 i::Isolate* isolate = handles.main_isolate();
3907
3908 std::pair<const char*, Handle<Object>> const_decl[] = {
3909 {"const x = x = 10 + 3; return x;", handle(Smi::FromInt(13), isolate)},
3910 {"const x = 10; x = 20; return x;", handle(Smi::FromInt(10), isolate)},
3911 {"var a = 10;\n"
3912 "for (var i = 0; i < 10; ++i) {\n"
3913 " const x = i;\n" // Legacy constants are not block scoped.
3914 " a = a + x;\n"
3915 "}\n"
3916 "return a;\n",
3917 handle(Smi::FromInt(10), isolate)},
3918 {"const x = 20; eval('x = 10;'); return x;",
3919 handle(Smi::FromInt(20), isolate)},
3920 };
3921
3922 for (size_t i = 0; i < arraysize(const_decl); i++) {
3923 std::string source(InterpreterTester::SourceForBody(const_decl[i].first) +
3924 " f();");
3925 InterpreterTester tester(handles.main_isolate(), source.c_str());
3926 auto callable = tester.GetCallableWithLegacyConstants<>();
3927
3928 Handle<i::Object> return_value = callable().ToHandleChecked();
3929 CHECK(return_value->SameValue(*const_decl[i].second));
3930 }
3931 }
3932
3683 } // namespace interpreter 3933 } // namespace interpreter
3684 } // namespace internal 3934 } // namespace internal
3685 } // namespace v8 3935 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698