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