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

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: Refactored VisitVariableAssignment. Created 4 years, 10 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;
rmcilroy 2016/02/03 12:28:27 Again you can just do this in the test rather than
mythria 2016/02/04 10:28:53 Done.
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 3718 matching lines...) Expand 10 before | Expand all | Expand 10 after
3827 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3848 InterpreterTester tester(handles.main_isolate(), source.c_str());
3828 auto callable = tester.GetCallable<>(); 3849 auto callable = tester.GetCallable<>();
3829 3850
3830 Handle<i::Object> return_value = callable().ToHandleChecked(); 3851 Handle<i::Object> return_value = callable().ToHandleChecked();
3831 CHECK(return_value->SameValue(*do_expr[i].second)); 3852 CHECK(return_value->SameValue(*do_expr[i].second));
3832 } 3853 }
3833 3854
3834 FLAG_harmony_do_expressions = old_flag; 3855 FLAG_harmony_do_expressions = old_flag;
3835 } 3856 }
3836 3857
3858 TEST(InterpreterConstDeclaration) {
3859 HandleAndZoneScope handles;
3860 i::Isolate* isolate = handles.main_isolate();
3861 i::Factory* factory = isolate->factory();
3862
3863 std::pair<const char*, Handle<Object>> const_decl[] = {
3864 {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
3865 {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
3866 {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
3867 {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
3868 {"let x; return x;", factory->undefined_value()},
3869 {"var x = 10; { let x = 30; } return x;",
3870 handle(Smi::FromInt(10), isolate)},
3871 {"let x = 10; { let x = 20; } return x;",
3872 handle(Smi::FromInt(10), isolate)},
3873 {"var x = 10; eval('let x = 20;'); return x;",
3874 handle(Smi::FromInt(10), isolate)},
3875 {"var x = 10; eval('const x = 20;'); return x;",
3876 handle(Smi::FromInt(10), isolate)},
3877 {"var x = 10; { const x = 20; } return x;",
3878 handle(Smi::FromInt(10), isolate)},
3879 {"var x = 10; { const x = 20; return x;} return -1;",
3880 handle(Smi::FromInt(20), isolate)},
3881 {"var a = 10;\n"
3882 "for (var i = 0; i < 10; ++i) {\n"
3883 " const x = i;\n" // const declarations are block scoped.
3884 " a = a + x;\n"
3885 "}\n"
3886 "return a;\n",
3887 handle(Smi::FromInt(55), isolate)},
3888 };
3889
3890 for (size_t i = 0; i < arraysize(const_decl); i++) {
rmcilroy 2016/02/03 12:28:27 comment - tests for sloppy mode.
mythria 2016/02/04 10:28:53 Done.
3891 std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
3892 InterpreterTester tester(handles.main_isolate(), source.c_str());
3893 auto callable = tester.GetCallable<>();
3894
3895 Handle<i::Object> return_value = callable().ToHandleChecked();
3896 CHECK(return_value->SameValue(*const_decl[i].second));
3897 }
3898
3899 // Tests for strict mode.
3900 for (size_t i = 0; i < arraysize(const_decl); i++) {
3901 std::string strict_body =
3902 "'use strict'; " + std::string(const_decl[i].first);
3903 std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
3904 InterpreterTester tester(handles.main_isolate(), source.c_str());
3905 auto callable = tester.GetCallable<>();
3906
3907 Handle<i::Object> return_value = callable().ToHandleChecked();
3908 CHECK(return_value->SameValue(*const_decl[i].second));
3909 }
3910 }
3911
3912 TEST(InterpreterConstDeclarationLookupSlots) {
3913 HandleAndZoneScope handles;
3914 i::Isolate* isolate = handles.main_isolate();
3915 i::Factory* factory = isolate->factory();
3916
3917 std::pair<const char*, Handle<Object>> const_decl[] = {
3918 {"const x = 3; function f1() {return x;}; return x;",
3919 handle(Smi::FromInt(3), isolate)},
3920 {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
3921 handle(Smi::FromInt(30), isolate)},
3922 {"let x; x = 20; function f1() {return x;}; return x;",
3923 handle(Smi::FromInt(20), isolate)},
3924 {"let x; function f1() {return x;}; return x;",
3925 factory->undefined_value()},
3926 };
3927
3928 for (size_t i = 0; i < arraysize(const_decl); i++) {
rmcilroy 2016/02/03 12:28:27 ditto
mythria 2016/02/04 10:28:53 Done.
3929 std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
3930 InterpreterTester tester(handles.main_isolate(), source.c_str());
3931 auto callable = tester.GetCallable<>();
3932
3933 Handle<i::Object> return_value = callable().ToHandleChecked();
3934 CHECK(return_value->SameValue(*const_decl[i].second));
3935 }
3936
3937 // Tests for strict mode.
3938 for (size_t i = 0; i < arraysize(const_decl); i++) {
3939 std::string strict_body =
3940 "'use strict'; " + std::string(const_decl[i].first);
3941 std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
3942 InterpreterTester tester(handles.main_isolate(), source.c_str());
3943 auto callable = tester.GetCallable<>();
3944
3945 Handle<i::Object> return_value = callable().ToHandleChecked();
3946 CHECK(return_value->SameValue(*const_decl[i].second));
3947 }
3948 }
3949
3950 TEST(InterpreterConstInLookupContextChain) {
3951 HandleAndZoneScope handles;
3952 i::Isolate* isolate = handles.main_isolate();
3953
3954 const char* prologue =
3955 "function OuterMost() {\n"
3956 " const outerConst = 10;\n"
3957 " let outerLet = 20;\n"
3958 " function Outer() {\n"
3959 " function Inner() {\n"
3960 " this.innerFunc = function() { ";
3961 const char* epilogue =
3962 " }\n"
3963 " }\n"
3964 " this.getInnerFunc ="
3965 " function() {return new Inner().innerFunc;}\n"
3966 " }\n"
3967 " this.getOuterFunc ="
3968 " function() {return new Outer().getInnerFunc();}"
3969 "}\n"
3970 "var f = new OuterMost().getOuterFunc();\n"
3971 "f();\n";
3972 std::pair<const char*, Handle<Object>> const_decl[] = {
3973 {"return outerConst;", handle(Smi::FromInt(10), isolate)},
3974 {"return outerLet;", handle(Smi::FromInt(20), isolate)},
3975 {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
3976 {"var outerLet = 40; return outerLet;",
3977 handle(Smi::FromInt(40), isolate)},
3978 {"var outerConst = 50; return outerConst;",
3979 handle(Smi::FromInt(50), isolate)},
3980 {"try { outerConst = 30 } catch(e) { return -1; }",
3981 handle(Smi::FromInt(-1), isolate)}};
3982
3983 for (size_t i = 0; i < arraysize(const_decl); i++) {
3984 std::string script = std::string(prologue) +
3985 std::string(const_decl[i].first) +
3986 std::string(epilogue);
3987 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
3988 auto callable = tester.GetCallable<>();
3989
3990 Handle<i::Object> return_value = callable().ToHandleChecked();
3991 CHECK(return_value->SameValue(*const_decl[i].second));
3992 }
3993
3994 // Tests for Legacy constant.
3995 std::pair<const char*, Handle<Object>> legacy_const_decl[] = {
3996 {"return outerConst = 23;", handle(Smi::FromInt(23), isolate)},
3997 {"outerConst = 30; return outerConst;",
3998 handle(Smi::FromInt(10), isolate)},
3999 };
4000
4001 for (size_t i = 0; i < arraysize(legacy_const_decl); i++) {
4002 std::string script = std::string(prologue) +
4003 std::string(legacy_const_decl[i].first) +
4004 std::string(epilogue);
4005 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
4006 auto callable = tester.GetCallableWithLegacyConstants<>();
4007
4008 Handle<i::Object> return_value = callable().ToHandleChecked();
4009 CHECK(return_value->SameValue(*legacy_const_decl[i].second));
4010 }
4011 }
4012
4013 TEST(InterpreterIllegalConstDeclaration) {
4014 HandleAndZoneScope handles;
4015
4016 std::pair<const char*, const char*> const_decl[] = {
4017 {"const x = x = 10 + 3; return x;",
4018 "Uncaught ReferenceError: x is not defined"},
4019 {"const x = 10; x = 20; return x;",
4020 "Uncaught TypeError: Assignment to constant variable."},
4021 {"const x = 10; { x = 20; } return x;",
4022 "Uncaught TypeError: Assignment to constant variable."},
4023 {"const x = 10; eval('x = 20;'); return x;",
4024 "Uncaught TypeError: Assignment to constant variable."},
4025 {"let x = x + 10; return x;",
4026 "Uncaught ReferenceError: x is not defined"},
4027 {"'use strict'; (function f1() { f1 = 123; })() ",
4028 "Uncaught TypeError: Assignment to constant variable."},
4029 };
4030
4031 for (size_t i = 0; i < arraysize(const_decl); i++) {
rmcilroy 2016/02/03 12:28:27 ditto
mythria 2016/02/04 10:28:53 Done.
4032 std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
4033 InterpreterTester tester(handles.main_isolate(), source.c_str());
4034 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
4035 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
4036 CHECK(
4037 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
4038 .FromJust());
4039 }
4040
4041 // Tests for strict mode.
4042 for (size_t i = 0; i < arraysize(const_decl); i++) {
4043 std::string strict_body =
4044 "'use strict'; " + std::string(const_decl[i].first);
4045 std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
4046 InterpreterTester tester(handles.main_isolate(), source.c_str());
4047 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
4048 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
4049 CHECK(
4050 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
4051 .FromJust());
4052 }
4053 }
4054
4055 TEST(InterpreterLegacyConstDeclaration) {
4056 HandleAndZoneScope handles;
4057 i::Isolate* isolate = handles.main_isolate();
4058
4059 std::pair<const char*, Handle<Object>> const_decl[] = {
4060 {"const x = (x = 10) + 3; return x;", handle(Smi::FromInt(13), isolate)},
4061 {"const x = 10; x = 20; return x;", handle(Smi::FromInt(10), isolate)},
4062 {"var a = 10;\n"
4063 "for (var i = 0; i < 10; ++i) {\n"
4064 " const x = i;\n" // Legacy constants are not block scoped.
4065 " a = a + x;\n"
4066 "}\n"
4067 "return a;\n",
4068 handle(Smi::FromInt(10), isolate)},
4069 {"const x = 20; eval('x = 10;'); return x;",
4070 handle(Smi::FromInt(20), isolate)},
4071 };
4072
4073 for (size_t i = 0; i < arraysize(const_decl); i++) {
4074 std::string source(InterpreterTester::SourceForBody(const_decl[i].first) +
4075 " f();");
4076 InterpreterTester tester(handles.main_isolate(), source.c_str());
4077 auto callable = tester.GetCallableWithLegacyConstants<>();
4078
4079 Handle<i::Object> return_value = callable().ToHandleChecked();
4080 CHECK(return_value->SameValue(*const_decl[i].second));
4081 }
4082 }
4083
3837 } // namespace interpreter 4084 } // namespace interpreter
3838 } // namespace internal 4085 } // namespace internal
3839 } // namespace v8 4086 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698