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
3 // found in the LICENSE file.
5 #ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
6 #define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
9 #include "test/cctest/cctest.h"
11 #include "src/ast-numbering.h"
12 #include "src/compiler.h"
13 #include "src/compiler/linkage.h"
14 #include "src/compiler/pipeline.h"
15 #include "src/execution.h"
16 #include "src/full-codegen/full-codegen.h"
17 #include "src/handles.h"
18 #include "src/objects-inl.h"
19 #include "src/parser.h"
20 #include "src/rewriter.h"
21 #include "src/scopes.h"
27 class FunctionTester : public InitializedHandleScope {
29 explicit FunctionTester(const char* source, uint32_t flags = 0)
30 : isolate(main_isolate()),
31 function((FLAG_allow_natives_syntax = true, NewFunction(source))),
34 const uint32_t supported_flags =
35 CompilationInfo::kFunctionContextSpecializing |
36 CompilationInfo::kInliningEnabled | CompilationInfo::kTypingEnabled;
37 CHECK_EQ(0u, flags_ & ~supported_flags);
40 // TODO(turbofan): generalize FunctionTester to work with N arguments. Now, it
41 // can handle up to four.
42 explicit FunctionTester(Graph* graph)
43 : isolate(main_isolate()),
44 function(NewFunction("(function(a,b,c,d){})")),
50 Handle<JSFunction> function;
52 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
53 Handle<Object> args[] = {a, b};
54 return Execution::Call(isolate, function, undefined(), 2, args);
57 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c,
59 Handle<Object> args[] = {a, b, c, d};
60 return Execution::Call(isolate, function, undefined(), 4, args);
63 void CheckThrows(Handle<Object> a, Handle<Object> b) {
64 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
65 MaybeHandle<Object> no_result = Call(a, b);
66 CHECK(isolate->has_pending_exception());
67 CHECK(try_catch.HasCaught());
68 CHECK(no_result.is_null());
69 isolate->OptionalRescheduleException(true);
72 v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
74 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
75 MaybeHandle<Object> no_result = Call(a, b);
76 CHECK(isolate->has_pending_exception());
77 CHECK(try_catch.HasCaught());
78 CHECK(no_result.is_null());
79 isolate->OptionalRescheduleException(true);
80 CHECK(!try_catch.Message().IsEmpty());
81 return try_catch.Message();
84 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
85 Handle<Object> result = Call(a, b).ToHandleChecked();
86 CHECK(expected->SameValue(*result));
89 void CheckCall(Handle<Object> expected, Handle<Object> a) {
90 CheckCall(expected, a, undefined());
93 void CheckCall(Handle<Object> expected) {
94 CheckCall(expected, undefined(), undefined());
97 void CheckCall(double expected, double a, double b) {
98 CheckCall(Val(expected), Val(a), Val(b));
101 void CheckTrue(Handle<Object> a, Handle<Object> b) {
102 CheckCall(true_value(), a, b);
105 void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
107 void CheckTrue(double a, double b) {
108 CheckCall(true_value(), Val(a), Val(b));
111 void CheckFalse(Handle<Object> a, Handle<Object> b) {
112 CheckCall(false_value(), a, b);
115 void CheckFalse(Handle<Object> a) {
116 CheckCall(false_value(), a, undefined());
119 void CheckFalse(double a, double b) {
120 CheckCall(false_value(), Val(a), Val(b));
123 Handle<JSFunction> NewFunction(const char* source) {
124 return v8::Utils::OpenHandle(
125 *v8::Local<v8::Function>::Cast(CompileRun(source)));
128 Handle<JSObject> NewObject(const char* source) {
129 return v8::Utils::OpenHandle(
130 *v8::Local<v8::Object>::Cast(CompileRun(source)));
133 Handle<String> Val(const char* string) {
134 return isolate->factory()->InternalizeUtf8String(string);
137 Handle<Object> Val(double value) {
138 return isolate->factory()->NewNumber(value);
141 Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
143 Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
145 Handle<Object> nan() { return isolate->factory()->nan_value(); }
147 Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
149 Handle<Object> null() { return isolate->factory()->null_value(); }
151 Handle<Object> true_value() { return isolate->factory()->true_value(); }
153 Handle<Object> false_value() { return isolate->factory()->false_value(); }
155 Handle<JSFunction> Compile(Handle<JSFunction> function) {
156 // TODO(titzer): make this method private.
158 ParseInfo parse_info(&zone, function);
159 CompilationInfo info(&parse_info);
160 info.MarkAsDeoptimizationEnabled();
162 CHECK(Parser::ParseStatic(info.parse_info()));
163 info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
164 if (flags_ & CompilationInfo::kFunctionContextSpecializing) {
165 info.MarkAsFunctionContextSpecializing();
167 if (flags_ & CompilationInfo::kInliningEnabled) {
168 info.MarkAsInliningEnabled();
170 if (flags_ & CompilationInfo::kTypingEnabled) {
171 info.MarkAsTypingEnabled();
173 CHECK(Compiler::Analyze(info.parse_info()));
174 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
176 Pipeline pipeline(&info);
177 Handle<Code> code = pipeline.GenerateCode();
178 CHECK(!code.is_null());
179 info.context()->native_context()->AddOptimizedCode(*code);
180 function->ReplaceCode(*code);
184 static Handle<JSFunction> ForMachineGraph(Graph* graph) {
185 JSFunction* p = NULL;
186 { // because of the implicit handle scope of FunctionTester.
187 FunctionTester f(graph);
190 return Handle<JSFunction>(p); // allocated in outer handle scope.
196 // Compile the given machine graph instead of the source of the function
197 // and replace the JSFunction's code with the result.
198 Handle<JSFunction> CompileGraph(Graph* graph) {
200 ParseInfo parse_info(&zone, function);
201 CompilationInfo info(&parse_info);
203 CHECK(Parser::ParseStatic(info.parse_info()));
204 info.SetOptimizing(BailoutId::None(),
205 Handle<Code>(function->shared()->code()));
206 CHECK(Compiler::Analyze(info.parse_info()));
207 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
209 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
210 CHECK(!code.is_null());
211 function->ReplaceCode(*code);
217 } // namespace v8::internal::compiler
219 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_