revise installing a license file
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / compiler / function-tester.h
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.
4
5 #ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
6 #define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
7
8 #include "src/v8.h"
9 #include "test/cctest/cctest.h"
10
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"
22
23 #define USE_CRANKSHAFT 0
24
25 namespace v8 {
26 namespace internal {
27 namespace compiler {
28
29 class FunctionTester : public InitializedHandleScope {
30  public:
31   explicit FunctionTester(const char* source, uint32_t flags = 0)
32       : isolate(main_isolate()),
33         function((FLAG_allow_natives_syntax = true, NewFunction(source))),
34         flags_(flags) {
35     Compile(function);
36     const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
37                                      CompilationInfo::kInliningEnabled |
38                                      CompilationInfo::kTypingEnabled;
39     CHECK_EQ(0u, flags_ & ~supported_flags);
40   }
41
42   // TODO(turbofan): generalize FunctionTester to work with N arguments. Now, it
43   // can handle up to four.
44   explicit FunctionTester(Graph* graph)
45       : isolate(main_isolate()),
46         function(NewFunction("(function(a,b,c,d){})")),
47         flags_(0) {
48     CompileGraph(graph);
49   }
50
51   Isolate* isolate;
52   Handle<JSFunction> function;
53
54   MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
55     Handle<Object> args[] = {a, b};
56     return Execution::Call(isolate, function, undefined(), 2, args, false);
57   }
58
59   MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c,
60                            Handle<Object> d) {
61     Handle<Object> args[] = {a, b, c, d};
62     return Execution::Call(isolate, function, undefined(), 4, args, false);
63   }
64
65   void CheckThrows(Handle<Object> a, Handle<Object> b) {
66     TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
67     MaybeHandle<Object> no_result = Call(a, b);
68     CHECK(isolate->has_pending_exception());
69     CHECK(try_catch.HasCaught());
70     CHECK(no_result.is_null());
71     isolate->OptionalRescheduleException(true);
72   }
73
74   v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
75                                                    Handle<Object> b) {
76     TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
77     MaybeHandle<Object> no_result = Call(a, b);
78     CHECK(isolate->has_pending_exception());
79     CHECK(try_catch.HasCaught());
80     CHECK(no_result.is_null());
81     isolate->OptionalRescheduleException(true);
82     CHECK(!try_catch.Message().IsEmpty());
83     return try_catch.Message();
84   }
85
86   void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
87     Handle<Object> result = Call(a, b).ToHandleChecked();
88     CHECK(expected->SameValue(*result));
89   }
90
91   void CheckCall(Handle<Object> expected, Handle<Object> a) {
92     CheckCall(expected, a, undefined());
93   }
94
95   void CheckCall(Handle<Object> expected) {
96     CheckCall(expected, undefined(), undefined());
97   }
98
99   void CheckCall(double expected, double a, double b) {
100     CheckCall(Val(expected), Val(a), Val(b));
101   }
102
103   void CheckTrue(Handle<Object> a, Handle<Object> b) {
104     CheckCall(true_value(), a, b);
105   }
106
107   void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
108
109   void CheckTrue(double a, double b) {
110     CheckCall(true_value(), Val(a), Val(b));
111   }
112
113   void CheckFalse(Handle<Object> a, Handle<Object> b) {
114     CheckCall(false_value(), a, b);
115   }
116
117   void CheckFalse(Handle<Object> a) {
118     CheckCall(false_value(), a, undefined());
119   }
120
121   void CheckFalse(double a, double b) {
122     CheckCall(false_value(), Val(a), Val(b));
123   }
124
125   Handle<JSFunction> NewFunction(const char* source) {
126     return v8::Utils::OpenHandle(
127         *v8::Handle<v8::Function>::Cast(CompileRun(source)));
128   }
129
130   Handle<JSObject> NewObject(const char* source) {
131     return v8::Utils::OpenHandle(
132         *v8::Handle<v8::Object>::Cast(CompileRun(source)));
133   }
134
135   Handle<String> Val(const char* string) {
136     return isolate->factory()->InternalizeUtf8String(string);
137   }
138
139   Handle<Object> Val(double value) {
140     return isolate->factory()->NewNumber(value);
141   }
142
143   Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
144
145   Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
146
147   Handle<Object> nan() { return isolate->factory()->nan_value(); }
148
149   Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
150
151   Handle<Object> null() { return isolate->factory()->null_value(); }
152
153   Handle<Object> true_value() { return isolate->factory()->true_value(); }
154
155   Handle<Object> false_value() { return isolate->factory()->false_value(); }
156
157   Handle<JSFunction> Compile(Handle<JSFunction> function) {
158 // TODO(titzer): make this method private.
159 #if V8_TURBOFAN_TARGET
160     Zone zone;
161     ParseInfo parse_info(&zone, function);
162     CompilationInfo info(&parse_info);
163     info.MarkAsDeoptimizationEnabled();
164
165     CHECK(Parser::ParseStatic(info.parse_info()));
166     info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
167     if (flags_ & CompilationInfo::kContextSpecializing) {
168       info.MarkAsContextSpecializing();
169     }
170     if (flags_ & CompilationInfo::kInliningEnabled) {
171       info.MarkAsInliningEnabled();
172     }
173     if (flags_ & CompilationInfo::kTypingEnabled) {
174       info.MarkAsTypingEnabled();
175     }
176     CHECK(Compiler::Analyze(info.parse_info()));
177     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
178
179     Pipeline pipeline(&info);
180     Handle<Code> code = pipeline.GenerateCode();
181     CHECK(!code.is_null());
182     info.context()->native_context()->AddOptimizedCode(*code);
183     function->ReplaceCode(*code);
184 #elif USE_CRANKSHAFT
185     Handle<Code> unoptimized = Handle<Code>(function->code());
186     Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized,
187                                                    Compiler::NOT_CONCURRENT);
188     CHECK(!code.is_null());
189 #if ENABLE_DISASSEMBLER
190     if (FLAG_print_opt_code) {
191       CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
192       code->Disassemble("test code", tracing_scope.file());
193     }
194 #endif
195     function->ReplaceCode(*code);
196 #endif
197     return function;
198   }
199
200   static Handle<JSFunction> ForMachineGraph(Graph* graph) {
201     JSFunction* p = NULL;
202     {  // because of the implicit handle scope of FunctionTester.
203       FunctionTester f(graph);
204       p = *f.function;
205     }
206     return Handle<JSFunction>(p);  // allocated in outer handle scope.
207   }
208
209  private:
210   uint32_t flags_;
211
212   // Compile the given machine graph instead of the source of the function
213   // and replace the JSFunction's code with the result.
214   Handle<JSFunction> CompileGraph(Graph* graph) {
215     CHECK(Pipeline::SupportedTarget());
216     Zone zone;
217     ParseInfo parse_info(&zone, function);
218     CompilationInfo info(&parse_info);
219
220     CHECK(Parser::ParseStatic(info.parse_info()));
221     info.SetOptimizing(BailoutId::None(),
222                        Handle<Code>(function->shared()->code()));
223     CHECK(Compiler::Analyze(info.parse_info()));
224     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
225
226     Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
227     CHECK(!code.is_null());
228     function->ReplaceCode(*code);
229     return function;
230   }
231 };
232 }
233 }
234 }  // namespace v8::internal::compiler
235
236 #endif  // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_