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