v8/src/compiler.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

354 lines
14 KiB
C
Raw Normal View History

// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_H_
#define V8_COMPILER_H_
#include <forward_list>
#include <memory>
#include "src/allocation.h"
#include "src/bailout-reason.h"
#include "src/code-events.h"
#include "src/contexts.h"
#include "src/isolate.h"
#include "src/unicode-cache.h"
#include "src/zone/zone.h"
namespace v8 {
namespace internal {
// Forward declarations.
[turbofan] Reland "Add new JSFrameSpecialization reducer." and "Perform OSR deconstruction early and remove type propagation.". We have to reland these two commits at once, because the first breaks some asm.js benchmarks without the second. The change was reverted because of bogus checks in the verifier, which will not work in the presence of OSR (and where hidden because of the type back propagation hack in OSR so far). Original messages are below: [turbofan] Add new JSFrameSpecialization reducer. The JSFrameSpecialization specializes an OSR graph to the current unoptimized frame on which we will perform the on-stack replacement. This is used for asm.js functions, where we cannot reuse the OSR code object anyway because of context specialization, and so we could as well specialize to the max instead. It works by replacing all OsrValues in the graph with their values in the JavaScriptFrame. The idea is that using this trick we get better performance without doing the unsound backpropagation of types to OsrValues later. This is the first step towards fixing OSR for TurboFan. [turbofan] Perform OSR deconstruction early and remove type propagation. This way we don't have to deal with dead pre-OSR code in the graph and risk optimizing the wrong code, especially we don't make optimistic assumptions in the dead code that leaks into the OSR code (i.e. deopt guards are in dead code, but the types propagate to OSR code via the OsrValue type back propagation). BUG=v8:4273 LOG=n R=jarin@chromium.org Review URL: https://codereview.chromium.org/1226673005 Cr-Commit-Position: refs/heads/master@{#29486}
2015-07-06 11:11:15 +00:00
class JavaScriptFrame;
class OptimizedCompilationInfo;
class OptimizedCompilationJob;
class ParseInfo;
class Parser;
class ScriptData;
struct ScriptStreamingData;
class UnoptimizedCompilationInfo;
class UnoptimizedCompilationJob;
typedef std::forward_list<std::unique_ptr<UnoptimizedCompilationJob>>
UnoptimizedCompilationJobList;
// 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.
class V8_EXPORT_PRIVATE Compiler : public AllStatic {
public:
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
// ===========================================================================
// 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).
Reland "[Compiler] Remove CompileDebugCode and EnsureBytecode and replace with Compile" This is a reland of 21da12a98352e0e31f79d3ae1fa003cacb4ae32c Original change's description: > [Compiler] Remove CompileDebugCode and EnsureBytecode and replace with Compile > > Removes the Compiler::CompileDebugCode and Compiler::EnsureBytecode functions > and replaces them with a Compiler::Compile(Handle<SharedFunctionInfo> shared) > function. The code in compiler.cc is refactored to use this function to compile > the SharedFunctionInfo when compiling a JSFunction. > > Also does some other cleanup: > - Removes CompileUnoptimizedFunction and inlines into new Compiler function > - Moves code to create top level SharedFunctionInfo into CompilerTopLevel and > out of FinalizeUnoptimizedCompile. > > BUG=v8:6409 > > Change-Id: Ic54afcd8eb005c17f3ae6b2355060846e3091ca3 > Reviewed-on: https://chromium-review.googlesource.com/613760 > Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> > Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> > Reviewed-by: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Yang Guo <yangguo@chromium.org> > Cr-Commit-Position: refs/heads/master@{#47394} TBR=yangguo@chromium.org TBR=jarin@chromium.org Bug: v8:6409 Change-Id: If2eae66a85f129e746a5ca5c04935540f3f86b04 Reviewed-on: https://chromium-review.googlesource.com/618886 Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#47399}
2017-08-17 12:40:24 +00:00
static bool Compile(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
Reland "[debug] liveedit in native" This is a reland of 3dfaf8264f8abd3e101d5f2e72739c4e8475ff78 Original change's description: > [debug] liveedit in native > > Liveedit step-by-step: > 1. calculate diff between old source and new source, > 2. map function literals from old source to new source, > 3. create new script for new_source, > 4. mark literals with changed code as changed, all others as unchanged, > 5. check that for changed literals there are no: > - running generators in the heap, > - non droppable frames (e.g. running generator) above them on stack. > 6. mark the bottom most frame with changed function as scheduled for > restart if any. > 7. for unchanged functions: > - deoptimize, > - remove from cache, > - update source positions, > - move to new script, > - reset feedback information and preparsed scope information if any, > - replace any sfi in constant pool with changed one if any. > 8. for changed functions: > - deoptimize > - remove from cache, > - reset feedback information, > - update all links from js functions to old shared with new one. > 9. swap scripts. > > TBR=ulan@chromium.org > > Bug: v8:7862,v8:5713 > Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;luci.chromium.try:linux_chromium_rel_ng;master.tryserver.blink:linux_trusty_blink_rel > Change-Id: I8f6f6156318cc82d6f36d7ebc1c9f7d5f3aa1461 > Reviewed-on: https://chromium-review.googlesource.com/1105493 > Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> > Reviewed-by: Dmitry Gozman <dgozman@chromium.org> > Reviewed-by: Yang Guo <yangguo@chromium.org> > Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#54146} TBR=dgozman@chromium.org Bug: v8:7862, v8:5713 Change-Id: I163ed2fd2ca3115ba0de74cb35a6fac9e40fdd94 Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;luci.chromium.try:linux_chromium_rel_ng;master.tryserver.blink:linux_trusty_blink_rel Reviewed-on: https://chromium-review.googlesource.com/1124879 Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> Cr-Commit-Position: refs/heads/master@{#54187}
2018-07-03 17:16:35 +00:00
V8_WARN_UNUSED_RESULT static MaybeHandle<SharedFunctionInfo>
CompileForLiveEdit(ParseInfo* parse_info, Isolate* isolate);
// Creates a new task that when run will parse and compile the streamed
// script associated with |streaming_data| and can be finalized with
// Compiler::GetSharedFunctionInfoForStreamedScript.
// Note: does not take ownership of streaming_data.
static ScriptCompiler::ScriptStreamingTask* NewBackgroundCompileTask(
ScriptStreamingData* streaming_data, Isolate* isolate);
// Generate and install code from previously queued compilation job.
static bool FinalizeCompilationJob(UnoptimizedCompilationJob* job,
Handle<SharedFunctionInfo> shared_info,
Isolate* isolate);
static bool FinalizeCompilationJob(OptimizedCompilationJob* job,
Isolate* isolate);
// 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);
// Parser::Parse, then Compiler::Analyze.
static bool ParseAndAnalyze(ParseInfo* parse_info,
Handle<SharedFunctionInfo> shared_info,
Isolate* isolate);
// Rewrite and analyze scopes.
static bool Analyze(ParseInfo* parse_info);
// ===========================================================================
// 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.
V8_WARN_UNUSED_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Handle<Context> context, LanguageMode language_mode,
Implement new Function.prototype.toString --harmony-function-tostring For functions declared in source code, the .toString() representation will be an excerpt of the source code. * For functions declared with the "function" keyword, the excerpt starts at the "function" or "async" keyword and ends at the final "}". The previous behavior would start the excerpt at the "(" of the parameter list, and prepend a canonical `"function " + name` or similar, which would discard comments and formatting surrounding the function's name. Anonymous functions declared as function expressions no longer get the name "anonymous" in their toString representation. * For methods, the excerpt starts at the "get", "set", "*" (for generator methods), or property name, whichever comes first. Previously, the toString representation for methods would use a canonical prefix before the "(" of the parameter list. Note that any "static" keyword is omitted. * For arrow functions and class declarations, the excerpt is unchanged. For functions created with the Function, GeneratorFunction, or AsyncFunction constructors: * The string separating the parameter text and body text is now "\n) {\n", where previously it was "\n/*``*/) {\n" or ") {\n". * At one point, newline normalization was required by the spec here, but that was removed from the spec, and so this CL does not do it. Included in this CL is a fix for CreateDynamicFunction parsing. ')' and '`' characters in the parameter string are no longer disallowed, and Function("a=function(", "}){") is no longer allowed. BUG=v8:4958, v8:4230 Review-Url: https://codereview.chromium.org/2156303002 Cr-Commit-Position: refs/heads/master@{#43262}
2017-02-16 20:19:24 +00:00
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>(),
ScriptOriginOptions options = ScriptOriginOptions());
struct ScriptDetails {
ScriptDetails() : line_offset(0), column_offset(0) {}
explicit ScriptDetails(Handle<Object> script_name)
: line_offset(0), column_offset(0), name_obj(script_name) {}
int line_offset;
int column_offset;
i::MaybeHandle<i::Object> name_obj;
i::MaybeHandle<i::Object> source_map_url;
i::MaybeHandle<i::FixedArray> host_defined_options;
};
// Create a function that results from wrapping |source| in a function,
// with |arguments| being a list of parameters for that function.
V8_WARN_UNUSED_RESULT static MaybeHandle<JSFunction> GetWrappedFunction(
Handle<String> source, Handle<FixedArray> arguments,
Handle<Context> context, const ScriptDetails& script_details,
ScriptOriginOptions origin_options, ScriptData* cached_data,
v8::ScriptCompiler::CompileOptions compile_options,
v8::ScriptCompiler::NoCacheReason no_cache_reason);
// Returns true if the embedder permits compiling the given source string in
// the given context.
static bool CodeGenerationFromStringsAllowed(Isolate* isolate,
Handle<Context> context,
Handle<String> source);
// Create a (bound) function for a String source within a context for eval.
V8_WARN_UNUSED_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
Handle<Context> context, Handle<String> source,
Implement new Function.prototype.toString --harmony-function-tostring For functions declared in source code, the .toString() representation will be an excerpt of the source code. * For functions declared with the "function" keyword, the excerpt starts at the "function" or "async" keyword and ends at the final "}". The previous behavior would start the excerpt at the "(" of the parameter list, and prepend a canonical `"function " + name` or similar, which would discard comments and formatting surrounding the function's name. Anonymous functions declared as function expressions no longer get the name "anonymous" in their toString representation. * For methods, the excerpt starts at the "get", "set", "*" (for generator methods), or property name, whichever comes first. Previously, the toString representation for methods would use a canonical prefix before the "(" of the parameter list. Note that any "static" keyword is omitted. * For arrow functions and class declarations, the excerpt is unchanged. For functions created with the Function, GeneratorFunction, or AsyncFunction constructors: * The string separating the parameter text and body text is now "\n) {\n", where previously it was "\n/*``*/) {\n" or ") {\n". * At one point, newline normalization was required by the spec here, but that was removed from the spec, and so this CL does not do it. Included in this CL is a fix for CreateDynamicFunction parsing. ')' and '`' characters in the parameter string are no longer disallowed, and Function("a=function(", "}){") is no longer allowed. BUG=v8:4958, v8:4230 Review-Url: https://codereview.chromium.org/2156303002 Cr-Commit-Position: refs/heads/master@{#43262}
2017-02-16 20:19:24 +00:00
ParseRestriction restriction, int parameters_end_pos);
// Create a shared function info object for a String source.
static MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
Isolate* isolate, Handle<String> source,
const ScriptDetails& script_details, ScriptOriginOptions origin_options,
v8::Extension* extension, ScriptData* cached_data,
ScriptCompiler::CompileOptions compile_options,
ScriptCompiler::NoCacheReason no_cache_reason,
NativesFlag is_natives_code);
// Create a shared function info object for a Script source that has already
// been parsed and possibly compiled on a background thread while being loaded
// from a streamed source. On return, the data held by |streaming_data| will
// have been released, however the object itself isn't freed and is still
// owned by the caller.
static MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
Isolate* isolate, Handle<String> source,
const ScriptDetails& script_details, ScriptOriginOptions origin_options,
ScriptStreamingData* streaming_data);
// Create a shared function info object for the given function literal
// node (the code may be lazily compiled).
static Handle<SharedFunctionInfo> GetSharedFunctionInfo(FunctionLiteral* node,
Handle<Script> script,
Isolate* isolate);
// ===========================================================================
// 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.
V8_WARN_UNUSED_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
Handle<JSFunction> function, BailoutId osr_offset,
JavaScriptFrame* osr_frame);
};
// A base class for compilation jobs intended to run concurrent to the main
// thread. The current state of the job can be checked using {state()}.
class V8_EXPORT_PRIVATE CompilationJob {
public:
enum Status { SUCCEEDED, FAILED };
enum class State {
kReadyToPrepare,
kReadyToExecute,
kReadyToFinalize,
kSucceeded,
kFailed,
};
CompilationJob(uintptr_t stack_limit, State initial_state)
: state_(initial_state), stack_limit_(stack_limit) {}
virtual ~CompilationJob() {}
void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
uintptr_t stack_limit() const { return stack_limit_; }
State state() const { return state_; }
protected:
V8_WARN_UNUSED_RESULT Status UpdateState(Status status, State next_state) {
if (status == SUCCEEDED) {
state_ = next_state;
} else {
state_ = State::kFailed;
}
return status;
}
private:
State state_;
uintptr_t stack_limit_;
};
// A base class for unoptimized compilation jobs.
//
// The job is split into two phases which are called in sequence on
// different threads and with different limitations:
// 1) ExecuteJob: Runs concurrently. No heap allocation or handle derefs.
// 2) FinalizeJob: Runs on main thread. No dependency changes.
//
// Either of phases can either fail or succeed.
class UnoptimizedCompilationJob : public CompilationJob {
public:
UnoptimizedCompilationJob(intptr_t stack_limit, ParseInfo* parse_info,
UnoptimizedCompilationInfo* compilation_info)
: CompilationJob(stack_limit, State::kReadyToExecute),
parse_info_(parse_info),
compilation_info_(compilation_info) {}
// Executes the compile job. Can be called on a background thread.
V8_WARN_UNUSED_RESULT Status ExecuteJob();
// Finalizes the compile job. Must be called on the main thread.
V8_WARN_UNUSED_RESULT Status
FinalizeJob(Handle<SharedFunctionInfo> shared_info, Isolate* isolate);
void RecordCompilationStats(Isolate* isolate) const;
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
Handle<SharedFunctionInfo> shared,
Isolate* isolate) const;
ParseInfo* parse_info() const { return parse_info_; }
UnoptimizedCompilationInfo* compilation_info() const {
return compilation_info_;
}
protected:
// Overridden by the actual implementation.
virtual Status ExecuteJobImpl() = 0;
virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) = 0;
private:
ParseInfo* parse_info_;
UnoptimizedCompilationInfo* compilation_info_;
base::TimeDelta time_taken_to_execute_;
base::TimeDelta time_taken_to_finalize_;
};
// A base class for optimized compilation jobs.
//
// The job is split into three phases which are called in sequence on
// different threads and with different limitations:
// 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.
//
// Each of the three phases can either fail or succeed.
class OptimizedCompilationJob : public CompilationJob {
public:
OptimizedCompilationJob(uintptr_t stack_limit,
OptimizedCompilationInfo* compilation_info,
const char* compiler_name,
State initial_state = State::kReadyToPrepare)
: CompilationJob(stack_limit, initial_state),
compilation_info_(compilation_info),
compiler_name_(compiler_name) {}
// Prepare the compile job. Must be called on the main thread.
V8_WARN_UNUSED_RESULT Status PrepareJob(Isolate* isolate);
// Executes the compile job. Can be called on a background thread if
// can_execute_on_background_thread() returns true.
V8_WARN_UNUSED_RESULT Status ExecuteJob();
// Finalizes the compile job. Must be called on the main thread.
V8_WARN_UNUSED_RESULT Status FinalizeJob(Isolate* isolate);
// Report a transient failure, try again next time. Should only be called on
// optimization compilation jobs.
Status RetryOptimization(BailoutReason reason);
// Report a persistent failure, disable future optimization on the function.
// Should only be called on optimization compilation jobs.
Status AbortOptimization(BailoutReason reason);
void RecordCompilationStats() const;
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
Isolate* isolate) const;
OptimizedCompilationInfo* compilation_info() const {
return compilation_info_;
}
protected:
// Overridden by the actual implementation.
virtual Status PrepareJobImpl(Isolate* isolate) = 0;
virtual Status ExecuteJobImpl() = 0;
virtual Status FinalizeJobImpl(Isolate* isolate) = 0;
private:
OptimizedCompilationInfo* compilation_info_;
base::TimeDelta time_taken_to_prepare_;
base::TimeDelta time_taken_to_execute_;
base::TimeDelta time_taken_to_finalize_;
const char* compiler_name_;
};
// Contains all data which needs to be transmitted between threads for
// background parsing and compiling and finalizing it on the main thread.
struct ScriptStreamingData {
ScriptStreamingData(ScriptCompiler::ExternalSourceStream* source_stream,
ScriptCompiler::StreamedSource::Encoding encoding);
~ScriptStreamingData();
void Release();
// Internal implementation of v8::ScriptCompiler::StreamedSource.
std::unique_ptr<ScriptCompiler::ExternalSourceStream> source_stream;
ScriptCompiler::StreamedSource::Encoding encoding;
std::unique_ptr<ScriptCompiler::CachedData> cached_data;
// Data needed for parsing, and data needed to to be passed between thread
// between parsing and compilation. These need to be initialized before the
// compilation starts.
UnicodeCache unicode_cache;
std::unique_ptr<ParseInfo> info;
std::unique_ptr<Parser> parser;
// Data needed for finalizing compilation after background compilation.
std::unique_ptr<UnoptimizedCompilationJob> outer_function_job;
UnoptimizedCompilationJobList inner_function_jobs;
DISALLOW_COPY_AND_ASSIGN(ScriptStreamingData);
};
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_H_