blob: 2fcd35398ce29a28b7070ade4dc3e5c25f4c6319 [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 |
34 CompilationInfo::kInliningEnabled | CompilationInfo::kTypingEnabled;
35 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 Murdoch4a90d5f2016-03-22 12:00:34 +000045 FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code)
46 : isolate(main_isolate()),
47 function(
48 (FLAG_allow_natives_syntax = true,
49 NewFunction(BuildFunctionFromDescriptor(descriptor).c_str()))),
50 flags_(0) {
51 Compile(function);
52 function->ReplaceCode(*code);
53 }
54
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 Isolate* isolate;
56 Handle<JSFunction> function;
57
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 MaybeHandle<Object> Call() {
59 return Execution::Call(isolate, function, undefined(), 0, nullptr);
60 }
61
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
63 Handle<Object> args[] = {a, b};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 return Execution::Call(isolate, function, undefined(), 2, args);
65 }
66
67 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c,
68 Handle<Object> d) {
69 Handle<Object> args[] = {a, b, c, d};
70 return Execution::Call(isolate, function, undefined(), 4, args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 }
72
73 void CheckThrows(Handle<Object> a, Handle<Object> b) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 MaybeHandle<Object> no_result = Call(a, b);
76 CHECK(isolate->has_pending_exception());
77 CHECK(try_catch.HasCaught());
78 CHECK(no_result.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 isolate->OptionalRescheduleException(true);
80 }
81
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
83 Handle<Object> b) {
84 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000085 MaybeHandle<Object> no_result = Call(a, b);
86 CHECK(isolate->has_pending_exception());
87 CHECK(try_catch.HasCaught());
88 CHECK(no_result.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089 isolate->OptionalRescheduleException(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 CHECK(!try_catch.Message().IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091 return try_catch.Message();
92 }
93
94 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
95 Handle<Object> result = Call(a, b).ToHandleChecked();
96 CHECK(expected->SameValue(*result));
97 }
98
99 void CheckCall(Handle<Object> expected, Handle<Object> a) {
100 CheckCall(expected, a, undefined());
101 }
102
103 void CheckCall(Handle<Object> expected) {
104 CheckCall(expected, undefined(), undefined());
105 }
106
107 void CheckCall(double expected, double a, double b) {
108 CheckCall(Val(expected), Val(a), Val(b));
109 }
110
111 void CheckTrue(Handle<Object> a, Handle<Object> b) {
112 CheckCall(true_value(), a, b);
113 }
114
115 void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
116
117 void CheckTrue(double a, double b) {
118 CheckCall(true_value(), Val(a), Val(b));
119 }
120
121 void CheckFalse(Handle<Object> a, Handle<Object> b) {
122 CheckCall(false_value(), a, b);
123 }
124
125 void CheckFalse(Handle<Object> a) {
126 CheckCall(false_value(), a, undefined());
127 }
128
129 void CheckFalse(double a, double b) {
130 CheckCall(false_value(), Val(a), Val(b));
131 }
132
133 Handle<JSFunction> NewFunction(const char* source) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 return Handle<JSFunction>::cast(v8::Utils::OpenHandle(
135 *v8::Local<v8::Function>::Cast(CompileRun(source))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 }
137
138 Handle<JSObject> NewObject(const char* source) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 return Handle<JSObject>::cast(v8::Utils::OpenHandle(
140 *v8::Local<v8::Object>::Cast(CompileRun(source))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141 }
142
143 Handle<String> Val(const char* string) {
144 return isolate->factory()->InternalizeUtf8String(string);
145 }
146
147 Handle<Object> Val(double value) {
148 return isolate->factory()->NewNumber(value);
149 }
150
151 Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
152
153 Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
154
155 Handle<Object> nan() { return isolate->factory()->nan_value(); }
156
157 Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
158
159 Handle<Object> null() { return isolate->factory()->null_value(); }
160
161 Handle<Object> true_value() { return isolate->factory()->true_value(); }
162
163 Handle<Object> false_value() { return isolate->factory()->false_value(); }
164
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 Handle<JSFunction> Compile(Handle<JSFunction> function) {
166// TODO(titzer): make this method private.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 Zone zone;
168 ParseInfo parse_info(&zone, function);
169 CompilationInfo info(&parse_info);
170 info.MarkAsDeoptimizationEnabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 CHECK(Parser::ParseStatic(info.parse_info()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173 info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 if (flags_ & CompilationInfo::kFunctionContextSpecializing) {
175 info.MarkAsFunctionContextSpecializing();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400176 }
177 if (flags_ & CompilationInfo::kInliningEnabled) {
178 info.MarkAsInliningEnabled();
179 }
180 if (flags_ & CompilationInfo::kTypingEnabled) {
181 info.MarkAsTypingEnabled();
182 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 CHECK(Compiler::Analyze(info.parse_info()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400184 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
185
186 Pipeline pipeline(&info);
187 Handle<Code> code = pipeline.GenerateCode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400188 CHECK(!code.is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 info.dependencies()->Commit(code);
190 info.context()->native_context()->AddOptimizedCode(*code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400191 function->ReplaceCode(*code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192 return function;
193 }
194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 JSFunction* p = NULL;
197 { // because of the implicit handle scope of FunctionTester.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 FunctionTester f(graph, param_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 p = *f.function;
200 }
201 return Handle<JSFunction>(p); // allocated in outer handle scope.
202 }
203
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 private:
205 uint32_t flags_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 std::string BuildFunction(int param_count) {
208 std::string function_string = "(function(";
209 if (param_count > 0) {
210 char next = 'a';
211 function_string += next;
212 while (param_count-- > 0) {
213 function_string += ',';
214 function_string += ++next;
215 }
216 }
217 function_string += "){})";
218 return function_string;
219 }
220
221 std::string BuildFunctionFromDescriptor(
222 const CallInterfaceDescriptor& descriptor) {
223 return BuildFunction(descriptor.GetParameterCount());
224 }
225
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400226 // Compile the given machine graph instead of the source of the function
227 // and replace the JSFunction's code with the result.
228 Handle<JSFunction> CompileGraph(Graph* graph) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 Zone zone;
230 ParseInfo parse_info(&zone, function);
231 CompilationInfo info(&parse_info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 CHECK(Parser::ParseStatic(info.parse_info()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234 info.SetOptimizing(BailoutId::None(),
235 Handle<Code>(function->shared()->code()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 CHECK(Compiler::Analyze(info.parse_info()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400237 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
238
239 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
240 CHECK(!code.is_null());
241 function->ReplaceCode(*code);
242 return function;
243 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245} // namespace compiler
246} // namespace internal
247} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248
249#endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_