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