blob: c7304f1da70089d791e249ac1107ea5269065c8f [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
6#define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/ast/ast-numbering.h"
9#include "src/ast/scopes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011#include "src/compiler/linkage.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/compiler/pipeline.h"
13#include "src/execution.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/full-codegen/full-codegen.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/handles.h"
16#include "src/objects-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/parsing/parser.h"
18#include "src/parsing/rewriter.h"
19#include "test/cctest/cctest.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020
21namespace v8 {
22namespace internal {
23namespace compiler {
24
25class FunctionTester : public InitializedHandleScope {
26 public:
27 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);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 const uint32_t supported_flags =
33 CompilationInfo::kFunctionContextSpecializing |
Ben Murdochc5610432016-08-08 18:44:38 +010034 CompilationInfo::kInliningEnabled;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 CHECK_EQ(0u, flags_ & ~supported_flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036 }
37
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 FunctionTester(Graph* graph, int param_count)
Emily Bernierd0a1eb72015-03-24 16:35:39 -040039 : isolate(main_isolate()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 function(NewFunction(BuildFunction(param_count).c_str())),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041 flags_(0) {
42 CompileGraph(graph);
43 }
44
Ben Murdoch61f157c2016-09-16 13:49:30 +010045 FunctionTester(Handle<Code> code, int param_count)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046 : isolate(main_isolate()),
Ben Murdoch61f157c2016-09-16 13:49:30 +010047 function((FLAG_allow_natives_syntax = true,
48 NewFunction(BuildFunction(param_count).c_str()))),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 flags_(0) {
50 Compile(function);
51 function->ReplaceCode(*code);
52 }
53
Ben Murdoch61f157c2016-09-16 13:49:30 +010054 FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code)
55 : FunctionTester(code, descriptor.GetParameterCount()) {}
56
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 Isolate* isolate;
58 Handle<JSFunction> function;
59
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 MaybeHandle<Object> Call() {
61 return Execution::Call(isolate, function, undefined(), 0, nullptr);
62 }
63
Ben Murdoch61f157c2016-09-16 13:49:30 +010064 MaybeHandle<Object> Call(Handle<Object> a) {
65 Handle<Object> args[] = {a};
66 return Execution::Call(isolate, function, undefined(), 1, args);
67 }
68
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
70 Handle<Object> args[] = {a, b};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 return Execution::Call(isolate, function, undefined(), 2, args);
72 }
73
Ben Murdoch61f157c2016-09-16 13:49:30 +010074 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 }
85
86 void CheckThrows(Handle<Object> a, Handle<Object> b) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 MaybeHandle<Object> no_result = Call(a, b);
89 CHECK(isolate->has_pending_exception());
90 CHECK(try_catch.HasCaught());
91 CHECK(no_result.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092 isolate->OptionalRescheduleException(true);
93 }
94
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
96 Handle<Object> b) {
97 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 MaybeHandle<Object> no_result = Call(a, b);
99 CHECK(isolate->has_pending_exception());
100 CHECK(try_catch.HasCaught());
101 CHECK(no_result.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 isolate->OptionalRescheduleException(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 CHECK(!try_catch.Message().IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 return try_catch.Message();
105 }
106
Ben Murdoch61f157c2016-09-16 13:49:30 +0100107 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b,
108 Handle<Object> c, Handle<Object> d) {
109 Handle<Object> result = Call(a, b, c, d).ToHandleChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110 CHECK(expected->SameValue(*result));
111 }
112
Ben Murdoch61f157c2016-09-16 13:49:30 +0100113 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b,
114 Handle<Object> c) {
115 return CheckCall(expected, a, b, c, undefined());
116 }
117
118 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
119 return CheckCall(expected, a, b, undefined());
120 }
121
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 void CheckCall(Handle<Object> expected, Handle<Object> a) {
123 CheckCall(expected, a, undefined());
124 }
125
Ben Murdoch61f157c2016-09-16 13:49:30 +0100126 void CheckCall(Handle<Object> expected) { CheckCall(expected, undefined()); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127
128 void CheckCall(double expected, double a, double b) {
129 CheckCall(Val(expected), Val(a), Val(b));
130 }
131
Ben Murdoch61f157c2016-09-16 13:49:30 +0100132 void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a); }
133
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134 void CheckTrue(Handle<Object> a, Handle<Object> b) {
135 CheckCall(true_value(), a, b);
136 }
137
Ben Murdoch61f157c2016-09-16 13:49:30 +0100138 void CheckTrue(Handle<Object> a, Handle<Object> b, Handle<Object> c) {
139 CheckCall(true_value(), a, b, c);
140 }
141
142 void CheckTrue(Handle<Object> a, Handle<Object> b, Handle<Object> c,
143 Handle<Object> d) {
144 CheckCall(true_value(), a, b, c, d);
145 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146
147 void CheckTrue(double a, double b) {
148 CheckCall(true_value(), Val(a), Val(b));
149 }
150
Ben Murdoch61f157c2016-09-16 13:49:30 +0100151 void CheckFalse(Handle<Object> a) { CheckCall(false_value(), a); }
152
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 void CheckFalse(Handle<Object> a, Handle<Object> b) {
154 CheckCall(false_value(), a, b);
155 }
156
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 void CheckFalse(double a, double b) {
158 CheckCall(false_value(), Val(a), Val(b));
159 }
160
161 Handle<JSFunction> NewFunction(const char* source) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 return Handle<JSFunction>::cast(v8::Utils::OpenHandle(
163 *v8::Local<v8::Function>::Cast(CompileRun(source))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 }
165
166 Handle<JSObject> NewObject(const char* source) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 return Handle<JSObject>::cast(v8::Utils::OpenHandle(
168 *v8::Local<v8::Object>::Cast(CompileRun(source))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 }
170
171 Handle<String> Val(const char* string) {
172 return isolate->factory()->InternalizeUtf8String(string);
173 }
174
175 Handle<Object> Val(double value) {
176 return isolate->factory()->NewNumber(value);
177 }
178
179 Handle<Object> infinity() { return isolate->factory()->infinity_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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100193 static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
194 JSFunction* p = NULL;
195 { // because of the implicit handle scope of FunctionTester.
196 FunctionTester f(graph, param_count);
197 p = *f.function;
198 }
199 return Handle<JSFunction>(p); // allocated in outer handle scope.
200 }
201
202 private:
203 uint32_t flags_;
204
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400205 Handle<JSFunction> Compile(Handle<JSFunction> function) {
Ben Murdochda12d292016-06-02 14:46:10 +0100206 Zone zone(function->GetIsolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 ParseInfo parse_info(&zone, function);
Ben Murdochc5610432016-08-08 18:44:38 +0100208 CompilationInfo info(&parse_info, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 info.MarkAsDeoptimizationEnabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 CHECK(Parser::ParseStatic(info.parse_info()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100212 info.SetOptimizing();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 if (flags_ & CompilationInfo::kFunctionContextSpecializing) {
214 info.MarkAsFunctionContextSpecializing();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215 }
216 if (flags_ & CompilationInfo::kInliningEnabled) {
217 info.MarkAsInliningEnabled();
218 }
Ben Murdochc5610432016-08-08 18:44:38 +0100219 if (FLAG_turbo_from_bytecode && function->shared()->HasBytecodeArray()) {
220 info.MarkAsOptimizeFromBytecode();
221 } else {
222 CHECK(Compiler::Analyze(info.parse_info()));
223 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400224 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100225 JSFunction::EnsureLiterals(function);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400226
Ben Murdochc5610432016-08-08 18:44:38 +0100227 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228 CHECK(!code.is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 info.dependencies()->Commit(code);
230 info.context()->native_context()->AddOptimizedCode(*code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231 function->ReplaceCode(*code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232 return function;
233 }
234
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 std::string BuildFunction(int param_count) {
236 std::string function_string = "(function(";
237 if (param_count > 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100238 function_string += 'a';
239 for (int i = 1; i < param_count; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 function_string += ',';
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241 function_string += static_cast<char>('a' + i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 }
243 }
244 function_string += "){})";
245 return function_string;
246 }
247
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248 // Compile the given machine graph instead of the source of the function
249 // and replace the JSFunction's code with the result.
250 Handle<JSFunction> CompileGraph(Graph* graph) {
Ben Murdochda12d292016-06-02 14:46:10 +0100251 Zone zone(function->GetIsolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 ParseInfo parse_info(&zone, function);
Ben Murdochc5610432016-08-08 18:44:38 +0100253 CompilationInfo info(&parse_info, function);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255 CHECK(Parser::ParseStatic(info.parse_info()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100256 info.SetOptimizing();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400257
258 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
259 CHECK(!code.is_null());
260 function->ReplaceCode(*code);
261 return function;
262 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264} // namespace compiler
265} // namespace internal
266} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267
268#endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_