blob: 555e049af44d6fe5d32a55951ad571135b1796c4 [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 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
Ben Murdoch097c5b22016-05-18 11:27:45 +0100165 static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
166 JSFunction* p = NULL;
167 { // because of the implicit handle scope of FunctionTester.
168 FunctionTester f(graph, param_count);
169 p = *f.function;
170 }
171 return Handle<JSFunction>(p); // allocated in outer handle scope.
172 }
173
174 private:
175 uint32_t flags_;
176
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400177 Handle<JSFunction> Compile(Handle<JSFunction> function) {
Ben Murdochda12d292016-06-02 14:46:10 +0100178 Zone zone(function->GetIsolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 ParseInfo parse_info(&zone, function);
Ben Murdochc5610432016-08-08 18:44:38 +0100180 CompilationInfo info(&parse_info, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 info.MarkAsDeoptimizationEnabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400182
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 CHECK(Parser::ParseStatic(info.parse_info()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100184 info.SetOptimizing();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 if (flags_ & CompilationInfo::kFunctionContextSpecializing) {
186 info.MarkAsFunctionContextSpecializing();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400187 }
188 if (flags_ & CompilationInfo::kInliningEnabled) {
189 info.MarkAsInliningEnabled();
190 }
Ben Murdochc5610432016-08-08 18:44:38 +0100191 if (FLAG_turbo_from_bytecode && function->shared()->HasBytecodeArray()) {
192 info.MarkAsOptimizeFromBytecode();
193 } else {
194 CHECK(Compiler::Analyze(info.parse_info()));
195 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400197
Ben Murdochc5610432016-08-08 18:44:38 +0100198 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 CHECK(!code.is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 info.dependencies()->Commit(code);
201 info.context()->native_context()->AddOptimizedCode(*code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202 function->ReplaceCode(*code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400203 return function;
204 }
205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 std::string BuildFunction(int param_count) {
207 std::string function_string = "(function(";
208 if (param_count > 0) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100209 function_string += 'a';
210 for (int i = 1; i < param_count; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 function_string += ',';
Ben Murdoch097c5b22016-05-18 11:27:45 +0100212 function_string += static_cast<char>('a' + i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 }
214 }
215 function_string += "){})";
216 return function_string;
217 }
218
219 std::string BuildFunctionFromDescriptor(
220 const CallInterfaceDescriptor& descriptor) {
221 return BuildFunction(descriptor.GetParameterCount());
222 }
223
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400224 // Compile the given machine graph instead of the source of the function
225 // and replace the JSFunction's code with the result.
226 Handle<JSFunction> CompileGraph(Graph* graph) {
Ben Murdochda12d292016-06-02 14:46:10 +0100227 Zone zone(function->GetIsolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 ParseInfo parse_info(&zone, function);
Ben Murdochc5610432016-08-08 18:44:38 +0100229 CompilationInfo info(&parse_info, function);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 CHECK(Parser::ParseStatic(info.parse_info()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100232 info.SetOptimizing();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233
234 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
235 CHECK(!code.is_null());
236 function->ReplaceCode(*code);
237 return function;
238 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240} // namespace compiler
241} // namespace internal
242} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243
244#endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_