compiler.h 9.96 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_COMPILER_H_
#define V8_COMPILER_H_

8 9
#include <memory>

10
#include "src/allocation.h"
11
#include "src/bailout-reason.h"
12 13
#include "src/contexts.h"
#include "src/isolate.h"
14
#include "src/zone/zone.h"
15

16 17
namespace v8 {
namespace internal {
18

19
// Forward declarations.
20
class CompilationInfo;
21
class CompilationJob;
22
class JavaScriptFrame;
23 24
class ParseInfo;
class ScriptData;
25 26 27 28
template <typename T>
class ThreadedList;
template <typename T>
class ThreadedListZoneEntry;
29

30 31 32 33 34 35 36 37 38 39
// The V8 compiler API.
//
// This is the central hub for dispatching to the various compilers within V8.
// Logic for which compiler to choose and how to wire compilation results into
// the object heap should be kept inside this class.
//
// General strategy: Scripts are translated into anonymous functions w/o
// parameters which then can be executed. If the source code contains other
// functions, they might be compiled and allocated as part of the compilation
// of the source code or deferred for lazy compilation at a later point.
40
class V8_EXPORT_PRIVATE Compiler : public AllStatic {
41 42 43
 public:
  enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
  enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
44
  enum CompilationTier { INTERPRETED, BASELINE, OPTIMIZED };
45 46 47 48 49 50 51 52

  // ===========================================================================
  // The following family of methods ensures a given function is compiled. The
  // general contract is that failures will be reported by returning {false},
  // whereas successful compilation ensures the {is_compiled} predicate on the
  // given function holds (except for live-edit, which compiles the world).

  static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
53
  static bool CompileBaseline(Handle<JSFunction> function);
54 55
  static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
  static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
56
  static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
57

58
  // Prepare a compilation job for unoptimized code. Requires ParseAndAnalyse.
59
  static CompilationJob* PrepareUnoptimizedCompilationJob(
60
      CompilationInfo* info);
61

62
  // Generate and install code from previously queued compilation job.
63
  static bool FinalizeCompilationJob(CompilationJob* job);
64 65 66 67 68 69

  // Give the compiler a chance to perform low-latency initialization tasks of
  // the given {function} on its instantiation. Note that only the runtime will
  // offer this chance, optimized closure instantiation will not call this.
  static void PostInstantiation(Handle<JSFunction> function, PretenureFlag);

70 71 72
  typedef ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>
      EagerInnerFunctionLiterals;

73 74
  // Parser::Parse, then Compiler::Analyze.
  static bool ParseAndAnalyze(ParseInfo* info);
75 76 77 78
  // Rewrite, analyze scopes, and renumber. If |eager_literals| is non-null, it
  // is appended with inner function literals which should be eagerly compiled.
  static bool Analyze(ParseInfo* info,
                      EagerInnerFunctionLiterals* eager_literals = nullptr);
79 80
  // Adds deoptimization support, requires ParseAndAnalyze.
  static bool EnsureDeoptimizationSupport(CompilationInfo* info);
81 82 83 84 85 86
  // Ensures that bytecode is generated, calls ParseAndAnalyze internally.
  static bool EnsureBytecode(CompilationInfo* info);

  // The next compilation tier which the function should  be compiled to for
  // optimization. This is used as a hint by the runtime profiler.
  static CompilationTier NextCompilationTier(JSFunction* function);
87 88 89 90 91 92 93 94 95 96 97 98 99 100

  // ===========================================================================
  // The following family of methods instantiates new functions for scripts or
  // function literals. The decision whether those functions will be compiled,
  // is left to the discretion of the compiler.
  //
  // Please note this interface returns shared function infos.  This means you
  // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
  // real function with a context.

  // Create a (bound) function for a String source within a context for eval.
  MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
      Handle<String> source, Handle<SharedFunctionInfo> outer_info,
      Handle<Context> context, LanguageMode language_mode,
101 102 103
      ParseRestriction restriction, int parameters_end_pos,
      int eval_scope_position, int eval_position, int line_offset = 0,
      int column_offset = 0, Handle<Object> script_name = Handle<Object>(),
104 105
      ScriptOriginOptions options = ScriptOriginOptions());

106 107 108
  // Create a (bound) function for a String source within a context for eval.
  MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
      Handle<Context> context, Handle<String> source,
109
      ParseRestriction restriction, int parameters_end_pos);
110

111 112 113 114 115 116 117
  // Create a shared function info object for a String source within a context.
  static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
      Handle<String> source, Handle<Object> script_name, int line_offset,
      int column_offset, ScriptOriginOptions resource_options,
      Handle<Object> source_map_url, Handle<Context> context,
      v8::Extension* extension, ScriptData** cached_data,
      ScriptCompiler::CompileOptions compile_options,
118
      NativesFlag is_natives_code);
