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(function, unoptimized, |
| 60 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, function, undefined(), 2, args, false); |
| 93 } |
| 94 |
| 95 void CheckThrows(Handle<Object> a, Handle<Object> b) { |
| 96 TryCatch try_catch; |
| 97 MaybeHandle<Object> no_result = Call(a, b); |
| 98 CHECK(isolate->has_pending_exception()); |
| 99 CHECK(try_catch.HasCaught()); |
| 100 CHECK(no_result.is_null()); |
| 101 // TODO(mstarzinger): Temporary workaround for issue chromium:362388. |
| 102 isolate->OptionalRescheduleException(true); |
| 103 } |
| 104 |
| 105 v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a, |
| 106 Handle<Object> b) { |
| 107 TryCatch try_catch; |
| 108 MaybeHandle<Object> no_result = Call(a, b); |
| 109 CHECK(isolate->has_pending_exception()); |
| 110 CHECK(try_catch.HasCaught()); |
| 111 CHECK(no_result.is_null()); |
| 112 // TODO(mstarzinger): Calling OptionalRescheduleException is a dirty hack, |
| 113 // it's the only way to make Message() not to assert because an external |
| 114 // exception has been caught by the try_catch. |
| 115 isolate->OptionalRescheduleException(true); |
| 116 return try_catch.Message(); |
| 117 } |
| 118 |
| 119 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) { |
| 120 Handle<Object> result = Call(a, b).ToHandleChecked(); |
| 121 CHECK(expected->SameValue(*result)); |
| 122 } |
| 123 |
| 124 void CheckCall(Handle<Object> expected, Handle<Object> a) { |
| 125 CheckCall(expected, a, undefined()); |
| 126 } |
| 127 |
| 128 void CheckCall(Handle<Object> expected) { |
| 129 CheckCall(expected, undefined(), undefined()); |
| 130 } |
| 131 |
| 132 void CheckCall(double expected, double a, double b) { |
| 133 CheckCall(Val(expected), Val(a), Val(b)); |
| 134 } |
| 135 |
| 136 void CheckTrue(Handle<Object> a, Handle<Object> b) { |
| 137 CheckCall(true_value(), a, b); |
| 138 } |
| 139 |
| 140 void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); } |
| 141 |
| 142 void CheckTrue(double a, double b) { |
| 143 CheckCall(true_value(), Val(a), Val(b)); |
| 144 } |
| 145 |
| 146 void CheckFalse(Handle<Object> a, Handle<Object> b) { |
| 147 CheckCall(false_value(), a, b); |
| 148 } |
| 149 |
| 150 void CheckFalse(Handle<Object> a) { |
| 151 CheckCall(false_value(), a, undefined()); |
| 152 } |
| 153 |
| 154 void CheckFalse(double a, double b) { |
| 155 CheckCall(false_value(), Val(a), Val(b)); |
| 156 } |
| 157 |
| 158 Handle<JSFunction> NewFunction(const char* source) { |
| 159 return v8::Utils::OpenHandle( |
| 160 *v8::Handle<v8::Function>::Cast(CompileRun(source))); |
| 161 } |
| 162 |
| 163 Handle<JSObject> NewObject(const char* source) { |
| 164 return v8::Utils::OpenHandle( |
| 165 *v8::Handle<v8::Object>::Cast(CompileRun(source))); |
| 166 } |
| 167 |
| 168 Handle<String> Val(const char* string) { |
| 169 return isolate->factory()->InternalizeUtf8String(string); |
| 170 } |
| 171 |
| 172 Handle<Object> Val(double value) { |
| 173 return isolate->factory()->NewNumber(value); |
| 174 } |
| 175 |
| 176 Handle<Object> infinity() { return isolate->factory()->infinity_value(); } |
| 177 |
| 178 Handle<Object> minus_infinity() { return Val(-V8_INFINITY); } |
| 179 |
| 180 Handle<Object> nan() { return isolate->factory()->nan_value(); } |
| 181 |
| 182 Handle<Object> undefined() { return isolate->factory()->undefined_value(); } |
| 183 |
| 184 Handle<Object> null() { return isolate->factory()->null_value(); } |
| 185 |
| 186 Handle<Object> true_value() { return isolate->factory()->true_value(); } |
| 187 |
| 188 Handle<Object> false_value() { return isolate->factory()->false_value(); } |
| 189 }; |
| 190 } |
| 191 } |
| 192 } // namespace v8::internal::compiler |
| 193 |
| 194 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
OLD | NEW |