Home | History | Annotate | Download | only in compiler
      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, uint32_t flags = 0)
     30       : isolate(main_isolate()),
     31         function((FLAG_allow_natives_syntax = true, NewFunction(source))),
     32         flags_(flags) {
     33     Compile(function);
     34     const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
     35                                      CompilationInfo::kInliningEnabled |
     36                                      CompilationInfo::kTypingEnabled;
     37     CHECK_EQ(0, flags_ & ~supported_flags);
     38   }
     39 
     40   Isolate* isolate;
     41   Handle<JSFunction> function;
     42 
     43   Handle<JSFunction> Compile(Handle<JSFunction> function) {
     44 #if V8_TURBOFAN_TARGET
     45     CompilationInfoWithZone info(function);
     46 
     47     CHECK(Parser::Parse(&info));
     48     info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
     49     if (flags_ & CompilationInfo::kContextSpecializing) {
     50       info.MarkAsContextSpecializing();
     51     }
     52     if (flags_ & CompilationInfo::kInliningEnabled) {
     53       info.MarkAsInliningEnabled();
     54     }
     55     if (flags_ & CompilationInfo::kTypingEnabled) {
     56       info.MarkAsTypingEnabled();
     57     }
     58     CHECK(Rewriter::Rewrite(&info));
     59     CHECK(Scope::Analyze(&info));
     60     CHECK(Compiler::EnsureDeoptimizationSupport(&info));
     61 
     62     Pipeline pipeline(&info);
     63     Handle<Code> code = pipeline.GenerateCode();
     64     if (FLAG_turbo_deoptimization) {
     65       info.context()->native_context()->AddOptimizedCode(*code);
     66     }
     67 
     68     CHECK(!code.is_null());
     69     function->ReplaceCode(*code);
     70 #elif USE_CRANKSHAFT
     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());
     79     }
     80 #endif
     81     function->ReplaceCode(*code);
     82 #endif
     83     return function;
     84   }
     85 
     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);
     89   }
     90 
     91   void CheckThrows(Handle<Object> a, Handle<Object> b) {
     92     TryCatch try_catch;
     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);
     99   }
    100 
    101   v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
    102                                                    Handle<Object> b) {
    103     TryCatch try_catch;
    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();
    113   }
    114 
    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));
    118   }
    119 
    120   void CheckCall(Handle<Object> expected, Handle<Object> a) {
    121     CheckCall(expected, a, undefined());
    122   }
    123 
    124   void CheckCall(Handle<Object> expected) {
    125     CheckCall(expected, undefined(), undefined());
    126   }
    127 
    128   void CheckCall(double expected, double a, double b) {
    129     CheckCall(Val(expected), Val(a), Val(b));
    130   }
    131 
    132   void CheckTrue(Handle<Object> a, Handle<Object> b) {
    133     CheckCall(true_value(), a, b);
    134   }
    135 
    136   void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
    137 
    138   void CheckTrue(double a, double b) {
    139     CheckCall(true_value(), Val(a), Val(b));
    140   }
    141 
    142   void CheckFalse(Handle<Object> a, Handle<Object> b) {
    143     CheckCall(false_value(), a, b);
    144   }
    145 
    146   void CheckFalse(Handle<Object> a) {
    147     CheckCall(false_value(), a, undefined());
    148   }
    149 
    150   void CheckFalse(double a, double b) {
    151     CheckCall(false_value(), Val(a), Val(b));
    152   }
    153 
    154   Handle<JSFunction> NewFunction(const char* source) {
    155     return v8::Utils::OpenHandle(
    156         *v8::Handle<v8::Function>::Cast(CompileRun(source)));
    157   }
    158 
    159   Handle<JSObject> NewObject(const char* source) {
    160     return v8::Utils::OpenHandle(
    161         *v8::Handle<v8::Object>::Cast(CompileRun(source)));
    162   }
    163 
    164   Handle<String> Val(const char* string) {
    165     return isolate->factory()->InternalizeUtf8String(string);
    166   }
    167 
    168   Handle<Object> Val(double value) {
    169     return isolate->factory()->NewNumber(value);
    170   }
    171 
    172   Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
    173 
    174   Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
    175 
    176   Handle<Object> nan() { return isolate->factory()->nan_value(); }
    177 
    178   Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
    179 
    180   Handle<Object> null() { return isolate->factory()->null_value(); }
    181 
    182   Handle<Object> true_value() { return isolate->factory()->true_value(); }
    183 
    184   Handle<Object> false_value() { return isolate->factory()->false_value(); }
    185 
    186  private:
    187   uint32_t flags_;
    188 };
    189 }
    190 }
    191 }  // namespace v8::internal::compiler
    192 
    193 #endif  // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
    194