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.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"
23 #define USE_CRANKSHAFT 0
29 class FunctionTester : public InitializedHandleScope {
31 explicit FunctionTester(const char* source, uint32_t flags = 0)
32 : isolate(main_isolate()),
33 function((FLAG_allow_natives_syntax = true, NewFunction(source))),
36 const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
37 CompilationInfo::kBuiltinInliningEnabled |
38 CompilationInfo::kInliningEnabled |
39 CompilationInfo::kTypingEnabled;
40 CHECK_EQ(0u, flags_ & ~supported_flags);
43 explicit FunctionTester(Graph* graph)
44 : isolate(main_isolate()),
45 function(NewFunction("(function(a,b){})")),
51 Handle<JSFunction> function;
53 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
54 Handle<Object> args[] = {a, b};
55 return Execution::Call(isolate, function, undefined(), 2, args, false);
58 void CheckThrows(Handle<Object> a, Handle<Object> b) {
60 MaybeHandle<Object> no_result = Call(a, b);
61 CHECK(isolate->has_pending_exception());
62 CHECK(try_catch.HasCaught());
63 CHECK(no_result.is_null());
64 isolate->OptionalRescheduleException(true);
67 v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
70 MaybeHandle<Object> no_result = Call(a, b);
71 CHECK(isolate->has_pending_exception());
72 CHECK(try_catch.HasCaught());
73 CHECK(no_result.is_null());
74 isolate->OptionalRescheduleException(true);
75 CHECK(!try_catch.Message().IsEmpty());
76 return try_catch.Message();
79 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
80 Handle<Object> result = Call(a, b).ToHandleChecked();
81 CHECK(expected->SameValue(*result));
84 void CheckCall(Handle<Object> expected, Handle<Object> a) {
85 CheckCall(expected, a, undefined());
88 void CheckCall(Handle<Object> expected) {
89 CheckCall(expected, undefined(), undefined());
92 void CheckCall(double expected, double a, double b) {
93 CheckCall(Val(expected), Val(a), Val(b));
96 void CheckTrue(Handle<Object> a, Handle<Object> b) {
97 CheckCall(true_value(), a, b);
100 void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
102 void CheckTrue(double a, double b) {
103 CheckCall(true_value(), Val(a), Val(b));
106 void CheckFalse(Handle<Object> a, Handle<Object> b) {
107 CheckCall(false_value(), a, b);
110 void CheckFalse(Handle<Object> a) {
111 CheckCall(false_value(), a, undefined());
114 void CheckFalse(double a, double b) {
115 CheckCall(false_value(), Val(a), Val(b));
118 Handle<JSFunction> NewFunction(const char* source) {
119 return v8::Utils::OpenHandle(
120 *v8::Handle<v8::Function>::Cast(CompileRun(source)));
123 Handle<JSObject> NewObject(const char* source) {
124 return v8::Utils::OpenHandle(
125 *v8::Handle<v8::Object>::Cast(CompileRun(source)));
128 Handle<String> Val(const char* string) {
129 return isolate->factory()->InternalizeUtf8String(string);
132 Handle<Object> Val(double value) {
133 return isolate->factory()->NewNumber(value);
136 Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
138 Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
140 Handle<Object> nan() { return isolate->factory()->nan_value(); }
142 Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
144 Handle<Object> null() { return isolate->factory()->null_value(); }
146 Handle<Object> true_value() { return isolate->factory()->true_value(); }
148 Handle<Object> false_value() { return isolate->factory()->false_value(); }
150 Handle<JSFunction> Compile(Handle<JSFunction> function) {
151 // TODO(titzer): make this method private.
152 #if V8_TURBOFAN_TARGET
154 ParseInfo parse_info(&zone, function);
155 CompilationInfo info(&parse_info);
157 CHECK(Parser::ParseStatic(info.parse_info()));
158 info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
159 if (flags_ & CompilationInfo::kContextSpecializing) {
160 info.MarkAsContextSpecializing();
162 if (flags_ & CompilationInfo::kInliningEnabled) {
163 info.MarkAsInliningEnabled();
165 if (flags_ & CompilationInfo::kTypingEnabled) {
166 info.MarkAsTypingEnabled();
168 CHECK(Compiler::Analyze(info.parse_info()));
169 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
171 Pipeline pipeline(&info);
172 Handle<Code> code = pipeline.GenerateCode();
173 if (FLAG_turbo_deoptimization) {
174 info.context()->native_context()->AddOptimizedCode(*code);
177 CHECK(!code.is_null());
178 function->ReplaceCode(*code);
180 Handle<Code> unoptimized = Handle<Code>(function->code());
181 Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized,
182 Compiler::NOT_CONCURRENT);
183 CHECK(!code.is_null());
184 #if ENABLE_DISASSEMBLER
185 if (FLAG_print_opt_code) {
186 CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
187 code->Disassemble("test code", tracing_scope.file());
190 function->ReplaceCode(*code);
195 static Handle<JSFunction> ForMachineGraph(Graph* graph) {
196 JSFunction* p = NULL;
197 { // because of the implicit handle scope of FunctionTester.
198 FunctionTester f(graph);
201 return Handle<JSFunction>(p); // allocated in outer handle scope.
207 // Compile the given machine graph instead of the source of the function
208 // and replace the JSFunction's code with the result.
209 Handle<JSFunction> CompileGraph(Graph* graph) {
210 CHECK(Pipeline::SupportedTarget());
212 ParseInfo parse_info(&zone, function);
213 CompilationInfo info(&parse_info);
215 CHECK(Parser::ParseStatic(info.parse_info()));
216 info.SetOptimizing(BailoutId::None(),
217 Handle<Code>(function->shared()->code()));
218 CHECK(Compiler::Analyze(info.parse_info()));
219 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
221 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
222 CHECK(!code.is_null());
223 function->ReplaceCode(*code);
229 } // namespace v8::internal::compiler
231 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_