17d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
27d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
37d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// found in the LICENSE file.
47d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
57d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
67d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
77d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
87d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/v8.h"
97d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "test/cctest/cctest.h"
107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler.h"
127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/pipeline.h"
137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/execution.h"
147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/full-codegen.h"
157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/handles.h"
167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/objects-inl.h"
177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/parser.h"
187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/rewriter.h"
197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/scopes.h"
207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define USE_CRANKSHAFT 0
227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace v8 {
247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace internal {
257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace compiler {
267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass FunctionTester : public InitializedHandleScope {
287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
29c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org  explicit FunctionTester(const char* source, uint32_t flags = 0)
307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : isolate(main_isolate()),
31a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org        function((FLAG_allow_natives_syntax = true, NewFunction(source))),
32c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org        flags_(flags) {
337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Compile(function);
34c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org    const uint32_t supported_flags = CompilationInfo::kContextSpecializing |
35c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org                                     CompilationInfo::kInliningEnabled |
36c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org                                     CompilationInfo::kTypingEnabled;
37c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org    CHECK_EQ(0, flags_ & ~supported_flags);
387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Isolate* isolate;
417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<JSFunction> function;
427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<JSFunction> Compile(Handle<JSFunction> function) {
447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#if V8_TURBOFAN_TARGET
457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CompilationInfoWithZone info(function);
467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(Parser::Parse(&info));
487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
49c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org    if (flags_ & CompilationInfo::kContextSpecializing) {
50c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org      info.MarkAsContextSpecializing();
51c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org    }
52c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org    if (flags_ & CompilationInfo::kInliningEnabled) {
53c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org      info.MarkAsInliningEnabled();
54c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org    }
55c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    if (flags_ & CompilationInfo::kTypingEnabled) {
56c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org      info.MarkAsTypingEnabled();
57c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    }
587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(Rewriter::Rewrite(&info));
597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(Scope::Analyze(&info));
60a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    CHECK(Compiler::EnsureDeoptimizationSupport(&info));
617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Pipeline pipeline(&info);
637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<Code> code = pipeline.GenerateCode();
649e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.org    if (FLAG_turbo_deoptimization) {
659e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.org      info.context()->native_context()->AddOptimizedCode(*code);
669e2b466e4b4a2026caefa79afe6737f1bad83a19machenbach@chromium.org    }
677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(!code.is_null());
697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    function->ReplaceCode(*code);
707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#elif USE_CRANKSHAFT
717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<Code> unoptimized = Handle<Code>(function->code());
727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized,
737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                                   Compiler::NOT_CONCURRENT);
747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(!code.is_null());
757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#if ENABLE_DISASSEMBLER
767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (FLAG_print_opt_code) {
777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      code->Disassemble("test code", tracing_scope.file());
797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#endif
817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    function->ReplaceCode(*code);
827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#endif
837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return function;
847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<Object> args[] = {a, b};
887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Execution::Call(isolate, function, undefined(), 2, args, false);
897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckThrows(Handle<Object> a, Handle<Object> b) {
927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    TryCatch try_catch;
937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    MaybeHandle<Object> no_result = Call(a, b);
947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(isolate->has_pending_exception());
957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(try_catch.HasCaught());
967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(no_result.is_null());
977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(mstarzinger): Temporary workaround for issue chromium:362388.
987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    isolate->OptionalRescheduleException(true);
997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  v8::Handle<v8::Message> CheckThrowsReturnMessage(Handle<Object> a,
1027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                                   Handle<Object> b) {
1037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    TryCatch try_catch;
1047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    MaybeHandle<Object> no_result = Call(a, b);
1057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(isolate->has_pending_exception());
1067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(try_catch.HasCaught());
1077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(no_result.is_null());
1087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(mstarzinger): Calling OptionalRescheduleException is a dirty hack,
1097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // it's the only way to make Message() not to assert because an external
1107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // exception has been caught by the try_catch.
1117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    isolate->OptionalRescheduleException(true);
1127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return try_catch.Message();
1137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b) {
1167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Handle<Object> result = Call(a, b).ToHandleChecked();
1177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CHECK(expected->SameValue(*result));
1187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckCall(Handle<Object> expected, Handle<Object> a) {
1217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(expected, a, undefined());
1227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckCall(Handle<Object> expected) {
1257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(expected, undefined(), undefined());
1267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckCall(double expected, double a, double b) {
1297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(Val(expected), Val(a), Val(b));
1307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckTrue(Handle<Object> a, Handle<Object> b) {
1337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(true_value(), a, b);
1347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckTrue(Handle<Object> a) { CheckCall(true_value(), a, undefined()); }
1377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckTrue(double a, double b) {
1397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(true_value(), Val(a), Val(b));
1407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckFalse(Handle<Object> a, Handle<Object> b) {
1437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(false_value(), a, b);
1447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckFalse(Handle<Object> a) {
1477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(false_value(), a, undefined());
1487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void CheckFalse(double a, double b) {
1517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CheckCall(false_value(), Val(a), Val(b));
1527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<JSFunction> NewFunction(const char* source) {
1557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return v8::Utils::OpenHandle(
1567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        *v8::Handle<v8::Function>::Cast(CompileRun(source)));
1577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<JSObject> NewObject(const char* source) {
1607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return v8::Utils::OpenHandle(
1617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        *v8::Handle<v8::Object>::Cast(CompileRun(source)));
1627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<String> Val(const char* string) {
1657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return isolate->factory()->InternalizeUtf8String(string);
1667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> Val(double value) {
1697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return isolate->factory()->NewNumber(value);
1707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> infinity() { return isolate->factory()->infinity_value(); }
1737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> minus_infinity() { return Val(-V8_INFINITY); }
1757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> nan() { return isolate->factory()->nan_value(); }
1777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> undefined() { return isolate->factory()->undefined_value(); }
1797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> null() { return isolate->factory()->null_value(); }
1817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> true_value() { return isolate->factory()->true_value(); }
1837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<Object> false_value() { return isolate->factory()->false_value(); }
185a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
186a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org private:
187c714f377950c6a8a80b90ddca93ad8bd23ce362amachenbach@chromium.org  uint32_t flags_;
1887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
1897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
1917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace v8::internal::compiler
1927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#endif  // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_
194