LCOV - code coverage report
Current view: top level - test/unittests - background-compile-task-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 86 86 100.0 %
Date: 2019-04-17 Functions: 28 29 96.6 %

          Line data    Source code
       1             : // Copyright 2018 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             : #include <memory>
       6             : 
       7             : #include "include/v8.h"
       8             : #include "src/api-inl.h"
       9             : #include "src/ast/ast.h"
      10             : #include "src/ast/scopes.h"
      11             : #include "src/base/platform/semaphore.h"
      12             : #include "src/base/template-utils.h"
      13             : #include "src/compiler.h"
      14             : #include "src/flags.h"
      15             : #include "src/isolate-inl.h"
      16             : #include "src/objects/smi.h"
      17             : #include "src/parsing/parse-info.h"
      18             : #include "src/parsing/parser.h"
      19             : #include "src/parsing/preparse-data.h"
      20             : #include "src/v8.h"
      21             : #include "src/zone/zone-list-inl.h"
      22             : #include "test/unittests/test-helpers.h"
      23             : #include "test/unittests/test-utils.h"
      24             : #include "testing/gtest/include/gtest/gtest.h"
      25             : 
      26             : namespace v8 {
      27             : namespace internal {
      28             : 
      29             : class BackgroundCompileTaskTest : public TestWithNativeContext {
      30             :  public:
      31          14 :   BackgroundCompileTaskTest() : allocator_(isolate()->allocator()) {}
      32          14 :   ~BackgroundCompileTaskTest() override = default;
      33             : 
      34             :   AccountingAllocator* allocator() { return allocator_; }
      35             : 
      36           7 :   static void SetUpTestCase() {
      37           7 :     CHECK_NULL(save_flags_);
      38           7 :     save_flags_ = new SaveFlags();
      39             :     TestWithNativeContext::SetUpTestCase();
      40           7 :   }
      41             : 
      42           7 :   static void TearDownTestCase() {
      43             :     TestWithNativeContext::TearDownTestCase();
      44           7 :     CHECK_NOT_NULL(save_flags_);
      45           7 :     delete save_flags_;
      46           7 :     save_flags_ = nullptr;
      47           7 :   }
      48             : 
      49           7 :   BackgroundCompileTask* NewBackgroundCompileTask(
      50             :       Isolate* isolate, Handle<SharedFunctionInfo> shared,
      51             :       size_t stack_size = FLAG_stack_size) {
      52             :     std::unique_ptr<ParseInfo> outer_parse_info =
      53          14 :         test::OuterParseInfoForShared(isolate, shared);
      54             :     AstValueFactory* ast_value_factory =
      55           7 :         outer_parse_info->GetOrCreateAstValueFactory();
      56             :     AstNodeFactory ast_node_factory(ast_value_factory,
      57           7 :                                     outer_parse_info->zone());
      58             : 
      59             :     const AstRawString* function_name =
      60           7 :         ast_value_factory->GetOneByteString("f");
      61             :     DeclarationScope* script_scope = new (outer_parse_info->zone())
      62           7 :         DeclarationScope(outer_parse_info->zone(), ast_value_factory);
      63             :     DeclarationScope* function_scope =
      64             :         new (outer_parse_info->zone()) DeclarationScope(
      65           7 :             outer_parse_info->zone(), script_scope, FUNCTION_SCOPE);
      66          14 :     function_scope->set_start_position(shared->StartPosition());
      67          14 :     function_scope->set_end_position(shared->EndPosition());
      68             :     std::vector<void*> buffer;
      69             :     ScopedPtrList<Statement> statements(&buffer);
      70             :     const FunctionLiteral* function_literal =
      71          21 :         ast_node_factory.NewFunctionLiteral(
      72             :             function_name, function_scope, statements, -1, -1, -1,
      73             :             FunctionLiteral::kNoDuplicateParameters,
      74             :             FunctionLiteral::kAnonymousExpression,
      75             :             FunctionLiteral::kShouldEagerCompile, shared->StartPosition(), true,
      76           7 :             shared->FunctionLiteralId(isolate), nullptr);
      77             : 
      78             :     return new BackgroundCompileTask(
      79             :         allocator(), outer_parse_info.get(), function_name, function_literal,
      80             :         isolate->counters()->worker_thread_runtime_call_stats(),
      81          14 :         isolate->counters()->compile_function_on_background(), FLAG_stack_size);
      82             :   }
      83             : 
      84             :  private:
      85             :   AccountingAllocator* allocator_;
      86             :   static SaveFlags* save_flags_;
      87             : 
      88             :   DISALLOW_COPY_AND_ASSIGN(BackgroundCompileTaskTest);
      89             : };
      90             : 
      91             : SaveFlags* BackgroundCompileTaskTest::save_flags_ = nullptr;
      92             : 
      93       15445 : TEST_F(BackgroundCompileTaskTest, Construct) {
      94             :   Handle<SharedFunctionInfo> shared =
      95           1 :       test::CreateSharedFunctionInfo(isolate(), nullptr);
      96           2 :   ASSERT_FALSE(shared->is_compiled());
      97             :   std::unique_ptr<BackgroundCompileTask> task(
      98           3 :       NewBackgroundCompileTask(isolate(), shared));
      99             : }
     100             : 
     101       15445 : TEST_F(BackgroundCompileTaskTest, SyntaxError) {
     102           1 :   test::ScriptResource* script = new test::ScriptResource("^^^", strlen("^^^"));
     103             :   Handle<SharedFunctionInfo> shared =
     104           1 :       test::CreateSharedFunctionInfo(isolate(), script);
     105             :   std::unique_ptr<BackgroundCompileTask> task(
     106           3 :       NewBackgroundCompileTask(isolate(), shared));
     107             : 
     108           1 :   task->Run();
     109           2 :   ASSERT_FALSE(Compiler::FinalizeBackgroundCompileTask(
     110             :       task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
     111           1 :   ASSERT_TRUE(isolate()->has_pending_exception());
     112             : 
     113             :   isolate()->clear_pending_exception();
     114             : }
     115             : 
     116       15445 : TEST_F(BackgroundCompileTaskTest, CompileAndRun) {
     117             :   const char raw_script[] =
     118             :       "function g() {\n"
     119             :       "  f = function(a) {\n"
     120             :       "        for (var i = 0; i < 3; i++) { a += 20; }\n"
     121             :       "        return a;\n"
     122             :       "      }\n"
     123             :       "  return f;\n"
     124             :       "}\n"
     125           1 :       "g();";
     126             :   test::ScriptResource* script =
     127           1 :       new test::ScriptResource(raw_script, strlen(raw_script));
     128             :   Handle<JSFunction> f = RunJS<JSFunction>(script);
     129             :   Handle<SharedFunctionInfo> shared = handle(f->shared(), isolate());
     130           2 :   ASSERT_FALSE(shared->is_compiled());
     131             :   std::unique_ptr<BackgroundCompileTask> task(
     132           3 :       NewBackgroundCompileTask(isolate(), shared));
     133             : 
     134           1 :   task->Run();
     135           2 :   ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
     136             :       task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
     137           2 :   ASSERT_TRUE(shared->is_compiled());
     138             : 
     139             :   Smi value = Smi::cast(*RunJS("f(100);"));
     140           1 :   ASSERT_TRUE(value == Smi::FromInt(160));
     141             : }
     142             : 
     143       15445 : TEST_F(BackgroundCompileTaskTest, CompileFailure) {
     144           1 :   std::string raw_script("() { var a = ");
     145       20001 :   for (int i = 0; i < 10000; i++) {
     146             :     // TODO(leszeks): Figure out a more "unit-test-y" way of forcing an analysis
     147             :     // failure than a binop stack overflow.
     148             : 
     149             :     // Alternate + and - to avoid n-ary operation nodes.
     150             :     raw_script += "'x' + 'x' - ";
     151             :   }
     152             :   raw_script += " 'x'; }";
     153             :   test::ScriptResource* script =
     154           1 :       new test::ScriptResource(raw_script.c_str(), strlen(raw_script.c_str()));
     155             :   Handle<SharedFunctionInfo> shared =
     156           1 :       test::CreateSharedFunctionInfo(isolate(), script);
     157             :   std::unique_ptr<BackgroundCompileTask> task(
     158           2 :       NewBackgroundCompileTask(isolate(), shared, 100));
     159             : 
     160           1 :   task->Run();
     161           2 :   ASSERT_FALSE(Compiler::FinalizeBackgroundCompileTask(
     162             :       task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
     163           1 :   ASSERT_TRUE(isolate()->has_pending_exception());
     164             : 
     165             :   isolate()->clear_pending_exception();
     166             : }
     167             : 
     168             : class CompileTask : public Task {
     169             :  public:
     170             :   CompileTask(BackgroundCompileTask* task, base::Semaphore* semaphore)
     171           1 :       : task_(task), semaphore_(semaphore) {}
     172           2 :   ~CompileTask() override = default;
     173             : 
     174           1 :   void Run() override {
     175           1 :     task_->Run();
     176           1 :     semaphore_->Signal();
     177           1 :   }
     178             : 
     179             :  private:
     180             :   BackgroundCompileTask* task_;
     181             :   base::Semaphore* semaphore_;
     182             :   DISALLOW_COPY_AND_ASSIGN(CompileTask);
     183             : };
     184             : 
     185       15445 : TEST_F(BackgroundCompileTaskTest, CompileOnBackgroundThread) {
     186             :   const char* raw_script =
     187             :       "(a, b) {\n"
     188             :       "  var c = a + b;\n"
     189             :       "  function bar() { return b }\n"
     190             :       "  var d = { foo: 100, bar : bar() }\n"
     191             :       "  return bar;"
     192             :       "}";
     193             :   test::ScriptResource* script =
     194           1 :       new test::ScriptResource(raw_script, strlen(raw_script));
     195             :   Handle<SharedFunctionInfo> shared =
     196           1 :       test::CreateSharedFunctionInfo(isolate(), script);
     197             :   std::unique_ptr<BackgroundCompileTask> task(
     198           3 :       NewBackgroundCompileTask(isolate(), shared));
     199             : 
     200           2 :   base::Semaphore semaphore(0);
     201             :   auto background_task = base::make_unique<CompileTask>(task.get(), &semaphore);
     202             : 
     203           3 :   V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(background_task));
     204           1 :   semaphore.Wait();
     205           2 :   ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
     206             :       task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
     207           2 :   ASSERT_TRUE(shared->is_compiled());
     208             : }
     209             : 
     210       15445 : TEST_F(BackgroundCompileTaskTest, EagerInnerFunctions) {
     211             :   const char raw_script[] =
     212             :       "function g() {\n"
     213             :       "  f = function() {\n"
     214             :       "    // Simulate an eager IIFE with brackets.\n "
     215             :       "    var e = (function () { return 42; });\n"
     216             :       "    return e;\n"
     217             :       "  }\n"
     218             :       "  return f;\n"
     219             :       "}\n"
     220           1 :       "g();";
     221             :   test::ScriptResource* script =
     222           1 :       new test::ScriptResource(raw_script, strlen(raw_script));
     223             :   Handle<JSFunction> f = RunJS<JSFunction>(script);
     224             :   Handle<SharedFunctionInfo> shared = handle(f->shared(), isolate());
     225           2 :   ASSERT_FALSE(shared->is_compiled());
     226             :   std::unique_ptr<BackgroundCompileTask> task(
     227           3 :       NewBackgroundCompileTask(isolate(), shared));
     228             : 
     229           1 :   task->Run();
     230           2 :   ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
     231             :       task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
     232           2 :   ASSERT_TRUE(shared->is_compiled());
     233             : 
     234             :   Handle<JSFunction> e = RunJS<JSFunction>("f();");
     235             : 
     236           2 :   ASSERT_TRUE(e->shared()->is_compiled());
     237             : }
     238             : 
     239       15445 : TEST_F(BackgroundCompileTaskTest, LazyInnerFunctions) {
     240             :   const char raw_script[] =
     241             :       "function g() {\n"
     242             :       "  f = function() {\n"
     243             :       "    function e() { return 42; };\n"
     244             :       "    return e;\n"
     245             :       "  }\n"
     246             :       "  return f;\n"
     247             :       "}\n"
     248           1 :       "g();";
     249             :   test::ScriptResource* script =
     250           1 :       new test::ScriptResource(raw_script, strlen(raw_script));
     251             :   Handle<JSFunction> f = RunJS<JSFunction>(script);
     252             :   Handle<SharedFunctionInfo> shared = handle(f->shared(), isolate());
     253           2 :   ASSERT_FALSE(shared->is_compiled());
     254             :   std::unique_ptr<BackgroundCompileTask> task(
     255           3 :       NewBackgroundCompileTask(isolate(), shared));
     256             : 
     257           1 :   task->Run();
     258           2 :   ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
     259             :       task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
     260           2 :   ASSERT_TRUE(shared->is_compiled());
     261             : 
     262             :   Handle<JSFunction> e = RunJS<JSFunction>("f();");
     263             : 
     264           2 :   ASSERT_FALSE(e->shared()->is_compiled());
     265             : }
     266             : 
     267             : }  // namespace internal
     268        9264 : }  // namespace v8

Generated by: LCOV version 1.10