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/compiler.h"
12 #include "src/compiler/pipeline.h"
13 #include "src/execution.h"
14 #include "src/full-codegen.h"
15 #include "src/handles.h"
16 #include "src/objects-inl.h"
17 #include "src/parser.h"
18 #include "src/rewriter.h"
19 #include "src/scopes.h"
21 #define USE_CRANKSHAFT 0
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 = CompilationInfo::kContextSpecializing |
35 CompilationInfo::kInliningEnabled |
36 CompilationInfo::kTypingEnabled;
37 CHECK_EQ(0, flags_ & ~supported_flags);
41 Handle<JSFunction> function;
43 Handle<JSFunction> Compile(Handle<JSFunction> function) {
44 #if V8_TURBOFAN_TARGET
45 CompilationInfoWithZone info(function);
47 CHECK(Parser::Parse(&info));
48 info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
49 if (flags_ & CompilationInfo::kContextSpecializing) {
50 info.MarkAsContextSpecializing();
52 if (flags_ & CompilationInfo::kInliningEnabled) {
53 info.MarkAsInliningEnabled();
55 if (flags_ & CompilationInfo::kTypingEnabled) {
56 info.MarkAsTypingEnabled();
58 CHECK(Rewriter::Rewrite(&info));
59 CHECK(Scope::Analyze(&info));
60 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
62 Pipeline pipeline(&info);
63 Handle<Code> code = pipeline.GenerateCode();
64 if (FLAG_turbo_deoptimization) {
65 info.context()->native_context()->AddOptimizedCode(*code);
68 CHECK(!code.is_null());
69 function->ReplaceCode(*code);
71 Handle<Code> unoptimized = Handle<Code>(function->code());
72 Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized,
73 Compiler::NOT_CONCURRENT);
74 CHECK(!code.is_null());
75 #if ENABLE_DISASSEMBLER
76 if (FLAG_print_opt_code) {
77 CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
78 code->Disassemble("test code", tracing_scope.file());
81 function->ReplaceCode(*code);
86 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
87 Handle<Object> args[] = {a, b};
88 return Execution::Call(isolate, function, undefined(), 2, args, false);
91 void CheckThrows(Handle<Object> a, Handle<Object> b) {
93 MaybeHandle<Object> no_result = Call(a, b);
94 CHECK(isolate->has_pending_exception());
95 CHECK(try_catch.HasCaught());
96 CHECK(no_result.is_null());
97 // TODO(mstarzinger): Temporary workaround for issue chromium:362388.
98 isolate->OptionalRescheduleException(true);
101 v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
104 MaybeHandle<Object> no_result = Call(a, b);
105 CHECK(isolate->has_pending_exception());
106 CHECK(try_catch.HasCaught());
107 CHECK(no_result.is_null());
108 // TODO(mstarzinger): Calling OptionalRescheduleException is a dirty hack,
109 // it's the only way to make Message() not to assert because an external
110 // exception has been caught by the try_catch.
111 isolate->OptionalRescheduleException(true);
112 return try_catch.Message();
115 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
116 Handle<Object> result = Call(a, b).ToHandleChecked();
117 CHECK(expected->SameValue(*result));
120 void CheckCall(Handle<Object> expected, Handle<Object> a) {
121 CheckCall(expected, a, undefined());
124 void CheckCall(Handle<Object> expected) {
125 CheckCall(expected, undefined(), undefined());
128 void CheckCall(double expected, double a, double b) {
129 CheckCall(Val(expected), Val(a), Val(b));
132 void CheckTrue(Handle<Object> a, Handle<Object> b) {
133 CheckCall(true_value(), a, b);
136 void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
138 void CheckTrue(double a, double b) {
139 CheckCall(true_value(), Val(a), Val(b));
142 void CheckFalse(Handle<Object> a, Handle<Object> b) {
143 CheckCall(false_value(), a, b);
146 void CheckFalse(Handle<Object> a) {
147 CheckCall(false_value(), a, undefined());
150 void CheckFalse(double a, double b) {
151 CheckCall(false_value(), Val(a), Val(b));
154 Handle<JSFunction> NewFunction(const char* source) {
155 return v8::Utils::OpenHandle(
156 *v8::Handle<v8::Function>::Cast(CompileRun(source)));
159 Handle<JSObject> NewObject(const char* source) {
160 return v8::Utils::OpenHandle(
161 *v8::Handle<v8::Object>::Cast(CompileRun(source)));
164 Handle<String> Val(const char* string) {
165 return isolate->factory()->InternalizeUtf8String(string);
168 Handle<Object> Val(double value) {
169 return isolate->factory()->NewNumber(value);
172 Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
174 Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
176 Handle<Object> nan() { return isolate->factory()->nan_value(); }
178 Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
180 Handle<Object> null() { return isolate->factory()->null_value(); }
182 Handle<Object> true_value() { return isolate->factory()->true_value(); }
184 Handle<Object> false_value() { return isolate->factory()->false_value(); }
191 } // namespace v8::internal::compiler
193 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_