blob: 307b3b0e428493887dbdadf28cd67c6d1d7444c4 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/compiler.h"
Ben Murdochf87a2032010-10-22 12:50:53 +01006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include <algorithm>
8
9#include "src/ast/ast-numbering.h"
10#include "src/ast/prettyprinter.h"
11#include "src/ast/scopeinfo.h"
12#include "src/ast/scopes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/bootstrapper.h"
14#include "src/codegen.h"
15#include "src/compilation-cache.h"
16#include "src/compiler/pipeline.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/crankshaft/hydrogen.h"
18#include "src/crankshaft/lithium.h"
19#include "src/crankshaft/typing.h"
20#include "src/debug/debug.h"
21#include "src/debug/liveedit.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022#include "src/deoptimizer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023#include "src/full-codegen/full-codegen.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/gdb-jit.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025#include "src/interpreter/interpreter.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026#include "src/isolate-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027#include "src/log-inl.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028#include "src/messages.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029#include "src/parsing/parser.h"
30#include "src/parsing/rewriter.h"
31#include "src/parsing/scanner-character-streams.h"
32#include "src/profiler/cpu-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033#include "src/runtime-profiler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034#include "src/snapshot/serialize.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37namespace v8 {
38namespace internal {
39
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040std::ostream& operator<<(std::ostream& os, const SourcePosition& p) {
41 if (p.IsUnknown()) {
42 return os << "<?>";
43 } else if (FLAG_hydrogen_track_positions) {
44 return os << "<" << p.inlining_id() << ":" << p.position() << ">";
45 } else {
46 return os << "<0:" << p.raw() << ">";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 }
Ben Murdochf87a2032010-10-22 12:50:53 +010048}
49
50
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051#define PARSE_INFO_GETTER(type, name) \
52 type CompilationInfo::name() const { \
53 CHECK(parse_info()); \
54 return parse_info()->name(); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056
57
58#define PARSE_INFO_GETTER_WITH_DEFAULT(type, name, def) \
59 type CompilationInfo::name() const { \
60 return parse_info() ? parse_info()->name() : def; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062
63
64PARSE_INFO_GETTER(Handle<Script>, script)
65PARSE_INFO_GETTER(bool, is_eval)
66PARSE_INFO_GETTER(bool, is_native)
67PARSE_INFO_GETTER(bool, is_module)
68PARSE_INFO_GETTER(FunctionLiteral*, literal)
69PARSE_INFO_GETTER_WITH_DEFAULT(LanguageMode, language_mode, STRICT)
70PARSE_INFO_GETTER_WITH_DEFAULT(Handle<JSFunction>, closure,
71 Handle<JSFunction>::null())
72PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr)
73PARSE_INFO_GETTER(Handle<Context>, context)
74PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
75
76#undef PARSE_INFO_GETTER
77#undef PARSE_INFO_GETTER_WITH_DEFAULT
78
79
80// Exactly like a CompilationInfo, except being allocated via {new} and it also
81// creates and enters a Zone on construction and deallocates it on destruction.
82class CompilationInfoWithZone : public CompilationInfo {
83 public:
84 explicit CompilationInfoWithZone(Handle<JSFunction> function)
85 : CompilationInfo(new ParseInfo(&zone_, function)) {}
86
87 // Virtual destructor because a CompilationInfoWithZone has to exit the
88 // zone scope and get rid of dependent maps even when the destructor is
89 // called when cast as a CompilationInfo.
90 virtual ~CompilationInfoWithZone() {
91 DisableFutureOptimization();
92 dependencies()->Rollback();
93 delete parse_info_;
94 parse_info_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096
97 private:
98 Zone zone_;
99};
100
101
102bool CompilationInfo::has_shared_info() const {
103 return parse_info_ && !parse_info_->shared_info().is_null();
104}
105
106
107bool CompilationInfo::has_context() const {
108 return parse_info_ && !parse_info_->context().is_null();
109}
110
111
112bool CompilationInfo::has_literal() const {
113 return parse_info_ && parse_info_->literal() != nullptr;
114}
115
116
117bool CompilationInfo::has_scope() const {
118 return parse_info_ && parse_info_->scope() != nullptr;
119}
120
121
122CompilationInfo::CompilationInfo(ParseInfo* parse_info)
123 : CompilationInfo(parse_info, nullptr, nullptr, BASE, parse_info->isolate(),
124 parse_info->zone()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400125 // Compiling for the snapshot typically results in different code than
126 // compiling later on. This means that code recompiled with deoptimization
127 // support won't be "equivalent" (as defined by SharedFunctionInfo::
128 // EnableDeoptimizationSupport), so it will replace the old code and all
129 // its type feedback. To avoid this, always compile functions in the snapshot
130 // with deoptimization support.
131 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
132
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134 if (FLAG_turbo_inlining) MarkAsInliningEnabled();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled();
136 if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 if (FLAG_turbo_types) MarkAsTypingEnabled();
138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 if (has_shared_info()) {
140 if (shared_info()->is_compiled()) {
141 // We should initialize the CompilationInfo feedback vector from the
142 // passed in shared info, rather than creating a new one.
143 feedback_vector_ = Handle<TypeFeedbackVector>(
144 shared_info()->feedback_vector(), parse_info->isolate());
145 }
146 if (shared_info()->never_compiled()) MarkAsFirstCompile();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150
151CompilationInfo::CompilationInfo(CodeStub* stub, Isolate* isolate, Zone* zone)
152 : CompilationInfo(nullptr, stub, CodeStub::MajorName(stub->MajorKey()),
153 STUB, isolate, zone) {}
154
155CompilationInfo::CompilationInfo(const char* debug_name, Isolate* isolate,
156 Zone* zone)
157 : CompilationInfo(nullptr, nullptr, debug_name, STUB, isolate, zone) {
158 set_output_code_kind(Code::STUB);
159}
160
161CompilationInfo::CompilationInfo(ParseInfo* parse_info, CodeStub* code_stub,
162 const char* debug_name, Mode mode,
163 Isolate* isolate, Zone* zone)
164 : parse_info_(parse_info),
165 isolate_(isolate),
166 flags_(0),
167 code_stub_(code_stub),
168 mode_(mode),
169 osr_ast_id_(BailoutId::None()),
170 zone_(zone),
171 deferred_handles_(nullptr),
172 dependencies_(isolate, zone),
173 bailout_reason_(kNoReason),
174 prologue_offset_(Code::kPrologueOffsetNotSet),
175 track_positions_(FLAG_hydrogen_track_positions ||
176 isolate->cpu_profiler()->is_profiling()),
177 opt_count_(has_shared_info() ? shared_info()->opt_count() : 0),
178 parameter_count_(0),
179 optimization_id_(-1),
180 osr_expr_stack_height_(0),
181 debug_name_(debug_name) {
182 // Parameter count is number of stack parameters.
183 if (code_stub_ != NULL) {
184 CodeStubDescriptor descriptor(code_stub_);
185 parameter_count_ = descriptor.GetStackParameterCount();
186 if (descriptor.function_mode() == NOT_JS_FUNCTION_STUB_MODE) {
187 parameter_count_--;
188 }
189 set_output_code_kind(code_stub->GetCodeKind());
190 } else {
191 set_output_code_kind(Code::FUNCTION);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 }
193}
194
195
196CompilationInfo::~CompilationInfo() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 DisableFutureOptimization();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 delete deferred_handles_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199#ifdef DEBUG
200 // Check that no dependent maps have been added or added dependent maps have
201 // been rolled back or committed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 DCHECK(dependencies()->IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203#endif // DEBUG
204}
205
206
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207int CompilationInfo::num_parameters() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 return has_scope() ? scope()->num_parameters() : parameter_count_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209}
210
211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212int CompilationInfo::num_parameters_including_this() const {
213 return num_parameters() + (is_this_defined() ? 1 : 0);
214}
215
216
217bool CompilationInfo::is_this_defined() const { return !IsStub(); }
218
219
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220int CompilationInfo::num_heap_slots() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 return has_scope() ? scope()->num_heap_slots() : 0;
Ben Murdoch257744e2011-11-30 15:57:28 +0000222}
Ben Murdochb8e0da22011-05-16 14:20:40 +0100223
Ben Murdoch257744e2011-11-30 15:57:28 +0000224
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100225// Primitive functions are unlikely to be picked up by the stack-walking
226// profiler, so they trigger their own optimization when they're called
227// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
228bool CompilationInfo::ShouldSelfOptimize() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 return FLAG_crankshaft &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
231 !literal()->dont_optimize() &&
232 literal()->scope()->AllowsLazyCompilation() &&
233 (!has_shared_info() || !shared_info()->optimization_disabled());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400236
237void CompilationInfo::EnsureFeedbackVector() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 if (feedback_vector_.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 Handle<TypeFeedbackMetadata> feedback_metadata =
240 TypeFeedbackMetadata::New(isolate(), literal()->feedback_vector_spec());
241 feedback_vector_ = TypeFeedbackVector::New(isolate(), feedback_metadata);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243
244 // It's very important that recompiles do not alter the structure of the
245 // type feedback vector.
246 CHECK(!feedback_vector_->metadata()->SpecDiffersFrom(
247 literal()->feedback_vector_spec()));
248}
249
250
251bool CompilationInfo::has_simple_parameters() {
252 return scope()->has_simple_parameters();
253}
254
255
256int CompilationInfo::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
257 SourcePosition position,
258 int parent_id) {
259 DCHECK(track_positions_);
260
261 int inline_id = static_cast<int>(inlined_function_infos_.size());
262 InlinedFunctionInfo info(parent_id, position, UnboundScript::kNoScriptId,
263 shared->start_position());
264 if (!shared->script()->IsUndefined()) {
265 Handle<Script> script(Script::cast(shared->script()));
266 info.script_id = script->id();
267
268 if (FLAG_hydrogen_track_positions && !script->source()->IsUndefined()) {
269 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
270 OFStream os(tracing_scope.file());
271 os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
272 << ") id{" << optimization_id() << "," << inline_id << "} ---\n";
273 {
274 DisallowHeapAllocation no_allocation;
275 int start = shared->start_position();
276 int len = shared->end_position() - start;
277 String::SubStringRange source(String::cast(script->source()), start,
278 len);
279 for (const auto& c : source) {
280 os << AsReversiblyEscapedUC16(c);
281 }
282 }
283
284 os << "\n--- END ---\n";
285 }
286 }
287
288 inlined_function_infos_.push_back(info);
289
290 if (FLAG_hydrogen_track_positions && inline_id != 0) {
291 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
292 OFStream os(tracing_scope.file());
293 os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
294 << optimization_id() << "," << inline_id << "} AS " << inline_id
295 << " AT " << position << std::endl;
296 }
297
298 return inline_id;
299}
300
301
302void CompilationInfo::LogDeoptCallPosition(int pc_offset, int inlining_id) {
303 if (!track_positions_ || IsStub()) return;
304 DCHECK_LT(static_cast<size_t>(inlining_id), inlined_function_infos_.size());
305 inlined_function_infos_.at(inlining_id).deopt_pc_offsets.push_back(pc_offset);
306}
307
308
309base::SmartArrayPointer<char> CompilationInfo::GetDebugName() const {
310 if (parse_info()) {
311 AllowHandleDereference allow_deref;
312 return parse_info()->literal()->debug_name()->ToCString();
313 }
314 const char* str = debug_name_ ? debug_name_ : "unknown";
315 size_t len = strlen(str) + 1;
316 base::SmartArrayPointer<char> name(new char[len]);
317 memcpy(name.get(), str, len);
318 return name;
319}
320
321
322bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
323 return is_sloppy(language_mode()) && !is_native();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100324}
325
326
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
328 public:
329 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
330 : HOptimizedGraphBuilder(info) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100331 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333#define DEF_VISIT(type) \
334 void Visit##type(type* node) override { \
335 SourcePosition old_position = SourcePosition::Unknown(); \
336 if (node->position() != RelocInfo::kNoPosition) { \
337 old_position = source_position(); \
338 SetSourcePosition(node->position()); \
339 } \
340 HOptimizedGraphBuilder::Visit##type(node); \
341 if (!old_position.IsUnknown()) { \
342 set_source_position(old_position); \
343 } \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100344 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 EXPRESSION_NODE_LIST(DEF_VISIT)
346#undef DEF_VISIT
Ben Murdochb0fe1622011-05-05 13:52:32 +0100347
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348#define DEF_VISIT(type) \
349 void Visit##type(type* node) override { \
350 SourcePosition old_position = SourcePosition::Unknown(); \
351 if (node->position() != RelocInfo::kNoPosition) { \
352 old_position = source_position(); \
353 SetSourcePosition(node->position()); \
354 } \
355 HOptimizedGraphBuilder::Visit##type(node); \
356 if (!old_position.IsUnknown()) { \
357 set_source_position(old_position); \
358 } \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 }
360 STATEMENT_NODE_LIST(DEF_VISIT)
361#undef DEF_VISIT
362
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400363#define DEF_VISIT(type) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 void Visit##type(type* node) override { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400365 HOptimizedGraphBuilder::Visit##type(node); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000366 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367 DECLARATION_NODE_LIST(DEF_VISIT)
368#undef DEF_VISIT
369};
370
371
372OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 DCHECK(info()->IsOptimizing());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100374
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 // Do not use Crankshaft/TurboFan if we need to be able to set break points.
376 if (info()->shared_info()->HasDebugInfo()) {
377 return AbortOptimization(kFunctionBeingDebugged);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 }
Steve Block44f0eee2011-05-26 01:26:41 +0100379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 // Limit the number of times we try to optimize functions.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100381 const int kMaxOptCount =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
383 if (info()->opt_count() > kMaxOptCount) {
384 return AbortOptimization(kOptimizedTooManyTimes);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100385 }
386
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387 // Check the whitelist for Crankshaft.
388 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) {
389 return AbortOptimization(kHydrogenFilter);
390 }
391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 // Optimization requires a version of fullcode with deoptimization support.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100393 // Recompile the unoptimized version of the code if the current version
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 // doesn't have deoptimization support already.
395 // Otherwise, if we are gathering compilation time and space statistics
396 // for hydrogen, gather baseline statistics for a fullcode compilation.
397 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
Steve Block44f0eee2011-05-26 01:26:41 +0100398 if (should_recompile || FLAG_hydrogen_stats) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 base::ElapsedTimer timer;
400 if (FLAG_hydrogen_stats) {
401 timer.Start();
402 }
403 if (!Compiler::EnsureDeoptimizationSupport(info())) {
404 return SetLastStatus(FAILED);
405 }
406 if (FLAG_hydrogen_stats) {
407 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100408 }
409 }
410
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411 DCHECK(info()->shared_info()->has_deoptimization_support());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 DCHECK(!info()->is_first_compile());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414 bool optimization_disabled = info()->shared_info()->optimization_disabled();
415 bool dont_crankshaft = info()->shared_info()->dont_crankshaft();
416
417 // Check the enabling conditions for Turbofan.
418 // 1. "use asm" code.
419 bool is_turbofanable_asm = FLAG_turbo_asm &&
420 info()->shared_info()->asm_function() &&
421 !optimization_disabled;
422
423 // 2. Fallback for features unsupported by Crankshaft.
424 bool is_unsupported_by_crankshaft_but_turbofanable =
425 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
426 !optimization_disabled;
427
428 // 3. Explicitly enabled by the command-line filter.
429 bool passes_turbo_filter = info()->closure()->PassesFilter(FLAG_turbo_filter);
430
431 // If this is OSR request, OSR must be enabled by Turbofan.
432 bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr();
433
434 if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
435 passes_turbo_filter) &&
436 passes_osr_test) {
437 // Use TurboFan for the compilation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400438 if (FLAG_trace_opt) {
439 OFStream os(stdout);
440 os << "[compiling method " << Brief(*info()->closure())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 << " using TurboFan";
442 if (info()->is_osr()) os << " OSR";
443 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400444 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445
446 if (info()->shared_info()->asm_function()) {
447 if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
448 info()->MarkAsFunctionContextSpecializing();
449 } else if (info()->has_global_object() &&
450 FLAG_native_context_specialization) {
451 info()->MarkAsNativeContextSpecializing();
452 info()->MarkAsTypingEnabled();
453 }
454 if (!info()->shared_info()->asm_function() ||
455 FLAG_turbo_asm_deoptimization) {
456 info()->MarkAsDeoptimizationEnabled();
457 }
458
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459 Timer t(this, &time_taken_to_create_graph_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000460 compiler::Pipeline pipeline(info());
461 pipeline.GenerateCode();
462 if (!info()->code().is_null()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 return SetLastStatus(SUCCEEDED);
464 }
465 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000467 if (!isolate()->use_crankshaft() || dont_crankshaft) {
468 // Crankshaft is entirely disabled.
469 return SetLastStatus(FAILED);
470 }
471
472 Scope* scope = info()->scope();
473 if (LUnallocated::TooManyParameters(scope->num_parameters())) {
474 // Crankshaft would require too many Lithium operands.
475 return AbortOptimization(kTooManyParameters);
476 }
477
478 if (info()->is_osr() &&
479 LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
480 scope->num_stack_slots())) {
481 // Crankshaft would require too many Lithium operands.
482 return AbortOptimization(kTooManyParametersLocals);
483 }
484
485 if (scope->HasIllegalRedeclaration()) {
486 // Crankshaft cannot handle illegal redeclarations.
487 return AbortOptimization(kFunctionWithIllegalRedeclaration);
488 }
489
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400490 if (FLAG_trace_opt) {
491 OFStream os(stdout);
492 os << "[compiling method " << Brief(*info()->closure())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000493 << " using Crankshaft";
494 if (info()->is_osr()) os << " OSR";
495 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400496 }
497
Ben Murdochb0fe1622011-05-05 13:52:32 +0100498 if (FLAG_trace_hydrogen) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 isolate()->GetHTracer()->TraceCompilation(info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100500 }
501
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502 // Type-check the function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 AstTyper(info()->isolate(), info()->zone(), info()->closure(),
504 info()->scope(), info()->osr_ast_id(), info()->literal())
505 .Run();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000507 // Optimization could have been disabled by the parser. Note that this check
508 // is only needed because the Hydrogen graph builder is missing some bailouts.
509 if (info()->shared_info()->optimization_disabled()) {
510 return AbortOptimization(
511 info()->shared_info()->disable_optimization_reason());
512 }
513
514 graph_builder_ = (info()->is_tracking_positions() || FLAG_trace_ic)
515 ? new (info()->zone())
516 HOptimizedGraphBuilderWithPositions(info())
517 : new (info()->zone()) HOptimizedGraphBuilder(info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518
519 Timer t(this, &time_taken_to_create_graph_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 graph_ = graph_builder_->CreateGraph();
521
522 if (isolate()->has_pending_exception()) {
523 return SetLastStatus(FAILED);
Steve Block1e0659c2011-05-24 12:43:12 +0100524 }
525
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 if (graph_ == NULL) return SetLastStatus(BAILED_OUT);
527
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528 if (info()->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 // Dependency has changed during graph creation. Let's try again later.
530 return RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100531 }
532
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 return SetLastStatus(SUCCEEDED);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100534}
535
536
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() {
538 DisallowHeapAllocation no_allocation;
539 DisallowHandleAllocation no_handles;
540 DisallowHandleDereference no_deref;
541 DisallowCodeDependencyChange no_dependency_change;
Ben Murdoch257744e2011-11-30 15:57:28 +0000542
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 DCHECK(last_status() == SUCCEEDED);
544 // TODO(turbofan): Currently everything is done in the first phase.
545 if (!info()->code().is_null()) {
546 return last_status();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100547 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548
549 Timer t(this, &time_taken_to_optimize_);
550 DCHECK(graph_ != NULL);
551 BailoutReason bailout_reason = kNoReason;
552
553 if (graph_->Optimize(&bailout_reason)) {
554 chunk_ = LChunk::NewChunk(graph_);
555 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
556 } else if (bailout_reason != kNoReason) {
557 graph_builder_->Bailout(bailout_reason);
558 }
559
560 return SetLastStatus(BAILED_OUT);
Steve Block6ded16b2010-05-10 14:33:55 +0100561}
Steve Block6ded16b2010-05-10 14:33:55 +0100562
563
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564namespace {
565
566void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
567 Handle<Code> code) {
568 Handle<WeakCell> cell = Code::WeakCellFor(code);
569 Heap* heap = isolate->heap();
570 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
571 dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
572 heap->AddWeakObjectToCodeDependency(object, dep);
573}
574
575
576void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
577 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
578 Isolate* const isolate = code->GetIsolate();
579 DCHECK(code->is_optimized_code());
580 std::vector<Handle<Map>> maps;
581 std::vector<Handle<HeapObject>> objects;
582 {
583 DisallowHeapAllocation no_gc;
584 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
585 RelocInfo::ModeMask(RelocInfo::CELL);
586 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
587 RelocInfo::Mode mode = it.rinfo()->rmode();
588 if (mode == RelocInfo::CELL &&
589 code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
590 objects.push_back(handle(it.rinfo()->target_cell(), isolate));
591 } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
592 code->IsWeakObjectInOptimizedCode(
593 it.rinfo()->target_object())) {
594 Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
595 isolate);
596 if (object->IsMap()) {
597 maps.push_back(Handle<Map>::cast(object));
598 } else {
599 objects.push_back(object);
600 }
601 }
602 }
603 }
604 for (Handle<Map> map : maps) {
605 if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) {
606 isolate->heap()->AddRetainedMap(map);
607 }
608 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code);
609 }
610 for (Handle<HeapObject> object : objects) {
611 AddWeakObjectToCodeDependency(isolate, object, code);
612 }
613 code->set_can_have_weak_objects(true);
614}
615
616} // namespace
617
618
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
620 DCHECK(last_status() == SUCCEEDED);
621 // TODO(turbofan): Currently everything is done in the first phase.
622 if (!info()->code().is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623 info()->dependencies()->Commit(info()->code());
624 if (info()->is_deoptimization_enabled()) {
625 info()->parse_info()->context()->native_context()->AddOptimizedCode(
626 *info()->code());
627 RegisterWeakObjectsInOptimizedCode(info()->code());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400628 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 RecordOptimizationStats();
630 return last_status();
631 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000632
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 DCHECK(!info()->dependencies()->HasAborted());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 DisallowCodeDependencyChange no_dependency_change;
635 DisallowJavascriptExecution no_js(isolate());
636 { // Scope for timer.
637 Timer timer(this, &time_taken_to_codegen_);
638 DCHECK(chunk_ != NULL);
639 DCHECK(graph_ != NULL);
640 // Deferred handles reference objects that were accessible during
641 // graph creation. To make sure that we don't encounter inconsistencies
642 // between graph creation and code generation, we disallow accessing
643 // objects through deferred handles during the latter, with exceptions.
644 DisallowDeferredHandleDereference no_deferred_handle_deref;
645 Handle<Code> optimized_code = chunk_->Codegen();
646 if (optimized_code.is_null()) {
647 if (info()->bailout_reason() == kNoReason) {
648 return AbortOptimization(kCodeGenerationFailed);
Leon Clarke4515c472010-02-03 11:58:03 +0000649 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000650 return SetLastStatus(BAILED_OUT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 RegisterWeakObjectsInOptimizedCode(optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 info()->SetCode(optimized_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000654 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 RecordOptimizationStats();
656 // Add to the weak list of optimized code objects.
657 info()->context()->native_context()->AddOptimizedCode(*info()->code());
658 return SetLastStatus(SUCCEEDED);
Steve Blocka7e24c12009-10-30 11:49:00 +0000659}
660
661
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662void OptimizedCompileJob::RecordOptimizationStats() {
663 Handle<JSFunction> function = info()->closure();
664 if (!function->IsOptimized()) {
665 // Concurrent recompilation and OSR may race. Increment only once.
666 int opt_count = function->shared()->opt_count();
667 function->shared()->set_opt_count(opt_count + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000668 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
670 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
671 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
672 if (FLAG_trace_opt) {
673 PrintF("[optimizing ");
674 function->ShortPrint();
675 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
676 ms_codegen);
Steve Blocka7e24c12009-10-30 11:49:00 +0000677 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678 if (FLAG_trace_opt_stats) {
679 static double compilation_time = 0.0;
680 static int compiled_functions = 0;
681 static int code_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000682
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
684 compiled_functions++;
685 code_size += function->shared()->SourceSize();
686 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
687 compiled_functions,
688 code_size,
689 compilation_time);
690 }
691 if (FLAG_hydrogen_stats) {
692 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
693 time_taken_to_optimize_,
694 time_taken_to_codegen_);
695 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000696}
697
698
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699// Sets the expected number of properties based on estimate from compiler.
700void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
701 int estimate) {
702 // If no properties are added in the constructor, they are more likely
703 // to be added later.
704 if (estimate == 0) estimate = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +0000705
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706 // TODO(yangguo): check whether those heuristics are still up-to-date.
707 // We do not shrink objects that go into a snapshot (yet), so we adjust
708 // the estimate conservatively.
709 if (shared->GetIsolate()->serializer_enabled()) {
710 estimate += 2;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400711 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712 // Inobject slack tracking will reclaim redundant inobject space later,
713 // so we can afford to adjust the estimate generously.
714 estimate += 8;
Steve Blocka7e24c12009-10-30 11:49:00 +0000715 }
716
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717 shared->set_expected_nof_properties(estimate);
Steve Blockd0582a62009-12-15 09:54:21 +0000718}
719
720
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400721static void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
722 BailoutReason bailout_reason) {
723 if (bailout_reason != kNoReason) {
724 shared_info->DisableOptimization(bailout_reason);
725 }
726}
727
728
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000729static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
730 CompilationInfo* info,
731 Handle<SharedFunctionInfo> shared) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100732 // SharedFunctionInfo is passed separately, because if CompilationInfo
733 // was created using Script object, it will not have it.
734
Ben Murdochf87a2032010-10-22 12:50:53 +0100735 // Log the code generation. If source information is available include
736 // script name and line number. Check explicitly whether logging is
737 // enabled as finding the line number is not free.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000738 if (info->isolate()->logger()->is_logging_code_events() ||
739 info->isolate()->cpu_profiler()->is_profiling()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000740 Handle<Script> script = info->parse_info()->script();
Ben Murdochf87a2032010-10-22 12:50:53 +0100741 Handle<Code> code = info->code();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000742 if (code.is_identical_to(info->isolate()->builtins()->CompileLazy())) {
Steve Block44f0eee2011-05-26 01:26:41 +0100743 return;
Andrei Popescu31002712010-02-23 13:46:05 +0000744 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
746 int column_num =
747 Script::GetColumnNumber(script, shared->start_position()) + 1;
748 String* script_name = script->name()->IsString()
749 ? String::cast(script->name())
750 : info->isolate()->heap()->empty_string();
751 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
752 PROFILE(info->isolate(),
753 CodeCreateEvent(log_tag, *code, *shared, info, script_name,
754 line_num, column_num));
Andrei Popescu31002712010-02-23 13:46:05 +0000755 }
756}
Andrei Popescu31002712010-02-23 13:46:05 +0000757
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000758
759static bool CompileUnoptimizedCode(CompilationInfo* info) {
760 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761 if (!Compiler::Analyze(info->parse_info()) ||
762 !FullCodeGenerator::MakeCode(info)) {
763 Isolate* isolate = info->isolate();
764 if (!isolate->has_pending_exception()) isolate->StackOverflow();
765 return false;
766 }
767 return true;
768}
769
770
771// TODO(rmcilroy): Remove this temporary work-around when ignition supports
772// catch and eval.
773static bool IgnitionShouldFallbackToFullCodeGen(Scope* scope) {
774 if (scope->is_eval_scope() || scope->is_catch_scope() ||
775 scope->calls_eval()) {
776 return true;
777 }
778 for (auto inner_scope : *scope->inner_scopes()) {
779 if (IgnitionShouldFallbackToFullCodeGen(inner_scope)) return true;
780 }
781 return false;
782}
783
784
785static bool UseIgnition(CompilationInfo* info) {
786 // Cannot use Ignition when the {function_data} is already used.
787 if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId()) {
788 return false;
789 }
790
791 // Checks whether the scope chain is supported.
792 if (FLAG_ignition_fallback_on_eval_and_catch &&
793 IgnitionShouldFallbackToFullCodeGen(info->scope())) {
794 return false;
795 }
796
797 // Checks whether top level functions should be passed by the filter.
798 if (info->closure().is_null()) {
799 Vector<const char> filter = CStrVector(FLAG_ignition_filter);
800 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
801 }
802
803 // Finally respect the filter.
804 return info->closure()->PassesFilter(FLAG_ignition_filter);
805}
806
807
808static bool GenerateBaselineCode(CompilationInfo* info) {
809 if (FLAG_ignition && UseIgnition(info)) {
810 return interpreter::Interpreter::MakeBytecode(info);
811 } else {
812 return FullCodeGenerator::MakeCode(info);
813 }
814}
815
816
817static bool CompileBaselineCode(CompilationInfo* info) {
818 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
819 if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000820 Isolate* isolate = info->isolate();
821 if (!isolate->has_pending_exception()) isolate->StackOverflow();
822 return false;
823 }
824 return true;
825}
826
827
828MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
829 CompilationInfo* info) {
830 VMState<COMPILER> state(info->isolate());
831 PostponeInterruptsScope postpone(info->isolate());
832
833 // Parse and update CompilationInfo with the results.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836 FunctionLiteral* lit = info->literal();
837 DCHECK_EQ(shared->language_mode(), lit->language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400839 MaybeDisableOptimization(shared, lit->dont_optimize_reason());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000840
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 // Compile either unoptimized code or bytecode for the interpreter.
842 if (!CompileBaselineCode(info)) return MaybeHandle<Code>();
843 if (info->code()->kind() == Code::FUNCTION) { // Only for full code.
844 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
845 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846
847 // Update the shared function info with the scope info. Allocating the
848 // ScopeInfo object may cause a GC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 Handle<ScopeInfo> scope_info =
850 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851 shared->set_scope_info(*scope_info);
852
853 // Update the code and feedback vector for the shared function info.
854 shared->ReplaceCode(*info->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 shared->set_feedback_vector(*info->feedback_vector());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856 if (info->has_bytecode_array()) {
857 DCHECK(shared->function_data()->IsUndefined());
858 shared->set_function_data(*info->bytecode_array());
859 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860
861 return info->code();
862}
863
864
865MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
866 Handle<JSFunction> function, BailoutId osr_ast_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867 Handle<SharedFunctionInfo> shared(function->shared());
868 DisallowHeapAllocation no_gc;
869 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
870 function->context()->native_context(), osr_ast_id);
871 if (cached.code != nullptr) {
872 // Caching of optimized code enabled and optimized code found.
873 if (cached.literals != nullptr) function->set_literals(cached.literals);
874 DCHECK(!cached.code->marked_for_deoptimization());
875 DCHECK(function->shared()->is_compiled());
876 return Handle<Code>(cached.code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 }
878 return MaybeHandle<Code>();
879}
880
881
882static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
883 Handle<Code> code = info->code();
884 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 // Function context specialization folds-in the function context,
887 // so no sharing can occur.
888 if (info->is_function_context_specializing()) return;
889 // Frame specialization implies function context specialization.
890 DCHECK(!info->is_frame_specializing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 // Cache optimized context-specific code.
893 Handle<JSFunction> function = info->closure();
894 Handle<SharedFunctionInfo> shared(function->shared());
895 Handle<LiteralsArray> literals(function->literals());
896 Handle<Context> native_context(function->context()->native_context());
897 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
898 literals, info->osr_ast_id());
899
900 // Do not cache (native) context-independent code compiled for OSR.
901 if (code->is_turbofanned() && info->is_osr()) return;
902
903 // Cache optimized (native) context-independent code.
904 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
905 !info->is_native_context_specializing()) {
906 DCHECK(!info->is_function_context_specializing());
907 DCHECK(info->osr_ast_id().IsNone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 }
911}
912
913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914static bool Renumber(ParseInfo* parse_info) {
915 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
916 parse_info->literal())) {
917 return false;
918 }
919 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info();
920 if (!shared_info.is_null()) {
921 FunctionLiteral* lit = parse_info->literal();
922 shared_info->set_ast_node_count(lit->ast_node_count());
923 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason());
924 shared_info->set_dont_crankshaft(lit->flags() &
925 AstProperties::kDontCrankshaft);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400926 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 return true;
928}
929
930
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931bool Compiler::Analyze(ParseInfo* info) {
932 DCHECK_NOT_NULL(info->literal());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400933 if (!Rewriter::Rewrite(info)) return false;
934 if (!Scope::Analyze(info)) return false;
935 if (!Renumber(info)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 DCHECK_NOT_NULL(info->scope());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400937 return true;
938}
939
940
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941bool Compiler::ParseAndAnalyze(ParseInfo* info) {
942 if (!Parser::ParseStatic(info)) return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400943 return Compiler::Analyze(info);
944}
945
946
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947static bool GetOptimizedCodeNow(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 Isolate* isolate = info->isolate();
949 CanonicalHandleScope canonical(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
952
953 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954
955 OptimizedCompileJob job(info);
956 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED ||
957 job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED ||
958 job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) {
959 if (FLAG_trace_opt) {
960 PrintF("[aborted optimizing ");
961 info->closure()->ShortPrint();
962 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
963 }
964 return false;
965 }
966
967 // Success!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000969 InsertCodeIntoOptimizedCodeMap(info);
970 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info,
971 info->shared_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 return true;
973}
974
975
976static bool GetOptimizedCodeLater(CompilationInfo* info) {
977 Isolate* isolate = info->isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000978 CanonicalHandleScope canonical(isolate);
979
980 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000981 if (FLAG_trace_concurrent_recompilation) {
982 PrintF(" ** Compilation queue full, will retry optimizing ");
983 info->closure()->ShortPrint();
984 PrintF(" later.\n");
985 }
986 return false;
987 }
988
989 CompilationHandleScope handle_scope(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000990 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
991
992 // Reopen handles in the new CompilationHandleScope.
993 info->ReopenHandlesInNewHandleScope();
994 info->parse_info()->ReopenHandlesInNewHandleScope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995
996 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
997
998 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info);
999 OptimizedCompileJob::Status status = job->CreateGraph();
1000 if (status != OptimizedCompileJob::SUCCEEDED) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002
1003 if (FLAG_trace_concurrent_recompilation) {
1004 PrintF(" ** Queued ");
1005 info->closure()->ShortPrint();
1006 if (info->is_osr()) {
1007 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt());
1008 } else {
1009 PrintF(" for concurrent optimization.\n");
1010 }
1011 }
1012 return true;
1013}
1014
1015
1016MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) {
1017 DCHECK(!function->GetIsolate()->has_pending_exception());
1018 DCHECK(!function->is_compiled());
1019 if (function->shared()->is_compiled()) {
1020 return Handle<Code>(function->shared()->code());
1021 }
1022
1023 CompilationInfoWithZone info(function);
1024 Handle<Code> result;
1025 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result,
1026 GetUnoptimizedCodeCommon(&info),
1027 Code);
1028 return result;
1029}
1030
1031
1032MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001033 Isolate* isolate = function->GetIsolate();
1034 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035 DCHECK(!function->is_compiled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001037 // If the debugger is active, do not compile with turbofan unless we can
1038 // deopt from turbofan code.
1039 if (FLAG_turbo_asm && function->shared()->asm_function() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001040 (FLAG_turbo_asm_deoptimization || !isolate->debug()->is_active()) &&
1041 !FLAG_turbo_osr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042 CompilationInfoWithZone info(function);
1043
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001044 VMState<COMPILER> state(isolate);
1045 PostponeInterruptsScope postpone(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001047 info.SetOptimizing(BailoutId::None(), handle(function->shared()->code()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001049 if (GetOptimizedCodeNow(&info)) {
1050 DCHECK(function->shared()->is_compiled());
1051 return info.code();
1052 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001053 // We have failed compilation. If there was an exception clear it so that
1054 // we can compile unoptimized code.
1055 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056 }
1057
1058 if (function->shared()->is_compiled()) {
1059 return Handle<Code>(function->shared()->code());
1060 }
1061
1062 CompilationInfoWithZone info(function);
1063 Handle<Code> result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001064 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCodeCommon(&info),
1065 Code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001066
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 if (FLAG_always_opt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068 Handle<Code> opt_code;
1069 if (Compiler::GetOptimizedCode(
1070 function, result,
1071 Compiler::NOT_CONCURRENT).ToHandle(&opt_code)) {
1072 result = opt_code;
1073 }
1074 }
1075
1076 return result;
1077}
1078
1079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001081 if (function->is_compiled()) return true;
1082 MaybeHandle<Code> maybe_code = Compiler::GetLazyCode(function);
1083 Handle<Code> code;
1084 if (!maybe_code.ToHandle(&code)) {
1085 if (flag == CLEAR_EXCEPTION) {
1086 function->GetIsolate()->clear_pending_exception();
1087 }
1088 return false;
1089 }
1090 function->ReplaceCode(*code);
1091 DCHECK(function->is_compiled());
1092 return true;
1093}
1094
1095
1096// TODO(turbofan): In the future, unoptimized code with deopt support could
1097// be generated lazily once deopt is triggered.
1098bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099 DCHECK_NOT_NULL(info->literal());
1100 DCHECK(info->has_scope());
1101 Handle<SharedFunctionInfo> shared = info->shared_info();
1102 if (!shared->has_deoptimization_support()) {
1103 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
1104 CompilationInfoWithZone unoptimized(info->closure());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001105 // Note that we use the same AST that we will use for generating the
1106 // optimized code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001107 ParseInfo* parse_info = unoptimized.parse_info();
1108 parse_info->set_literal(info->literal());
1109 parse_info->set_scope(info->scope());
1110 parse_info->set_context(info->context());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111 unoptimized.EnableDeoptimizationSupport();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001112 // If the current code has reloc info for serialization, also include
1113 // reloc info for serialization for the new code, so that deopt support
1114 // can be added without losing IC state.
1115 if (shared->code()->kind() == Code::FUNCTION &&
1116 shared->code()->has_reloc_info_for_serialization()) {
1117 unoptimized.PrepareForSerializing();
1118 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001119 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1120
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 shared->EnableDeoptimizationSupport(*unoptimized.code());
1122 shared->set_feedback_vector(*unoptimized.feedback_vector());
1123
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001124 info->MarkAsCompiled();
1125
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126 // The scope info might not have been set if a lazily compiled
1127 // function is inlined before being called for the first time.
1128 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1129 Handle<ScopeInfo> target_scope_info =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001130 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 shared->set_scope_info(*target_scope_info);
1132 }
1133
1134 // The existing unoptimized code was replaced with the new one.
1135 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
1136 }
1137 return true;
1138}
1139
1140
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001141bool CompileEvalForDebugging(Handle<JSFunction> function,
1142 Handle<SharedFunctionInfo> shared) {
1143 Handle<Script> script(Script::cast(shared->script()));
1144 Handle<Context> context(function->context());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001145
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 Zone zone;
1147 ParseInfo parse_info(&zone, script);
1148 CompilationInfo info(&parse_info);
1149 Isolate* isolate = info.isolate();
1150
1151 parse_info.set_eval();
1152 parse_info.set_context(context);
1153 if (context->IsNativeContext()) parse_info.set_global();
1154 parse_info.set_toplevel();
1155 parse_info.set_allow_lazy_parsing(false);
1156 parse_info.set_language_mode(shared->language_mode());
1157 parse_info.set_parse_restriction(NO_PARSE_RESTRICTION);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158 info.MarkAsDebug();
1159
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 VMState<COMPILER> state(info.isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 if (!Parser::ParseStatic(&parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001163 isolate->clear_pending_exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166
1167 FunctionLiteral* lit = parse_info.literal();
1168 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
1169
1170 if (!CompileUnoptimizedCode(&info)) {
1171 isolate->clear_pending_exception();
1172 return false;
1173 }
1174 shared->ReplaceCode(*info.code());
1175 return true;
1176}
1177
1178
1179bool CompileForDebugging(CompilationInfo* info) {
1180 info->MarkAsDebug();
1181 if (GetUnoptimizedCodeCommon(info).is_null()) {
1182 info->isolate()->clear_pending_exception();
1183 return false;
1184 }
1185 return true;
1186}
1187
1188
1189static inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
1190 return shared->is_toplevel() && shared->script()->IsScript() &&
1191 Script::cast(shared->script())->compilation_type() ==
1192 Script::COMPILATION_TYPE_EVAL;
1193}
1194
1195
1196bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
1197 Handle<SharedFunctionInfo> shared(function->shared());
1198 if (IsEvalToplevel(shared)) {
1199 return CompileEvalForDebugging(function, shared);
1200 } else {
1201 CompilationInfoWithZone info(function);
1202 return CompileForDebugging(&info);
1203 }
1204}
1205
1206
1207bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1208 DCHECK(shared->allows_lazy_compilation_without_context());
1209 DCHECK(!IsEvalToplevel(shared));
1210 Zone zone;
1211 ParseInfo parse_info(&zone, shared);
1212 CompilationInfo info(&parse_info);
1213 return CompileForDebugging(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214}
1215
1216
1217void Compiler::CompileForLiveEdit(Handle<Script> script) {
1218 // TODO(635): support extensions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 Zone zone;
1220 ParseInfo parse_info(&zone, script);
1221 CompilationInfo info(&parse_info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001222 PostponeInterruptsScope postpone(info.isolate());
1223 VMState<COMPILER> state(info.isolate());
1224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001225 // Get rid of old list of shared function infos.
1226 info.MarkAsFirstCompile();
1227 info.MarkAsDebug();
1228 info.parse_info()->set_global();
1229 if (!Parser::ParseStatic(info.parse_info())) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001231 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001232 if (!CompileUnoptimizedCode(&info)) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001233 if (info.has_shared_info()) {
1234 Handle<ScopeInfo> scope_info =
1235 ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001236 info.shared_info()->set_scope_info(*scope_info);
1237 }
1238 tracker.RecordRootFunctionInfo(info.code());
1239}
1240
1241
1242static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
1243 Isolate* isolate = info->isolate();
1244 PostponeInterruptsScope postpone(isolate);
1245 DCHECK(!isolate->native_context().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001246 ParseInfo* parse_info = info->parse_info();
1247 Handle<Script> script = parse_info->script();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001248
1249 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
1250 FixedArray* array = isolate->native_context()->embedder_data();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001251 script->set_context_data(array->get(v8::Context::kDebugIdIndex));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001252
1253 isolate->debug()->OnBeforeCompile(script);
1254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001255 DCHECK(parse_info->is_eval() || parse_info->is_global() ||
1256 parse_info->is_module());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001257
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001258 parse_info->set_toplevel();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001259
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001260 Handle<SharedFunctionInfo> result;
1261
1262 { VMState<COMPILER> state(info->isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263 if (parse_info->literal() == NULL) {
1264 // Parse the script if needed (if it's already parsed, literal() is
1265 // non-NULL). If compiling for debugging, we may eagerly compile inner
1266 // functions, so do not parse lazily in that case.
1267 ScriptCompiler::CompileOptions options = parse_info->compile_options();
1268 bool parse_allow_lazy = (options == ScriptCompiler::kConsumeParserCache ||
1269 String::cast(script->source())->length() >
1270 FLAG_min_preparse_length) &&
1271 !info->is_debug();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001273 parse_info->set_allow_lazy_parsing(parse_allow_lazy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274 if (!parse_allow_lazy &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001275 (options == ScriptCompiler::kProduceParserCache ||
1276 options == ScriptCompiler::kConsumeParserCache)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 // We are going to parse eagerly, but we either 1) have cached data
1278 // produced by lazy parsing or 2) are asked to generate cached data.
1279 // Eager parsing cannot benefit from cached data, and producing cached
1280 // data while parsing eagerly is not implemented.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001281 parse_info->set_cached_data(nullptr);
1282 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001284 if (!Parser::ParseStatic(parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285 return Handle<SharedFunctionInfo>::null();
1286 }
1287 }
1288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001289 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing());
1290
1291 info->MarkAsFirstCompile();
1292
1293 FunctionLiteral* lit = parse_info->literal();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001294 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
1295
1296 // Measure how long it takes to do the compilation; only take the
1297 // rest of the function into account to avoid overlap with the
1298 // parsing statistics.
1299 HistogramTimer* rate = info->is_eval()
1300 ? info->isolate()->counters()->compile_eval()
1301 : info->isolate()->counters()->compile();
1302 HistogramTimerScope timer(rate);
1303
1304 // Compile the code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001305 if (!CompileBaselineCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306 return Handle<SharedFunctionInfo>::null();
1307 }
1308
1309 // Allocate function.
1310 DCHECK(!info->code().is_null());
1311 result = isolate->factory()->NewSharedFunctionInfo(
1312 lit->name(), lit->materialized_literal_count(), lit->kind(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001313 info->code(),
1314 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315 info->feedback_vector());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 if (info->has_bytecode_array()) {
1317 DCHECK(result->function_data()->IsUndefined());
1318 result->set_function_data(*info->bytecode_array());
1319 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320
1321 DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001322 SharedFunctionInfo::InitFromFunctionLiteral(result, lit);
1323 SharedFunctionInfo::SetScript(result, script);
1324 result->set_is_toplevel(true);
1325 if (info->is_eval()) {
1326 // Eval scripts cannot be (re-)compiled without context.
1327 result->set_allows_lazy_compilation_without_context(false);
1328 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001330 Handle<String> script_name =
1331 script->name()->IsString()
1332 ? Handle<String>(String::cast(script->name()))
1333 : isolate->factory()->empty_string();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 Logger::LogEventsAndTags log_tag = info->is_eval()
1335 ? Logger::EVAL_TAG
1336 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
1337
1338 PROFILE(isolate, CodeCreateEvent(
1339 log_tag, *info->code(), *result, info, *script_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340
1341 // Hint to the runtime system used when allocating space for initial
1342 // property space by setting the expected number of properties for
1343 // the instances of the function.
1344 SetExpectedNofPropertiesFromEstimate(result,
1345 lit->expected_property_count());
1346
1347 if (!script.is_null())
1348 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1349
1350 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
1351 }
1352
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001353 return result;
1354}
1355
1356
1357MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1358 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001359 Handle<Context> context, LanguageMode language_mode,
1360 ParseRestriction restriction, int line_offset, int column_offset,
1361 Handle<Object> script_name, ScriptOriginOptions options) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001362 Isolate* isolate = source->GetIsolate();
1363 int source_length = source->length();
1364 isolate->counters()->total_eval_size()->Increment(source_length);
1365 isolate->counters()->total_compile_size()->Increment(source_length);
1366
1367 CompilationCache* compilation_cache = isolate->compilation_cache();
1368 MaybeHandle<SharedFunctionInfo> maybe_shared_info =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 compilation_cache->LookupEval(source, outer_info, context, language_mode,
1370 line_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001371 Handle<SharedFunctionInfo> shared_info;
1372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001373 Handle<Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374 if (!maybe_shared_info.ToHandle(&shared_info)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001375 script = isolate->factory()->NewScript(source);
1376 if (!script_name.is_null()) {
1377 script->set_name(*script_name);
1378 script->set_line_offset(line_offset);
1379 script->set_column_offset(column_offset);
1380 }
1381 script->set_origin_options(options);
1382 Zone zone;
1383 ParseInfo parse_info(&zone, script);
1384 CompilationInfo info(&parse_info);
1385 parse_info.set_eval();
1386 if (context->IsNativeContext()) parse_info.set_global();
1387 parse_info.set_language_mode(language_mode);
1388 parse_info.set_parse_restriction(restriction);
1389 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390
1391 Debug::RecordEvalCaller(script);
1392
1393 shared_info = CompileToplevel(&info);
1394
1395 if (shared_info.is_null()) {
1396 return MaybeHandle<JSFunction>();
1397 } else {
1398 // Explicitly disable optimization for eval code. We're not yet prepared
1399 // to handle eval-code in the optimizing compiler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001400 if (restriction != ONLY_SINGLE_FUNCTION_LITERAL) {
1401 shared_info->DisableOptimization(kEval);
1402 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001403
1404 // If caller is strict mode, the result must be in strict mode as well.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001405 DCHECK(is_sloppy(language_mode) ||
1406 is_strict(shared_info->language_mode()));
1407 compilation_cache->PutEval(source, outer_info, context, shared_info,
1408 line_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409 }
1410 } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) {
1411 shared_info->ResetForNewContext(isolate->heap()->global_ic_age());
1412 }
1413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 Handle<JSFunction> result =
1415 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1416 shared_info, context, NOT_TENURED);
1417
1418 // OnAfterCompile has to be called after we create the JSFunction, which we
1419 // may require to recompile the eval for debugging, if we find a function
1420 // that contains break points in the eval script.
1421 isolate->debug()->OnAfterCompile(script);
1422
1423 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001424}
1425
1426
1427Handle<SharedFunctionInfo> Compiler::CompileScript(
1428 Handle<String> source, Handle<Object> script_name, int line_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001429 int column_offset, ScriptOriginOptions resource_options,
1430 Handle<Object> source_map_url, Handle<Context> context,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 v8::Extension* extension, ScriptData** cached_data,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001432 ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
1433 bool is_module) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001434 Isolate* isolate = source->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001435 if (compile_options == ScriptCompiler::kNoCompileOptions) {
1436 cached_data = NULL;
1437 } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1438 compile_options == ScriptCompiler::kProduceCodeCache) {
1439 DCHECK(cached_data && !*cached_data);
1440 DCHECK(extension == NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001441 DCHECK(!isolate->debug()->is_loaded());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442 } else {
1443 DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1444 compile_options == ScriptCompiler::kConsumeCodeCache);
1445 DCHECK(cached_data && *cached_data);
1446 DCHECK(extension == NULL);
1447 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001448 int source_length = source->length();
1449 isolate->counters()->total_load_size()->Increment(source_length);
1450 isolate->counters()->total_compile_size()->Increment(source_length);
1451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452 // TODO(rossberg): The natives do not yet obey strong mode rules
1453 // (for example, some macros use '==').
1454 bool use_strong = FLAG_use_strong && !isolate->bootstrapper()->IsActive();
1455 LanguageMode language_mode =
1456 construct_language_mode(FLAG_use_strict, use_strong);
1457
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458 CompilationCache* compilation_cache = isolate->compilation_cache();
1459
1460 // Do a lookup in the compilation cache but not for extensions.
1461 MaybeHandle<SharedFunctionInfo> maybe_result;
1462 Handle<SharedFunctionInfo> result;
1463 if (extension == NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001464 // First check per-isolate compilation cache.
1465 maybe_result = compilation_cache->LookupScript(
1466 source, script_name, line_offset, column_offset, resource_options,
1467 context, language_mode);
1468 if (maybe_result.is_null() && FLAG_serialize_toplevel &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 compile_options == ScriptCompiler::kConsumeCodeCache &&
1470 !isolate->debug()->is_loaded()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001471 // Then check cached code provided by embedder.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001473 Handle<SharedFunctionInfo> result;
1474 if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1475 .ToHandle(&result)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001476 // Promote to per-isolate compilation cache.
1477 compilation_cache->PutScript(source, context, language_mode, result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001478 return result;
1479 }
1480 // Deserializer failed. Fall through to compile.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001481 }
1482 }
1483
1484 base::ElapsedTimer timer;
1485 if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
1486 compile_options == ScriptCompiler::kProduceCodeCache) {
1487 timer.Start();
1488 }
1489
1490 if (!maybe_result.ToHandle(&result)) {
1491 // No cache entry found. Compile the script.
1492
1493 // Create a script object describing the script to be compiled.
1494 Handle<Script> script = isolate->factory()->NewScript(source);
1495 if (natives == NATIVES_CODE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001496 script->set_type(Script::TYPE_NATIVE);
1497 script->set_hide_source(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001498 }
1499 if (!script_name.is_null()) {
1500 script->set_name(*script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001501 script->set_line_offset(line_offset);
1502 script->set_column_offset(column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504 script->set_origin_options(resource_options);
1505 if (!source_map_url.is_null()) {
1506 script->set_source_mapping_url(*source_map_url);
1507 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001508
1509 // Compile the function and add it to the cache.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001510 Zone zone;
1511 ParseInfo parse_info(&zone, script);
1512 CompilationInfo info(&parse_info);
1513 if (FLAG_harmony_modules && is_module) {
1514 parse_info.set_module();
1515 } else {
1516 parse_info.set_global();
1517 }
1518 if (compile_options != ScriptCompiler::kNoCompileOptions) {
1519 parse_info.set_cached_data(cached_data);
1520 }
1521 parse_info.set_compile_options(compile_options);
1522 parse_info.set_extension(extension);
1523 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524 if (FLAG_serialize_toplevel &&
1525 compile_options == ScriptCompiler::kProduceCodeCache) {
1526 info.PrepareForSerializing();
1527 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001529 parse_info.set_language_mode(
1530 static_cast<LanguageMode>(info.language_mode() | language_mode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 result = CompileToplevel(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001532 if (extension == NULL && !result.is_null()) {
1533 compilation_cache->PutScript(source, context, language_mode, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534 if (FLAG_serialize_toplevel &&
1535 compile_options == ScriptCompiler::kProduceCodeCache) {
1536 HistogramTimerScope histogram_timer(
1537 isolate->counters()->compile_serialize());
1538 *cached_data = CodeSerializer::Serialize(isolate, result, source);
1539 if (FLAG_profile_deserialization) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001540 PrintF("[Compiling and serializing took %0.3f ms]\n",
1541 timer.Elapsed().InMillisecondsF());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001542 }
1543 }
1544 }
1545
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 if (result.is_null()) {
1547 isolate->ReportPendingMessages();
1548 } else {
1549 isolate->debug()->OnAfterCompile(script);
1550 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551 } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1552 result->ResetForNewContext(isolate->heap()->global_ic_age());
1553 }
1554 return result;
1555}
1556
1557
1558Handle<SharedFunctionInfo> Compiler::CompileStreamedScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559 Handle<Script> script, ParseInfo* parse_info, int source_length) {
1560 Isolate* isolate = script->GetIsolate();
1561 // TODO(titzer): increment the counters in caller.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001562 isolate->counters()->total_load_size()->Increment(source_length);
1563 isolate->counters()->total_compile_size()->Increment(source_length);
1564
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001565 LanguageMode language_mode =
1566 construct_language_mode(FLAG_use_strict, FLAG_use_strong);
1567 parse_info->set_language_mode(
1568 static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1569
1570 CompilationInfo compile_info(parse_info);
1571
1572 // The source was parsed lazily, so compiling for debugging is not possible.
1573 DCHECK(!compile_info.is_debug());
1574
1575 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
1576 if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
1577 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001578}
1579
1580
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001581Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001582 FunctionLiteral* literal, Handle<Script> script,
1583 CompilationInfo* outer_info) {
1584 // Precondition: code has been parsed and scopes have been analyzed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001585 Isolate* isolate = outer_info->isolate();
1586 MaybeHandle<SharedFunctionInfo> maybe_existing;
1587 if (outer_info->is_first_compile()) {
1588 // On the first compile, there are no existing shared function info for
1589 // inner functions yet, so do not try to find them. All bets are off for
1590 // live edit though.
1591 DCHECK(script->FindSharedFunctionInfo(literal).is_null() ||
1592 isolate->debug()->live_edit_enabled());
1593 } else {
1594 maybe_existing = script->FindSharedFunctionInfo(literal);
1595 }
1596 // We found an existing shared function info. If it's already compiled,
1597 // don't worry about compiling it, and simply return it. If it's not yet
1598 // compiled, continue to decide whether to eagerly compile.
1599 // Carry on if we are compiling eager to obtain code for debugging,
1600 // unless we already have code with debut break slots.
1601 Handle<SharedFunctionInfo> existing;
1602 if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) {
1603 if (!outer_info->is_debug() || existing->HasDebugCode()) {
1604 return existing;
1605 }
1606 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001607
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001608 Zone zone;
1609 ParseInfo parse_info(&zone, script);
1610 CompilationInfo info(&parse_info);
1611 parse_info.set_literal(literal);
1612 parse_info.set_scope(literal->scope());
1613 parse_info.set_language_mode(literal->scope()->language_mode());
1614 if (outer_info->will_serialize()) info.PrepareForSerializing();
1615 if (outer_info->is_first_compile()) info.MarkAsFirstCompile();
1616 if (outer_info->is_debug()) info.MarkAsDebug();
1617
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001618 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
1619 // Determine if the function can be lazily compiled. This is necessary to
1620 // allow some of our builtin JS files to be lazily compiled. These
1621 // builtins cannot be handled lazily by the parser, since we have to know
1622 // if a function uses the special natives syntax, which is something the
1623 // parser records.
1624 // If the debugger requests compilation for break points, we cannot be
1625 // aggressive about lazy compilation, because it might trigger compilation
1626 // of functions without an outer context when setting a breakpoint through
1627 // Debug::FindSharedFunctionInfoInScript.
1628 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001629 // Compile eagerly for live edit. When compiling debug code, eagerly compile
1630 // unless we can lazily compile without the context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001631 bool allow_lazy = literal->AllowsLazyCompilation() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001632 !LiveEditFunctionTracker::IsActive(isolate) &&
1633 (!info.is_debug() || allow_lazy_without_ctx);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635 bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001636
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637 // Generate code
1638 Handle<ScopeInfo> scope_info;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001639 if (lazy) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001640 Handle<Code> code = isolate->builtins()->CompileLazy();
1641 info.SetCode(code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001642 // There's no need in theory for a lazy-compiled function to have a type
1643 // feedback vector, but some parts of the system expect all
1644 // SharedFunctionInfo instances to have one. The size of the vector depends
1645 // on how many feedback-needing nodes are in the tree, and when lazily
1646 // parsing we might not know that, if this function was never parsed before.
1647 // In that case the vector will be replaced the next time MakeCode is
1648 // called.
1649 info.EnsureFeedbackVector();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001650 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 } else if (Renumber(info.parse_info()) && GenerateBaselineCode(&info)) {
1652 // Code generation will ensure that the feedback vector is present and
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001653 // appropriately sized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001654 DCHECK(!info.code().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001655 scope_info = ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
1656 if (literal->should_eager_compile() &&
1657 literal->should_be_used_once_hint()) {
1658 info.code()->MarkToBeExecutedOnce(isolate);
1659 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001660 } else {
1661 return Handle<SharedFunctionInfo>::null();
1662 }
1663
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001664 if (maybe_existing.is_null()) {
1665 // Create a shared function info object.
1666 Handle<SharedFunctionInfo> result =
1667 isolate->factory()->NewSharedFunctionInfo(
1668 literal->name(), literal->materialized_literal_count(),
1669 literal->kind(), info.code(), scope_info, info.feedback_vector());
1670 if (info.has_bytecode_array()) {
1671 DCHECK(result->function_data()->IsUndefined());
1672 result->set_function_data(*info.bytecode_array());
1673 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001674
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675 SharedFunctionInfo::InitFromFunctionLiteral(result, literal);
1676 SharedFunctionInfo::SetScript(result, script);
1677 result->set_is_toplevel(false);
1678 // If the outer function has been compiled before, we cannot be sure that
1679 // shared function info for this function literal has been created for the
1680 // first time. It may have already been compiled previously.
1681 result->set_never_compiled(outer_info->is_first_compile() && lazy);
1682
1683 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1684 result->set_allows_lazy_compilation(literal->AllowsLazyCompilation());
1685 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1686
1687 // Set the expected number of properties for instances and return
1688 // the resulting function.
1689 SetExpectedNofPropertiesFromEstimate(result,
1690 literal->expected_property_count());
1691 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
1692 return result;
1693 } else if (!lazy) {
1694 // Assert that we are not overwriting (possibly patched) debug code.
1695 DCHECK(!existing->HasDebugCode());
1696 existing->ReplaceCode(*info.code());
1697 existing->set_scope_info(*scope_info);
1698 existing->set_feedback_vector(*info.feedback_vector());
1699 }
1700 return existing;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001701}
1702
1703
1704MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
1705 Handle<Code> current_code,
1706 ConcurrencyMode mode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001707 BailoutId osr_ast_id,
1708 JavaScriptFrame* osr_frame) {
1709 Isolate* isolate = function->GetIsolate();
1710 Handle<SharedFunctionInfo> shared(function->shared(), isolate);
1711 if (shared->HasDebugInfo()) return MaybeHandle<Code>();
1712
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001713 Handle<Code> cached_code;
1714 if (GetCodeFromOptimizedCodeMap(
1715 function, osr_ast_id).ToHandle(&cached_code)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001716 if (FLAG_trace_opt) {
1717 PrintF("[found optimized code for ");
1718 function->ShortPrint();
1719 if (!osr_ast_id.IsNone()) {
1720 PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
1721 }
1722 PrintF("]\n");
1723 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 return cached_code;
1725 }
1726
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001727 DCHECK(AllowCompilation::IsAllowed(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001729 if (!shared->is_compiled() ||
1730 shared->scope_info() == ScopeInfo::Empty(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001731 // The function was never compiled. Compile it unoptimized first.
1732 // TODO(titzer): reuse the AST and scope info from this compile.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001733 CompilationInfoWithZone unoptimized(function);
1734 unoptimized.EnableDeoptimizationSupport();
1735 if (!GetUnoptimizedCodeCommon(&unoptimized).ToHandle(&current_code)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001736 return MaybeHandle<Code>();
1737 }
1738 shared->ReplaceCode(*current_code);
1739 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001740
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001741 current_code->set_profiler_ticks(0);
1742
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001743 // TODO(mstarzinger): We cannot properly deserialize a scope chain containing
1744 // an eval scope and hence would fail at parsing the eval source again.
1745 if (shared->disable_optimization_reason() == kEval) {
1746 return MaybeHandle<Code>();
1747 }
1748
1749 // TODO(mstarzinger): We cannot properly deserialize a scope chain for the
1750 // builtin context, hence Genesis::InstallExperimentalNatives would fail.
1751 if (shared->is_toplevel() && isolate->bootstrapper()->IsActive()) {
1752 return MaybeHandle<Code>();
1753 }
1754
1755 base::SmartPointer<CompilationInfo> info(
1756 new CompilationInfoWithZone(function));
1757 VMState<COMPILER> state(isolate);
1758 DCHECK(!isolate->has_pending_exception());
1759 PostponeInterruptsScope postpone(isolate);
1760
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001761 info->SetOptimizing(osr_ast_id, current_code);
1762
1763 if (mode == CONCURRENT) {
1764 if (GetOptimizedCodeLater(info.get())) {
1765 info.Detach(); // The background recompile job owns this now.
1766 return isolate->builtins()->InOptimizationQueue();
1767 }
1768 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001769 info->set_osr_frame(osr_frame);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001770 if (GetOptimizedCodeNow(info.get())) return info->code();
1771 }
1772
1773 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1774 return MaybeHandle<Code>();
1775}
1776
1777
1778Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) {
1779 // Take ownership of compilation info. Deleting compilation info
1780 // also tears down the zone and the recompile job.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001781 base::SmartPointer<CompilationInfo> info(job->info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001782 Isolate* isolate = info->isolate();
1783
1784 VMState<COMPILER> state(isolate);
1785 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
1786
1787 Handle<SharedFunctionInfo> shared = info->shared_info();
1788 shared->code()->set_profiler_ticks(0);
1789
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001790 DCHECK(!shared->HasDebugInfo());
1791
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001792 // 1) Optimization on the concurrent thread may have failed.
1793 // 2) The function may have already been optimized by OSR. Simply continue.
1794 // Except when OSR already disabled optimization for some reason.
1795 // 3) The code may have already been invalidated due to dependency change.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001796 // 4) Code generation may have failed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001797 if (job->last_status() == OptimizedCompileJob::SUCCEEDED) {
1798 if (shared->optimization_disabled()) {
1799 job->RetryOptimization(kOptimizationDisabled);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001800 } else if (info->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001801 job->RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802 } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
1803 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001804 if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
1805 info->osr_ast_id()).code == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001806 InsertCodeIntoOptimizedCodeMap(info.get());
1807 }
1808 if (FLAG_trace_opt) {
1809 PrintF("[completed optimizing ");
1810 info->closure()->ShortPrint();
1811 PrintF("]\n");
1812 }
1813 return Handle<Code>(*info->code());
1814 }
1815 }
1816
1817 DCHECK(job->last_status() != OptimizedCompileJob::SUCCEEDED);
1818 if (FLAG_trace_opt) {
1819 PrintF("[aborted optimizing ");
1820 info->closure()->ShortPrint();
1821 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
1822 }
1823 return Handle<Code>::null();
1824}
1825
1826
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001827CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001828 : name_(name), info_(info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001829 if (FLAG_hydrogen_stats) {
1830 info_zone_start_allocation_size_ = info->zone()->allocation_size();
1831 timer_.Start();
1832 }
1833}
1834
1835
1836CompilationPhase::~CompilationPhase() {
1837 if (FLAG_hydrogen_stats) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001838 size_t size = zone()->allocation_size();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001839 size += info_->zone()->allocation_size() - info_zone_start_allocation_size_;
1840 isolate()->GetHStatistics()->SaveTiming(name_, timer_.Elapsed(), size);
1841 }
1842}
1843
1844
1845bool CompilationPhase::ShouldProduceTraceOutput() const {
1846 // Trace if the appropriate trace flag is set and the phase name's first
1847 // character is in the FLAG_trace_phase command line parameter.
1848 AllowHandleDereference allow_deref;
1849 bool tracing_on = info()->IsStub()
1850 ? FLAG_trace_hydrogen_stubs
1851 : (FLAG_trace_hydrogen &&
1852 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
1853 return (tracing_on &&
1854 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1855}
1856
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001857#if DEBUG
1858void CompilationInfo::PrintAstForTesting() {
1859 PrintF("--- Source from AST ---\n%s\n",
1860 PrettyPrinter(isolate()).PrintProgram(literal()));
1861}
1862#endif
1863} // namespace internal
1864} // namespace v8