Home | History | Annotate | Download | only in src
      1 // Copyright 2016 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 "src/compilation-info.h"
      6 
      7 #include "src/api.h"
      8 #include "src/ast/ast.h"
      9 #include "src/ast/scopes.h"
     10 #include "src/debug/debug.h"
     11 #include "src/isolate.h"
     12 #include "src/objects-inl.h"
     13 #include "src/parsing/parse-info.h"
     14 #include "src/source-position.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 #define PARSE_INFO_GETTER(type, name)  \
     20   type CompilationInfo::name() const { \
     21     CHECK(parse_info());               \
     22     return parse_info()->name();       \
     23   }
     24 
     25 #define PARSE_INFO_GETTER_WITH_DEFAULT(type, name, def) \
     26   type CompilationInfo::name() const {                  \
     27     return parse_info() ? parse_info()->name() : def;   \
     28   }
     29 
     30 PARSE_INFO_GETTER(Handle<Script>, script)
     31 PARSE_INFO_GETTER(FunctionLiteral*, literal)
     32 PARSE_INFO_GETTER_WITH_DEFAULT(DeclarationScope*, scope, nullptr)
     33 PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
     34 
     35 #undef PARSE_INFO_GETTER
     36 #undef PARSE_INFO_GETTER_WITH_DEFAULT
     37 
     38 bool CompilationInfo::is_debug() const {
     39   return parse_info() ? parse_info()->is_debug() : false;
     40 }
     41 
     42 void CompilationInfo::set_is_debug() {
     43   CHECK(parse_info());
     44   parse_info()->set_is_debug();
     45 }
     46 
     47 void CompilationInfo::PrepareForSerializing() {
     48   if (parse_info()) parse_info()->set_will_serialize();
     49   SetFlag(kSerializing);
     50 }
     51 
     52 bool CompilationInfo::has_shared_info() const {
     53   return parse_info_ && !parse_info_->shared_info().is_null();
     54 }
     55 
     56 CompilationInfo::CompilationInfo(Zone* zone, ParseInfo* parse_info,
     57                                  Handle<JSFunction> closure)
     58     : CompilationInfo(parse_info, {}, Code::ComputeFlags(Code::FUNCTION), BASE,
     59                       parse_info->isolate(), zone) {
     60   closure_ = closure;
     61 
     62   // Compiling for the snapshot typically results in different code than
     63   // compiling later on. This means that code recompiled with deoptimization
     64   // support won't be "equivalent" (as defined by SharedFunctionInfo::
     65   // EnableDeoptimizationSupport), so it will replace the old code and all
     66   // its type feedback. To avoid this, always compile functions in the snapshot
     67   // with deoptimization support.
     68   if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
     69 
     70   if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
     71   if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
     72 
     73   // Collect source positions for optimized code when profiling or if debugger
     74   // is active, to be able to get more precise source positions at the price of
     75   // more memory consumption.
     76   if (isolate_->NeedsSourcePositionsForProfiling()) {
     77     MarkAsSourcePositionsEnabled();
     78   }
     79 }
     80 
     81 CompilationInfo::CompilationInfo(Vector<const char> debug_name,
     82                                  Isolate* isolate, Zone* zone,
     83                                  Code::Flags code_flags)
     84     : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
     85 
     86 CompilationInfo::CompilationInfo(ParseInfo* parse_info,
     87                                  Vector<const char> debug_name,
     88                                  Code::Flags code_flags, Mode mode,
     89                                  Isolate* isolate, Zone* zone)
     90     : parse_info_(parse_info),
     91       isolate_(isolate),
     92       flags_(0),
     93       code_flags_(code_flags),
     94       mode_(mode),
     95       osr_ast_id_(BailoutId::None()),
     96       zone_(zone),
     97       deferred_handles_(nullptr),
     98       dependencies_(isolate, zone),
     99       bailout_reason_(kNoReason),
    100       prologue_offset_(Code::kPrologueOffsetNotSet),
    101       parameter_count_(0),
    102       optimization_id_(-1),
    103       osr_expr_stack_height_(-1),
    104       debug_name_(debug_name) {}
    105 
    106 CompilationInfo::~CompilationInfo() {
    107   if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
    108     shared_info()->DisableOptimization(bailout_reason());
    109   }
    110   dependencies()->Rollback();
    111 }
    112 
    113 int CompilationInfo::num_parameters() const {
    114   return !IsStub() ? scope()->num_parameters() : parameter_count_;
    115 }
    116 
    117 int CompilationInfo::num_parameters_including_this() const {
    118   return num_parameters() + (is_this_defined() ? 1 : 0);
    119 }
    120 
    121 bool CompilationInfo::is_this_defined() const { return !IsStub(); }
    122 
    123 // Primitive functions are unlikely to be picked up by the stack-walking
    124 // profiler, so they trigger their own optimization when they're called
    125 // for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
    126 bool CompilationInfo::ShouldSelfOptimize() {
    127   return FLAG_opt && FLAG_crankshaft &&
    128          !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
    129          !literal()->dont_optimize() &&
    130          literal()->scope()->AllowsLazyCompilation() &&
    131          !shared_info()->optimization_disabled();
    132 }
    133 
    134 void CompilationInfo::set_deferred_handles(
    135     std::shared_ptr<DeferredHandles> deferred_handles) {
    136   DCHECK(deferred_handles_.get() == nullptr);
    137   deferred_handles_.swap(deferred_handles);
    138 }
    139 
    140 void CompilationInfo::set_deferred_handles(DeferredHandles* deferred_handles) {
    141   DCHECK(deferred_handles_.get() == nullptr);
    142   deferred_handles_.reset(deferred_handles);
    143 }
    144 
    145 void CompilationInfo::ReopenHandlesInNewHandleScope() {
    146   if (!closure_.is_null()) {
    147     closure_ = Handle<JSFunction>(*closure_);
    148   }
    149 }
    150 
    151 bool CompilationInfo::has_simple_parameters() {
    152   return scope()->has_simple_parameters();
    153 }
    154 
    155 std::unique_ptr<char[]> CompilationInfo::GetDebugName() const {
    156   if (parse_info() && parse_info()->literal()) {
    157     AllowHandleDereference allow_deref;
    158     return parse_info()->literal()->debug_name()->ToCString();
    159   }
    160   if (parse_info() && !parse_info()->shared_info().is_null()) {
    161     return parse_info()->shared_info()->DebugName()->ToCString();
    162   }
    163   Vector<const char> name_vec = debug_name_;
    164   if (name_vec.is_empty()) name_vec = ArrayVector("unknown");
    165   std::unique_ptr<char[]> name(new char[name_vec.length() + 1]);
    166   memcpy(name.get(), name_vec.start(), name_vec.length());
    167   name[name_vec.length()] = '\0';
    168   return name;
    169 }
    170 
    171 StackFrame::Type CompilationInfo::GetOutputStackFrameType() const {
    172   switch (output_code_kind()) {
    173     case Code::STUB:
    174     case Code::BYTECODE_HANDLER:
    175     case Code::HANDLER:
    176     case Code::BUILTIN:
    177 #define CASE_KIND(kind) case Code::kind:
    178       IC_KIND_LIST(CASE_KIND)
    179 #undef CASE_KIND
    180       return StackFrame::STUB;
    181     case Code::WASM_FUNCTION:
    182       return StackFrame::WASM_COMPILED;
    183     case Code::JS_TO_WASM_FUNCTION:
    184       return StackFrame::JS_TO_WASM;
    185     case Code::WASM_TO_JS_FUNCTION:
    186       return StackFrame::WASM_TO_JS;
    187     case Code::WASM_INTERPRETER_ENTRY:
    188       return StackFrame::WASM_INTERPRETER_ENTRY;
    189     default:
    190       UNIMPLEMENTED();
    191       return StackFrame::NONE;
    192   }
    193 }
    194 
    195 int CompilationInfo::GetDeclareGlobalsFlags() const {
    196   DCHECK(DeclareGlobalsLanguageMode::is_valid(parse_info()->language_mode()));
    197   return DeclareGlobalsEvalFlag::encode(parse_info()->is_eval()) |
    198          DeclareGlobalsNativeFlag::encode(parse_info()->is_native()) |
    199          DeclareGlobalsLanguageMode::encode(parse_info()->language_mode());
    200 }
    201 
    202 SourcePositionTableBuilder::RecordingMode
    203 CompilationInfo::SourcePositionRecordingMode() const {
    204   return parse_info() && parse_info()->is_native()
    205              ? SourcePositionTableBuilder::OMIT_SOURCE_POSITIONS
    206              : SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS;
    207 }
    208 
    209 bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
    210   return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native();
    211 }
    212 
    213 bool CompilationInfo::has_context() const { return !closure().is_null(); }
    214 
    215 Context* CompilationInfo::context() const {
    216   return has_context() ? closure()->context() : nullptr;
    217 }
    218 
    219 bool CompilationInfo::has_native_context() const {
    220   return !closure().is_null() && (closure()->native_context() != nullptr);
    221 }
    222 
    223 Context* CompilationInfo::native_context() const {
    224   return has_native_context() ? closure()->native_context() : nullptr;
    225 }
    226 
    227 bool CompilationInfo::has_global_object() const { return has_native_context(); }
    228 
    229 JSGlobalObject* CompilationInfo::global_object() const {
    230   return has_global_object() ? native_context()->global_object() : nullptr;
    231 }
    232 
    233 void CompilationInfo::SetOptimizing() {
    234   DCHECK(has_shared_info());
    235   SetMode(OPTIMIZE);
    236   optimization_id_ = isolate()->NextOptimizationId();
    237   code_flags_ = Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION);
    238 }
    239 
    240 int CompilationInfo::AddInlinedFunction(
    241     Handle<SharedFunctionInfo> inlined_function, SourcePosition pos) {
    242   int id = static_cast<int>(inlined_functions_.size());
    243   inlined_functions_.push_back(InlinedFunctionHolder(
    244       inlined_function, handle(inlined_function->code()), pos));
    245   return id;
    246 }
    247 
    248 Code::Kind CompilationInfo::output_code_kind() const {
    249   return Code::ExtractKindFromFlags(code_flags_);
    250 }
    251 
    252 }  // namespace internal
    253 }  // namespace v8
    254