OLD | NEW |
(Empty) | |
| 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/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" |
| 20 |
| 21 #define USE_CRANKSHAFT 0 |
| 22 |
| 23 namespace v8 { |
| 24 namespace internal { |
| 25 namespace compiler { |
| 26 |
| 27 class FunctionTester : public InitializedHandleScope { |
| 28 public: |
| 29 explicit FunctionTester(const char* source) |
| 30 : isolate(main_isolate()), |
| 31 function((FLAG_allow_natives_syntax = true, NewFunction(source))) { |
| 32 Compile(function); |
| 33 } |
| 34 |
| 35 Isolate* isolate; |
| 36 Handle<JSFunction> function; |
| 37 |
| 38 Handle<JSFunction> Compile(Handle<JSFunction> function) { |
| 39 #if V8_TURBOFAN_TARGET |
| 40 CompilationInfoWithZone info(function); |
| 41 |
| 42 CHECK(Parser::Parse(&info)); |
| 43 StrictMode strict_mode = info.function()->strict_mode(); |
| 44 info.SetStrictMode(strict_mode); |
| 45 info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code())); |
| 46 CHECK(Rewriter::Rewrite(&info)); |
| 47 CHECK(Scope::Analyze(&info)); |
| 48 CHECK_NE(NULL, info.scope()); |
| 49 |
| 50 EnsureDeoptimizationSupport(&info); |
| 51 |
| 52 Pipeline pipeline(&info); |
| 53 Handle<Code> code = pipeline.GenerateCode(); |
| 54 |
| 55 CHECK(!code.is_null()); |
| 56 function->ReplaceCode(*code); |
| 57 #elif USE_CRANKSHAFT |
| 58 Handle<Code> unoptimized = Handle<Code>(function->code()); |
| 59 Handle<Code> code = Compiler::GetOptimizedCode( |
| 60 function, unoptimized, Compiler::NOT_CONCURRENT); |
| 61 CHECK(!code.is_null()); |
| 62 #if ENABLE_DISASSEMBLER |
| 63 if (FLAG_print_opt_code) { |
| 64 CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); |
| 65 code->Disassemble("test code", tracing_scope.file()); |
| 66 } |
| 67 #endif |
| 68 function->ReplaceCode(*code); |
| 69 #endif |
| 70 return function; |
| 71 } |
| 72 |
| 73 static void EnsureDeoptimizationSupport(CompilationInfo* info) { |
| 74 bool should_recompile = !info->shared_info()->has_deoptimization_support(); |
| 75 if (should_recompile) { |
| 76 CompilationInfoWithZone unoptimized(info->shared_info()); |
| 77 // Note that we use the same AST that we will use for generating the |
| 78 // optimized code. |
| 79 unoptimized.SetFunction(info->function()); |
| 80 unoptimized.PrepareForCompilation(info->scope()); |
| 81 unoptimized.SetContext(info->context()); |
| 82 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); |
| 83 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); |
| 84 CHECK(succeeded); |
| 85 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 86 shared->EnableDeoptimizationSupport(*unoptimized.code()); |
| 87 } |
| 88 } |
| 89 |
| 90 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) { |
| 91 Handle<Object> args[] = { a, b }; |
| 92 return Execution::Call(isolate, |
| 93 function, |
| 94 undefined(), |
| 95 2, |
| 96 args, |
| 97 false); |
| 98 } |
| 99 |
| 100 void CheckThrows(Handle<Object> a, Handle<Object> b) { |
| 101 TryCatch try_catch; |
| 102 MaybeHandle<Object> no_result = Call(a, b); |
| 103 CHECK(isolate->has_pending_exception()); |
| 104 CHECK(try_catch.HasCaught()); |
| 105 CHECK(no_result.is_null()); |
| 106 // TODO(mstarzinger): Temporary workaround for issue chromium:362388. |
| 107 isolate->OptionalRescheduleException(true); |
| 108 } |
| 109 |
| 110 v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a, |
| 111 Handle<Object> b) { |
| 112 TryCatch try_catch; |
| 113 MaybeHandle<Object> no_result = Call(a, b); |
| 114 CHECK(isolate->has_pending_exception()); |
| 115 CHECK(try_catch.HasCaught()); |
| 116 CHECK(no_result.is_null()); |
| 117 // TODO(mstarzinger): Calling OptionalRescheduleException is a dirty hack, |
| 118 // it's the only way to make Message() not to assert because an external |
| 119 // exception has been caught by the try_catch. |
| 120 isolate->OptionalRescheduleException(true); |
| 121 return try_catch.Message(); |
| 122 } |
| 123 |
| 124 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) { |
| 125 Handle<Object> result = Call(a, b).ToHandleChecked(); |
| 126 CHECK(expected->SameValue(*result)); |
| 127 } |
| 128 |
| 129 void CheckCall(Handle<Object> expected, Handle<Object> a) { |
| 130 CheckCall(expected, a, undefined()); |
| 131 } |
| 132 |
| 133 void CheckCall(Handle<Object> expected) { |
| 134 CheckCall(expected, undefined(), undefined()); |
| 135 } |
| 136 |
| 137 void CheckCall(double expected, double a, double b) { |
| 138 CheckCall(Val(expected), Val(a), Val(b)); |
| 139 } |
| 140 |
| 141 void CheckTrue(Handle<Object> a, Handle<Object> b) { |
| 142 CheckCall(true_value(), a, b); |
| 143 } |
| 144 |
| 145 void CheckTrue(Handle<Object> a) { |
| 146 CheckCall(true_value(), a, undefined()); |
| 147 } |
| 148 |
| 149 void CheckTrue(double a, double b) { |
| 150 CheckCall(true_value(), Val(a), Val(b)); |
| 151 } |
| 152 |
| 153 void CheckFalse(Handle<Object> a, Handle<Object> b) { |
| 154 CheckCall(false_value(), a, b); |
| 155 } |
| 156 |
| 157 void CheckFalse(Handle<Object> a) { |
| 158 CheckCall(false_value(), a, undefined()); |
| 159 } |
| 160 |
| 161 void CheckFalse(double a, double b) { |
| 162 CheckCall(false_value(), Val(a), Val(b)); |
| 163 } |
| 164 |
| 165 Handle<JSFunction> NewFunction(const char* source) { |
| 166 return v8::Utils::OpenHandle( |
| 167 *v8::Handle<v8::Function>::Cast(CompileRun(source))); |
| 168 } |
| 169 |
| 170 Handle<JSObject> NewObject(const char* source) { |
| 171 return v8::Utils::OpenHandle( |
| 172 *v8::Handle<v8::Object>::Cast(CompileRun(source))); |
| 173 } |
| 174 |
| 175 Handle<String> Val(const char* string) { |
| 176 return isolate->factory()->InternalizeUtf8String(string); |
| 177 } |
| 178 |
| 179 Handle<Object> Val(double value) { |
| 180 return isolate->factory()->NewNumber(value); |
| 181 } |
| 182 |
| 183 Handle<Object> infinity() { |
| 184 return isolate->factory()->infinity_value(); |
| 185 } |
| 186 |
| 187 Handle<Object> minus_infinity() { |
| 188 return Val(-V8_INFINITY); |
| 189 } |
| 190 |
| 191 Handle<Object> nan() { |
| 192 return isolate->factory()->nan_value(); |
| 193 } |
| 194 |
| 195 Handle<Object> undefined() { |
| 196 return isolate->factory()->undefined_value(); |
| 197 } |
| 198 |
| 199 Handle<Object> null() { |
| 200 return isolate->factory()->null_value(); |
| 201 } |
| 202 |
| 203 Handle<Object> true_value() { |
| 204 return isolate->factory()->true_value(); |
| 205 } |
| 206 |
| 207 Handle<Object> false_value() { |
| 208 return isolate->factory()->false_value(); |
| 209 } |
| 210 }; |
| 211 |
| 212 } } } // namespace v8::internal::compiler |
| 213 |
| 214 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
OLD | NEW |