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 // TODO(jochen): Remove this after the setting is turned on globally. | 5 // TODO(jochen): Remove this after the setting is turned on globally. |
6 #define V8_IMMINENT_DEPRECATION_WARNINGS | 6 #define V8_IMMINENT_DEPRECATION_WARNINGS |
7 | 7 |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 } | 60 } |
61 | 61 |
62 private: | 62 private: |
63 Isolate* isolate_; | 63 Isolate* isolate_; |
64 Handle<JSFunction> function_; | 64 Handle<JSFunction> function_; |
65 }; | 65 }; |
66 | 66 |
67 | 67 |
68 class BytecodeGraphTester { | 68 class BytecodeGraphTester { |
69 public: | 69 public: |
70 BytecodeGraphTester(Isolate* isolate, Zone* zone, const char* script) | 70 BytecodeGraphTester(Isolate* isolate, Zone* zone, const char* script, |
| 71 const char* filter = kFunctionName) |
71 : isolate_(isolate), zone_(zone), script_(script) { | 72 : isolate_(isolate), zone_(zone), script_(script) { |
72 i::FLAG_ignition = true; | 73 i::FLAG_ignition = true; |
73 i::FLAG_always_opt = false; | 74 i::FLAG_always_opt = false; |
74 i::FLAG_allow_natives_syntax = true; | 75 i::FLAG_allow_natives_syntax = true; |
75 // Set ignition filter flag via SetFlagsFromString to avoid double-free | 76 // Set ignition filter flag via SetFlagsFromString to avoid double-free |
76 // (or potential leak with StrDup() based on ownership confusion). | 77 // (or potential leak with StrDup() based on ownership confusion). |
77 ScopedVector<char> ignition_filter(64); | 78 ScopedVector<char> ignition_filter(64); |
78 SNPrintF(ignition_filter, "--ignition-filter=%s", kFunctionName); | 79 SNPrintF(ignition_filter, "--ignition-filter=%s", filter); |
79 FlagList::SetFlagsFromString(ignition_filter.start(), | 80 FlagList::SetFlagsFromString(ignition_filter.start(), |
80 ignition_filter.length()); | 81 ignition_filter.length()); |
81 // Ensure handler table is generated. | 82 // Ensure handler table is generated. |
82 isolate->interpreter()->Initialize(); | 83 isolate->interpreter()->Initialize(); |
83 } | 84 } |
84 virtual ~BytecodeGraphTester() {} | 85 virtual ~BytecodeGraphTester() {} |
85 | 86 |
86 template <class... A> | 87 template <class... A> |
87 BytecodeGraphCallable<A...> GetCallable() { | 88 BytecodeGraphCallable<A...> GetCallable( |
88 return BytecodeGraphCallable<A...>(isolate_, GetFunction()); | 89 const char* functionName = kFunctionName) { |
| 90 return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName)); |
89 } | 91 } |
90 | 92 |
91 Local<Message> CheckThrowsReturnMessage() { | 93 Local<Message> CheckThrowsReturnMessage() { |
92 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_)); | 94 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_)); |
93 auto callable = GetCallable<>(); | 95 auto callable = GetCallable<>(); |
94 MaybeHandle<Object> no_result = callable(); | 96 MaybeHandle<Object> no_result = callable(); |
95 CHECK(isolate_->has_pending_exception()); | 97 CHECK(isolate_->has_pending_exception()); |
96 CHECK(try_catch.HasCaught()); | 98 CHECK(try_catch.HasCaught()); |
97 CHECK(no_result.is_null()); | 99 CHECK(no_result.is_null()); |
98 isolate_->OptionalRescheduleException(true); | 100 isolate_->OptionalRescheduleException(true); |
99 CHECK(!try_catch.Message().IsEmpty()); | 101 CHECK(!try_catch.Message().IsEmpty()); |
100 return try_catch.Message(); | 102 return try_catch.Message(); |
101 } | 103 } |
102 | 104 |
103 static Handle<Object> NewObject(const char* script) { | 105 static Handle<Object> NewObject(const char* script) { |
104 return v8::Utils::OpenHandle(*CompileRun(script)); | 106 return v8::Utils::OpenHandle(*CompileRun(script)); |
105 } | 107 } |
106 | 108 |
107 private: | 109 private: |
108 Isolate* isolate_; | 110 Isolate* isolate_; |
109 Zone* zone_; | 111 Zone* zone_; |
110 const char* script_; | 112 const char* script_; |
111 | 113 |
112 Handle<JSFunction> GetFunction() { | 114 Handle<JSFunction> GetFunction(const char* functionName) { |
113 CompileRun(script_); | 115 CompileRun(script_); |
114 Local<Function> api_function = Local<Function>::Cast( | 116 Local<Function> api_function = Local<Function>::Cast( |
115 CcTest::global() | 117 CcTest::global() |
116 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(kFunctionName)) | 118 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName)) |
117 .ToLocalChecked()); | 119 .ToLocalChecked()); |
118 Handle<JSFunction> function = | 120 Handle<JSFunction> function = |
119 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function)); | 121 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function)); |
120 CHECK(function->shared()->HasBytecodeArray()); | 122 CHECK(function->shared()->HasBytecodeArray()); |
121 | 123 |
122 ParseInfo parse_info(zone_, function); | 124 ParseInfo parse_info(zone_, function); |
123 | 125 |
124 CompilationInfo compilation_info(&parse_info); | 126 CompilationInfo compilation_info(&parse_info); |
125 compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>()); | 127 compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>()); |
126 // TODO(mythria): Remove this step once parse_info is not needed. | 128 // TODO(mythria): Remove this step once parse_info is not needed. |
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 snippets[i].code_snippet, kFunctionName); | 997 snippets[i].code_snippet, kFunctionName); |
996 BytecodeGraphTester tester(isolate, zone, script.start()); | 998 BytecodeGraphTester tester(isolate, zone, script.start()); |
997 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); | 999 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
998 v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value()); | 1000 v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value()); |
999 CHECK( | 1001 CHECK( |
1000 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) | 1002 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
1001 .FromJust()); | 1003 .FromJust()); |
1002 } | 1004 } |
1003 } | 1005 } |
1004 | 1006 |
| 1007 |
| 1008 TEST(BytecodeGraphBuilderContext) { |
| 1009 HandleAndZoneScope scope; |
| 1010 Isolate* isolate = scope.main_isolate(); |
| 1011 Zone* zone = scope.main_zone(); |
| 1012 Factory* factory = isolate->factory(); |
| 1013 |
| 1014 ExpectedSnippet<0> snippets[] = { |
| 1015 {"var x = 'outer';" |
| 1016 "function f() {" |
| 1017 " 'use strict';" |
| 1018 " {" |
| 1019 " let x = 'inner';" |
| 1020 " (function() {x});" |
| 1021 " }" |
| 1022 "return(x);" |
| 1023 "}" |
| 1024 "f();", |
| 1025 {factory->NewStringFromStaticChars("outer")}}, |
| 1026 {"var x = 'outer';" |
| 1027 "function f() {" |
| 1028 " 'use strict';" |
| 1029 " {" |
| 1030 " let x = 'inner ';" |
| 1031 " var innerFunc = function() {return x};" |
| 1032 " }" |
| 1033 "return(innerFunc() + x);" |
| 1034 "}" |
| 1035 "f();", |
| 1036 {factory->NewStringFromStaticChars("inner outer")}}, |
| 1037 {"var x = 'outer';" |
| 1038 "function f() {" |
| 1039 " 'use strict';" |
| 1040 " {" |
| 1041 " let x = 'inner ';" |
| 1042 " var innerFunc = function() {return x;};" |
| 1043 " {" |
| 1044 " let x = 'innermost ';" |
| 1045 " var innerMostFunc = function() {return x + innerFunc();};" |
| 1046 " }" |
| 1047 " x = 'inner_changed ';" |
| 1048 " }" |
| 1049 " return(innerMostFunc() + x);" |
| 1050 "}" |
| 1051 "f();", |
| 1052 {factory->NewStringFromStaticChars("innermost inner_changed outer")}}, |
| 1053 }; |
| 1054 |
| 1055 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 1056 for (size_t i = 0; i < num_snippets; i++) { |
| 1057 ScopedVector<char> script(1024); |
| 1058 SNPrintF(script, "%s", snippets[i].code_snippet); |
| 1059 |
| 1060 BytecodeGraphTester tester(isolate, zone, script.start(), "f"); |
| 1061 auto callable = tester.GetCallable<>("f"); |
| 1062 Handle<Object> return_value = callable().ToHandleChecked(); |
| 1063 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 1064 } |
| 1065 } |
| 1066 |
| 1067 |
| 1068 TEST(BytecodeGraphBuilderLoadContext) { |
| 1069 HandleAndZoneScope scope; |
| 1070 Isolate* isolate = scope.main_isolate(); |
| 1071 Zone* zone = scope.main_zone(); |
| 1072 Factory* factory = isolate->factory(); |
| 1073 |
| 1074 ExpectedSnippet<1> snippets[] = { |
| 1075 {"function Outer() {" |
| 1076 " var outerVar = 2;" |
| 1077 " function Inner(innerArg) {" |
| 1078 " this.innerFunc = function () {" |
| 1079 " return outerVar * innerArg;" |
| 1080 " };" |
| 1081 " };" |
| 1082 " this.getInnerFunc = function GetInner() {" |
| 1083 " return new Inner(3).innerFunc;" |
| 1084 " }" |
| 1085 "}" |
| 1086 "var f = new Outer().getInnerFunc();" |
| 1087 "f();", |
| 1088 {factory->NewNumberFromInt(6), factory->undefined_value()}}, |
| 1089 {"function Outer() {" |
| 1090 " var outerVar = 2;" |
| 1091 " function Inner(innerArg) {" |
| 1092 " this.innerFunc = function () {" |
| 1093 " outerVar = innerArg; return outerVar;" |
| 1094 " };" |
| 1095 " };" |
| 1096 " this.getInnerFunc = function GetInner() {" |
| 1097 " return new Inner(10).innerFunc;" |
| 1098 " }" |
| 1099 "}" |
| 1100 "var f = new Outer().getInnerFunc();" |
| 1101 "f();", |
| 1102 {factory->NewNumberFromInt(10), factory->undefined_value()}}, |
| 1103 {"function testOuter(outerArg) {" |
| 1104 " this.testinnerFunc = function testInner(innerArg) {" |
| 1105 " return innerArg + outerArg;" |
| 1106 " }" |
| 1107 "}" |
| 1108 "var f = new testOuter(10).testinnerFunc;" |
| 1109 "f(0);", |
| 1110 {factory->NewNumberFromInt(14), factory->NewNumberFromInt(4)}}, |
| 1111 {"function testOuter(outerArg) {" |
| 1112 " var outerVar = outerArg * 2;" |
| 1113 " this.testinnerFunc = function testInner(innerArg) {" |
| 1114 " outerVar = outerVar + innerArg; return outerVar;" |
| 1115 " }" |
| 1116 "}" |
| 1117 "var f = new testOuter(10).testinnerFunc;" |
| 1118 "f(0);", |
| 1119 {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}}; |
| 1120 |
| 1121 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 1122 for (size_t i = 0; i < num_snippets; i++) { |
| 1123 ScopedVector<char> script(1024); |
| 1124 SNPrintF(script, "%s", snippets[i].code_snippet); |
| 1125 |
| 1126 BytecodeGraphTester tester(isolate, zone, script.start(), "*"); |
| 1127 auto callable = tester.GetCallable<Handle<Object>>("f"); |
| 1128 Handle<Object> return_value = |
| 1129 callable(snippets[i].parameter(0)).ToHandleChecked(); |
| 1130 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 1131 } |
| 1132 } |
| 1133 |
1005 } // namespace compiler | 1134 } // namespace compiler |
1006 } // namespace internal | 1135 } // namespace internal |
1007 } // namespace v8 | 1136 } // namespace v8 |
OLD | NEW |