119 120 121 122 123 124 125 126

  // Create a shared function info object for a Script that has already been
  // parsed while the script was being loaded from a streamed source.
  static Handle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
      Handle<Script> script, ParseInfo* info, int source_length);

  // Create a shared function info object (the code may be lazily compiled).
  static Handle<SharedFunctionInfo> GetSharedFunctionInfo(
127
      FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer);
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

  // Create a shared function info object for a native function literal.
  static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
      v8::Extension* extension, Handle<String> name);

  // ===========================================================================
  // The following family of methods provides support for OSR. Code generated
  // for entry via OSR might not be suitable for normal entry, hence will be
  // returned directly to the caller.
  //
  // Please note this interface is the only part dealing with {Code} objects
  // directly. Other methods are agnostic to {Code} and can use an interpreter
  // instead of generating JIT code for a function at all.

  // Generate and return optimized code for OSR, or empty handle on failure.
  MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
      Handle<JSFunction> function, BailoutId osr_ast_id,
      JavaScriptFrame* osr_frame);
};
147

148 149 150
// A base class for compilation jobs intended to run concurrent to the main
// thread. The job is split into three phases which are called in sequence on
// different threads and with different limitations:
151 152 153
//  1) PrepareJob:   Runs on main thread. No major limitations.
//  2) ExecuteJob:   Runs concurrently. No heap allocation or handle derefs.
//  3) FinalizeJob:  Runs on main thread. No dependency changes.
154
//
155 156
// Each of the three phases can either fail or succeed. The current state of
// the job can be checked using {state()}.
157
class V8_EXPORT_PRIVATE CompilationJob {
158
 public:
159 160 161 162 163 164 165 166 167
  enum Status { SUCCEEDED, FAILED };
  enum class State {
    kReadyToPrepare,
    kReadyToExecute,
    kReadyToFinalize,
    kSucceeded,
    kFailed,
  };

168 169
  CompilationJob(Isolate* isolate, CompilationInfo* info,
                 const char* compiler_name,
170
                 State initial_state = State::kReadyToPrepare);
171
  virtual ~CompilationJob() {}
172

173 174
  // Prepare the compile job. Must be called on the main thread.
  MUST_USE_RESULT Status PrepareJob();
175

176 177
  // Executes the compile job. Can be called on a background thread if
  // can_execute_on_background_thread() returns true.
178
  MUST_USE_RESULT Status ExecuteJob();
179

180 181
  // Finalizes the compile job. Must be called on the main thread.
  MUST_USE_RESULT Status FinalizeJob();
182

183 184
  // Report a transient failure, try again next time. Should only be called on
  // optimization compilation jobs.
185
  Status RetryOptimization(BailoutReason reason);
186

187 188
  // Report a persistent failure, disable future optimization on the function.
  // Should only be called on optimization compilation jobs.
189
  Status AbortOptimization(BailoutReason reason);
190

191 192 193 194 195 196 197
  void RecordOptimizedCompilationStats() const;
  void RecordUnoptimizedCompilationStats() const;

  virtual bool can_execute_on_background_thread() const { return true; }

  void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
  uintptr_t stack_limit() const { return stack_limit_; }
198

199 200 201 202 203
  bool executed_on_background_thread() const {
    DCHECK_IMPLIES(!can_execute_on_background_thread(),
                   !executed_on_background_thread_);
    return executed_on_background_thread_;
  }
204 205
  State state() const { return state_; }
  CompilationInfo* info() const { return info_; }
206
  Isolate* isolate() const;
207

208
 protected:
209
  // Overridden by the actual implementation.
210 211 212 213 214 215 216
  virtual Status PrepareJobImpl() = 0;
  virtual Status ExecuteJobImpl() = 0;
  virtual Status FinalizeJobImpl() = 0;

  // Registers weak object to optimized code dependencies.
  // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
  void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
217

218 219
 private:
  CompilationInfo* info_;
220
  ThreadId isolate_thread_id_;
221 222 223
  base::TimeDelta time_taken_to_prepare_;
  base::TimeDelta time_taken_to_execute_;
  base::TimeDelta time_taken_to_finalize_;
224
  const char* compiler_name_;
225
  State state_;
226
  uintptr_t stack_limit_;
227
  bool executed_on_background_thread_;
228 229 230 231 232 233 234 235

  MUST_USE_RESULT Status UpdateState(Status status, State next_state) {
    if (status == SUCCEEDED) {
      state_ = next_state;
    } else {
      state_ = State::kFailed;
    }
    return status;
236 237 238
  }
};

239 240
}  // namespace internal
}  // namespace v8
241 242

#endif  // V8_COMPILER_H_