OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 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 #ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ | 5 #ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
6 #define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ | 6 #define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
7 | 7 |
8 #include "src/ast/ast-numbering.h" | |
9 #include "src/compiler.h" | |
10 #include "src/compiler/linkage.h" | |
11 #include "src/compiler/pipeline.h" | |
12 #include "src/execution.h" | |
13 #include "src/full-codegen/full-codegen.h" | |
14 #include "src/handles.h" | 8 #include "src/handles.h" |
15 #include "src/objects-inl.h" | |
16 #include "src/parsing/parse-info.h" | |
17 #include "src/parsing/parser.h" | |
18 #include "src/parsing/rewriter.h" | |
19 #include "test/cctest/cctest.h" | 9 #include "test/cctest/cctest.h" |
20 | 10 |
21 namespace v8 { | 11 namespace v8 { |
22 namespace internal { | 12 namespace internal { |
| 13 |
| 14 class CallInterfaceDescriptor; |
| 15 class Isolate; |
| 16 |
23 namespace compiler { | 17 namespace compiler { |
24 | 18 |
| 19 class Graph; |
| 20 |
25 class FunctionTester : public InitializedHandleScope { | 21 class FunctionTester : public InitializedHandleScope { |
26 public: | 22 public: |
27 explicit FunctionTester(const char* source, uint32_t flags = 0) | 23 explicit FunctionTester(const char* source, uint32_t flags = 0); |
28 : isolate(main_isolate()), | |
29 function((FLAG_allow_natives_syntax = true, NewFunction(source))), | |
30 flags_(flags) { | |
31 Compile(function); | |
32 const uint32_t supported_flags = | |
33 CompilationInfo::kNativeContextSpecializing | | |
34 CompilationInfo::kInliningEnabled; | |
35 CHECK_EQ(0u, flags_ & ~supported_flags); | |
36 } | |
37 | 24 |
38 FunctionTester(Graph* graph, int param_count) | 25 FunctionTester(Graph* graph, int param_count); |
39 : isolate(main_isolate()), | |
40 function(NewFunction(BuildFunction(param_count).c_str())), | |
41 flags_(0) { | |
42 CompileGraph(graph); | |
43 } | |
44 | 26 |
45 FunctionTester(Handle<Code> code, int param_count) | 27 FunctionTester(Handle<Code> code, int param_count); |
46 : isolate(main_isolate()), | |
47 function((FLAG_allow_natives_syntax = true, | |
48 NewFunction(BuildFunction(param_count).c_str()))), | |
49 flags_(0) { | |
50 Compile(function); | |
51 function->ReplaceCode(*code); | |
52 } | |
53 | 28 |
54 FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code) | 29 FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code); |
55 : FunctionTester(code, descriptor.GetParameterCount()) {} | |
56 | 30 |
57 Isolate* isolate; | 31 Isolate* isolate; |
58 Handle<JSFunction> function; | 32 Handle<JSFunction> function; |
59 | 33 |
60 MaybeHandle<Object> Call() { | 34 MaybeHandle<Object> Call(); |
61 return Execution::Call(isolate, function, undefined(), 0, nullptr); | 35 MaybeHandle<Object> Call(Handle<Object> a); |
62 } | 36 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b); |
| 37 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, |
| 38 Handle<Object> c); |
| 39 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c, |
| 40 Handle<Object> d); |
63 | 41 |
64 MaybeHandle<Object> Call(Handle<Object> a) { | 42 void CheckThrows(Handle<Object> a, Handle<Object> b); |
65 Handle<Object> args[] = {a}; | |
66 return Execution::Call(isolate, function, undefined(), 1, args); | |
67 } | |
68 | |
69 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) { | |
70 Handle<Object> args[] = {a, b}; | |
71 return Execution::Call(isolate, function, undefined(), 2, args); | |
72 } | |
73 | |
74 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, | |
75 Handle<Object> c) { | |
76 Handle<Object> args[] = {a, b, c}; | |
77 return Execution::Call(isolate, function, undefined(), 3, args); | |
78 } | |
79 | |
80 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c, | |
81 Handle<Object> d) { | |
82 Handle<Object> args[] = {a, b, c, d}; | |
83 return Execution::Call(isolate, function, undefined(), 4, args); | |
84 } | |
85 | |
86 void CheckThrows(Handle<Object> a, Handle<Object> b) { | |
87 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); | |
88 MaybeHandle<Object> no_result = Call(a, b); | |
89 CHECK(isolate->has_pending_exception()); | |
90 CHECK(try_catch.HasCaught()); | |
91 CHECK(no_result.is_null()); | |
92 isolate->OptionalRescheduleException(true); | |
93 } | |
94 | |
95 v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a, | 43 v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a, |
96 Handle<Object> b) { | 44 Handle<Object> b); |
97 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); | |
98 MaybeHandle<Object> no_result = Call(a, b); | |
99 CHECK(isolate->has_pending_exception()); | |
100 CHECK(try_catch.HasCaught()); | |
101 CHECK(no_result.is_null()); | |
102 isolate->OptionalRescheduleException(true); | |
103 CHECK(!try_catch.Message().IsEmpty()); | |
104 return try_catch.Message(); | |
105 } | |
106 | |
107 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, | 45 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, |
108 Handle<Object> c, Handle<Object> d) { | 46 Handle<Object> c, Handle<Object> d) { |
109 Handle<Object> result = Call(a, b, c, d).ToHandleChecked(); | 47 Handle<Object> result = Call(a, b, c, d).ToHandleChecked(); |
110 CHECK(expected->SameValue(*result)); | 48 CHECK(expected->SameValue(*result)); |
111 } | 49 } |
112 | 50 |
113 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, | 51 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, |
114 Handle<Object> c) { | 52 Handle<Object> c) { |
115 return CheckCall(expected, a, b, c, undefined()); | 53 return CheckCall(expected, a, b, c, undefined()); |
116 } | 54 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 Handle<JSFunction> NewFunction(const char* source) { | 99 Handle<JSFunction> NewFunction(const char* source) { |
162 return Handle<JSFunction>::cast(v8::Utils::OpenHandle( | 100 return Handle<JSFunction>::cast(v8::Utils::OpenHandle( |
163 *v8::Local<v8::Function>::Cast(CompileRun(source)))); | 101 *v8::Local<v8::Function>::Cast(CompileRun(source)))); |
164 } | 102 } |
165 | 103 |
166 Handle<JSObject> NewObject(const char* source) { | 104 Handle<JSObject> NewObject(const char* source) { |
167 return Handle<JSObject>::cast(v8::Utils::OpenHandle( | 105 return Handle<JSObject>::cast(v8::Utils::OpenHandle( |
168 *v8::Local<v8::Object>::Cast(CompileRun(source)))); | 106 *v8::Local<v8::Object>::Cast(CompileRun(source)))); |
169 } | 107 } |
170 | 108 |
171 Handle<String> Val(const char* string) { | 109 Handle<String> Val(const char* string); |
172 return isolate->factory()->InternalizeUtf8String(string); | 110 Handle<Object> Val(double value); |
173 } | 111 Handle<Object> infinity(); |
174 | 112 Handle<Object> minus_infinity(); |
175 Handle<Object> Val(double value) { | 113 Handle<Object> nan(); |
176 return isolate->factory()->NewNumber(value); | 114 Handle<Object> undefined(); |
177 } | 115 Handle<Object> null(); |
178 | 116 Handle<Object> true_value(); |
179 Handle<Object> infinity() { return isolate->factory()->infinity_value(); } | 117 Handle<Object> false_value(); |
180 | |
181 Handle<Object> minus_infinity() { return Val(-V8_INFINITY); } | |
182 | |
183 Handle<Object> nan() { return isolate->factory()->nan_value(); } | |
184 | |
185 Handle<Object> undefined() { return isolate->factory()->undefined_value(); } | |
186 | |
187 Handle<Object> null() { return isolate->factory()->null_value(); } | |
188 | |
189 Handle<Object> true_value() { return isolate->factory()->true_value(); } | |
190 | |
191 Handle<Object> false_value() { return isolate->factory()->false_value(); } | |
192 | 118 |
193 static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) { | 119 static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) { |
194 JSFunction* p = NULL; | 120 JSFunction* p = NULL; |
195 { // because of the implicit handle scope of FunctionTester. | 121 { // because of the implicit handle scope of FunctionTester. |
196 FunctionTester f(graph, param_count); | 122 FunctionTester f(graph, param_count); |
197 p = *f.function; | 123 p = *f.function; |
198 } | 124 } |
199 return Handle<JSFunction>(p); // allocated in outer handle scope. | 125 return Handle<JSFunction>(p); // allocated in outer handle scope. |
200 } | 126 } |
201 | 127 |
202 private: | 128 private: |
203 uint32_t flags_; | 129 uint32_t flags_; |
204 | 130 |
205 Handle<JSFunction> Compile(Handle<JSFunction> function) { | 131 Handle<JSFunction> Compile(Handle<JSFunction> function); |
206 Zone zone(function->GetIsolate()->allocator()); | |
207 ParseInfo parse_info(&zone, function); | |
208 CompilationInfo info(&parse_info, function); | |
209 info.MarkAsDeoptimizationEnabled(); | |
210 | |
211 if (!FLAG_turbo_from_bytecode) { | |
212 CHECK(Parser::ParseStatic(info.parse_info())); | |
213 } | |
214 info.SetOptimizing(); | |
215 if (flags_ & CompilationInfo::kNativeContextSpecializing) { | |
216 info.MarkAsNativeContextSpecializing(); | |
217 } | |
218 if (flags_ & CompilationInfo::kInliningEnabled) { | |
219 info.MarkAsInliningEnabled(); | |
220 } | |
221 if (FLAG_turbo_from_bytecode) { | |
222 CHECK(Compiler::EnsureBytecode(&info)); | |
223 info.MarkAsOptimizeFromBytecode(); | |
224 } else { | |
225 CHECK(Compiler::Analyze(info.parse_info())); | |
226 CHECK(Compiler::EnsureDeoptimizationSupport(&info)); | |
227 } | |
228 JSFunction::EnsureLiterals(function); | |
229 | |
230 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info); | |
231 CHECK(!code.is_null()); | |
232 info.dependencies()->Commit(code); | |
233 info.context()->native_context()->AddOptimizedCode(*code); | |
234 function->ReplaceCode(*code); | |
235 return function; | |
236 } | |
237 | |
238 std::string BuildFunction(int param_count) { | 132 std::string BuildFunction(int param_count) { |
239 std::string function_string = "(function("; | 133 std::string function_string = "(function("; |
240 if (param_count > 0) { | 134 if (param_count > 0) { |
241 function_string += 'a'; | 135 function_string += 'a'; |
242 for (int i = 1; i < param_count; i++) { | 136 for (int i = 1; i < param_count; i++) { |
243 function_string += ','; | 137 function_string += ','; |
244 function_string += static_cast<char>('a' + i); | 138 function_string += static_cast<char>('a' + i); |
245 } | 139 } |
246 } | 140 } |
247 function_string += "){})"; | 141 function_string += "){})"; |
248 return function_string; | 142 return function_string; |
249 } | 143 } |
250 | 144 |
251 // Compile the given machine graph instead of the source of the function | 145 // Compile the given machine graph instead of the source of the function |
252 // and replace the JSFunction's code with the result. | 146 // and replace the JSFunction's code with the result. |
253 Handle<JSFunction> CompileGraph(Graph* graph) { | 147 Handle<JSFunction> CompileGraph(Graph* graph); |
254 Zone zone(function->GetIsolate()->allocator()); | |
255 ParseInfo parse_info(&zone, function); | |
256 CompilationInfo info(&parse_info, function); | |
257 | |
258 CHECK(Parser::ParseStatic(info.parse_info())); | |
259 info.SetOptimizing(); | |
260 | |
261 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph); | |
262 CHECK(!code.is_null()); | |
263 function->ReplaceCode(*code); | |
264 return function; | |
265 } | |
266 }; | 148 }; |
267 } // namespace compiler | 149 } // namespace compiler |
268 } // namespace internal | 150 } // namespace internal |
269 } // namespace v8 | 151 } // namespace v8 |
270 | 152 |
271 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ | 153 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
OLD | NEW |