blob: 3b52aa2d3b925925b243fe13836641725c1d69d4 [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/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/compiler.h"
Ben Murdochf87a2032010-10-22 12:50:53 +01008
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include "src/ast-numbering.h"
10#include "src/ast-this-access-visitor.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/bootstrapper.h"
12#include "src/codegen.h"
13#include "src/compilation-cache.h"
14#include "src/compiler/pipeline.h"
15#include "src/cpu-profiler.h"
16#include "src/debug.h"
17#include "src/deoptimizer.h"
18#include "src/full-codegen.h"
19#include "src/gdb-jit.h"
20#include "src/hydrogen.h"
21#include "src/isolate-inl.h"
22#include "src/lithium.h"
23#include "src/liveedit.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024#include "src/messages.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025#include "src/parser.h"
26#include "src/rewriter.h"
27#include "src/runtime-profiler.h"
28#include "src/scanner-character-streams.h"
29#include "src/scopeinfo.h"
30#include "src/scopes.h"
31#include "src/typing.h"
32#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033
34namespace v8 {
35namespace internal {
36
Ben Murdochf87a2032010-10-22 12:50:53 +010037
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038ScriptData::ScriptData(const byte* data, int length)
Emily Bernierd0a1eb72015-03-24 16:35:39 -040039 : owns_data_(false), rejected_(false), data_(data), length_(length) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040 if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) {
41 byte* copy = NewArray<byte>(length);
42 DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment));
43 CopyBytes(copy, data, length);
44 data_ = copy;
45 AcquireDataOwnership();
46 }
Ben Murdochf87a2032010-10-22 12:50:53 +010047}
48
49
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050CompilationInfo::CompilationInfo(Handle<Script> script, Zone* zone)
51 : flags_(kThisHasUses),
52 script_(script),
53 source_stream_(NULL),
54 osr_ast_id_(BailoutId::None()),
55 parameter_count_(0),
56 optimization_id_(-1),
57 ast_value_factory_(NULL),
58 ast_value_factory_owned_(false),
59 aborted_due_to_dependency_change_(false) {
60 Initialize(script->GetIsolate(), BASE, zone);
61}
62
63
64CompilationInfo::CompilationInfo(Isolate* isolate, Zone* zone)
65 : flags_(kThisHasUses),
66 script_(Handle<Script>::null()),
67 source_stream_(NULL),
68 osr_ast_id_(BailoutId::None()),
69 parameter_count_(0),
70 optimization_id_(-1),
71 ast_value_factory_(NULL),
72 ast_value_factory_owned_(false),
73 aborted_due_to_dependency_change_(false) {
74 Initialize(isolate, STUB, zone);
75}
76
77
78CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
79 Zone* zone)
80 : flags_(kLazy | kThisHasUses),
Ben Murdochf87a2032010-10-22 12:50:53 +010081 shared_info_(shared_info),
82 script_(Handle<Script>(Script::cast(shared_info->script()))),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 source_stream_(NULL),
84 osr_ast_id_(BailoutId::None()),
85 parameter_count_(0),
86 optimization_id_(-1),
87 ast_value_factory_(NULL),
88 ast_value_factory_owned_(false),
89 aborted_due_to_dependency_change_(false) {
90 Initialize(script_->GetIsolate(), BASE, zone);
Ben Murdochf87a2032010-10-22 12:50:53 +010091}
92
93
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094CompilationInfo::CompilationInfo(Handle<JSFunction> closure, Zone* zone)
95 : flags_(kLazy | kThisHasUses),
Ben Murdochf87a2032010-10-22 12:50:53 +010096 closure_(closure),
97 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
98 script_(Handle<Script>(Script::cast(shared_info_->script()))),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 source_stream_(NULL),
100 context_(closure->context()),
101 osr_ast_id_(BailoutId::None()),
102 parameter_count_(0),
103 optimization_id_(-1),
104 ast_value_factory_(NULL),
105 ast_value_factory_owned_(false),
106 aborted_due_to_dependency_change_(false) {
107 Initialize(script_->GetIsolate(), BASE, zone);
Ben Murdochf87a2032010-10-22 12:50:53 +0100108}
109
110
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111CompilationInfo::CompilationInfo(HydrogenCodeStub* stub, Isolate* isolate,
112 Zone* zone)
113 : flags_(kLazy | kThisHasUses),
114 source_stream_(NULL),
115 osr_ast_id_(BailoutId::None()),
116 parameter_count_(0),
117 optimization_id_(-1),
118 ast_value_factory_(NULL),
119 ast_value_factory_owned_(false),
120 aborted_due_to_dependency_change_(false) {
121 Initialize(isolate, STUB, zone);
122 code_stub_ = stub;
123}
124
125
126CompilationInfo::CompilationInfo(
127 ScriptCompiler::ExternalSourceStream* stream,
128 ScriptCompiler::StreamedSource::Encoding encoding, Isolate* isolate,
129 Zone* zone)
130 : flags_(kThisHasUses),
131 source_stream_(stream),
132 source_stream_encoding_(encoding),
133 osr_ast_id_(BailoutId::None()),
134 parameter_count_(0),
135 optimization_id_(-1),
136 ast_value_factory_(NULL),
137 ast_value_factory_owned_(false),
138 aborted_due_to_dependency_change_(false) {
139 Initialize(isolate, BASE, zone);
140}
141
142
143void CompilationInfo::Initialize(Isolate* isolate,
144 Mode mode,
145 Zone* zone) {
146 isolate_ = isolate;
147 function_ = NULL;
148 scope_ = NULL;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149 script_scope_ = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 extension_ = NULL;
151 cached_data_ = NULL;
152 compile_options_ = ScriptCompiler::kNoCompileOptions;
153 zone_ = zone;
154 deferred_handles_ = NULL;
155 code_stub_ = NULL;
156 prologue_offset_ = Code::kPrologueOffsetNotSet;
157 opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
158 no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
159 ? new List<OffsetRange>(2) : NULL;
160 for (int i = 0; i < DependentCode::kGroupCount; i++) {
161 dependencies_[i] = NULL;
162 }
163 if (mode == STUB) {
164 mode_ = STUB;
165 return;
166 }
167 mode_ = mode;
168 if (!script_.is_null() && script_->type()->value() == Script::TYPE_NATIVE) {
169 MarkAsNative();
170 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400171 // Compiling for the snapshot typically results in different code than
172 // compiling later on. This means that code recompiled with deoptimization
173 // support won't be "equivalent" (as defined by SharedFunctionInfo::
174 // EnableDeoptimizationSupport), so it will replace the old code and all
175 // its type feedback. To avoid this, always compile functions in the snapshot
176 // with deoptimization support.
177 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
178
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 if (isolate_->debug()->is_active()) MarkAsDebug();
180 if (FLAG_context_specialization) MarkAsContextSpecializing();
181 if (FLAG_turbo_inlining) MarkAsInliningEnabled();
182 if (FLAG_turbo_types) MarkAsTypingEnabled();
183
184 if (!shared_info_.is_null()) {
185 DCHECK(strict_mode() == SLOPPY);
186 SetStrictMode(shared_info_->strict_mode());
187 }
188 bailout_reason_ = kUnknown;
189
190 if (!shared_info().is_null() && shared_info()->is_compiled()) {
191 // We should initialize the CompilationInfo feedback vector from the
192 // passed in shared info, rather than creating a new one.
193 feedback_vector_ =
194 Handle<TypeFeedbackVector>(shared_info()->feedback_vector(), isolate);
195 }
196}
197
198
199CompilationInfo::~CompilationInfo() {
200 if (GetFlag(kDisableFutureOptimization)) {
201 shared_info()->DisableOptimization(bailout_reason());
202 }
203 delete deferred_handles_;
204 delete no_frame_ranges_;
205 if (ast_value_factory_owned_) delete ast_value_factory_;
206#ifdef DEBUG
207 // Check that no dependent maps have been added or added dependent maps have
208 // been rolled back or committed.
209 for (int i = 0; i < DependentCode::kGroupCount; i++) {
210 DCHECK_EQ(NULL, dependencies_[i]);
211 }
212#endif // DEBUG
213}
214
215
216void CompilationInfo::CommitDependencies(Handle<Code> code) {
217 for (int i = 0; i < DependentCode::kGroupCount; i++) {
218 ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
219 if (group_objects == NULL) continue;
220 DCHECK(!object_wrapper_.is_null());
221 for (int j = 0; j < group_objects->length(); j++) {
222 DependentCode::DependencyGroup group =
223 static_cast<DependentCode::DependencyGroup>(i);
224 DependentCode* dependent_code =
225 DependentCode::ForObject(group_objects->at(j), group);
226 dependent_code->UpdateToFinishedCode(group, this, *code);
227 }
228 dependencies_[i] = NULL; // Zone-allocated, no need to delete.
229 }
230}
231
232
233void CompilationInfo::RollbackDependencies() {
234 // Unregister from all dependent maps if not yet committed.
235 for (int i = 0; i < DependentCode::kGroupCount; i++) {
236 ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
237 if (group_objects == NULL) continue;
238 for (int j = 0; j < group_objects->length(); j++) {
239 DependentCode::DependencyGroup group =
240 static_cast<DependentCode::DependencyGroup>(i);
241 DependentCode* dependent_code =
242 DependentCode::ForObject(group_objects->at(j), group);
243 dependent_code->RemoveCompilationInfo(group, this);
244 }
245 dependencies_[i] = NULL; // Zone-allocated, no need to delete.
246 }
247}
248
249
250int CompilationInfo::num_parameters() const {
251 if (IsStub()) {
252 DCHECK(parameter_count_ > 0);
253 return parameter_count_;
254 } else {
255 return scope()->num_parameters();
256 }
257}
258
259
260int CompilationInfo::num_heap_slots() const {
261 if (IsStub()) {
262 return 0;
263 } else {
264 return scope()->num_heap_slots();
265 }
266}
267
268
269Code::Flags CompilationInfo::flags() const {
270 if (IsStub()) {
271 return Code::ComputeFlags(code_stub()->GetCodeKind(),
272 code_stub()->GetICState(),
273 code_stub()->GetExtraICState(),
274 code_stub()->GetStubType());
275 } else {
276 return Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
277 }
Ben Murdoch257744e2011-11-30 15:57:28 +0000278}
Ben Murdochb8e0da22011-05-16 14:20:40 +0100279
Ben Murdoch257744e2011-11-30 15:57:28 +0000280
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100281// Primitive functions are unlikely to be picked up by the stack-walking
282// profiler, so they trigger their own optimization when they're called
283// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
284bool CompilationInfo::ShouldSelfOptimize() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 return FLAG_crankshaft &&
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100286 !function()->flags()->Contains(kDontSelfOptimize) &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 !function()->dont_optimize() &&
288 function()->scope()->AllowsLazyCompilation() &&
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100289 (shared_info().is_null() || !shared_info()->optimization_disabled());
290}
291
292
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293void CompilationInfo::PrepareForCompilation(Scope* scope) {
294 DCHECK(scope_ == NULL);
295 scope_ = scope;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400296}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400298
299void CompilationInfo::EnsureFeedbackVector() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300 if (feedback_vector_.is_null()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400301 feedback_vector_ = isolate()->factory()->NewTypeFeedbackVector(
302 function()->feedback_vector_spec());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100304}
305
306
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
308 public:
309 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
310 : HOptimizedGraphBuilder(info) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100311 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100312
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400313#define DEF_VISIT(type) \
314 void Visit##type(type* node) OVERRIDE { \
315 if (node->position() != RelocInfo::kNoPosition) { \
316 SetSourcePosition(node->position()); \
317 } \
318 HOptimizedGraphBuilder::Visit##type(node); \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100319 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 EXPRESSION_NODE_LIST(DEF_VISIT)
321#undef DEF_VISIT
Ben Murdochb0fe1622011-05-05 13:52:32 +0100322
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400323#define DEF_VISIT(type) \
324 void Visit##type(type* node) OVERRIDE { \
325 if (node->position() != RelocInfo::kNoPosition) { \
326 SetSourcePosition(node->position()); \
327 } \
328 HOptimizedGraphBuilder::Visit##type(node); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 }
330 STATEMENT_NODE_LIST(DEF_VISIT)
331#undef DEF_VISIT
332
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400333#define DEF_VISIT(type) \
334 void Visit##type(type* node) OVERRIDE { \
335 HOptimizedGraphBuilder::Visit##type(node); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 }
337 MODULE_NODE_LIST(DEF_VISIT)
338 DECLARATION_NODE_LIST(DEF_VISIT)
339#undef DEF_VISIT
340};
341
342
343OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 DCHECK(info()->IsOptimizing());
345 DCHECK(!info()->IsCompilingForDebugging());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100346
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400347 // Optimization could have been disabled by the parser.
348 if (info()->shared_info()->optimization_disabled()) {
349 return AbortOptimization(
350 info()->shared_info()->disable_optimization_reason());
351 }
Steve Block44f0eee2011-05-26 01:26:41 +0100352
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 // Do not use crankshaft if we need to be able to set break points.
354 if (isolate()->DebuggerHasBreakPoints()) {
355 return RetryOptimization(kDebuggerHasBreakPoints);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100356 }
357
358 // Limit the number of times we re-compile a functions with
359 // the optimizing compiler.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100360 const int kMaxOptCount =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
362 if (info()->opt_count() > kMaxOptCount) {
363 return AbortOptimization(kOptimizedTooManyTimes);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100364 }
365
366 // Due to an encoding limit on LUnallocated operands in the Lithium
367 // language, we cannot optimize functions with too many formal parameters
368 // or perform on-stack replacement for function with too many
369 // stack-allocated local variables.
370 //
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100371 // The encoding is as a signed value, with parameters and receiver using
372 // the negative indices and locals the non-negative ones.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex;
374 Scope* scope = info()->scope();
375 if ((scope->num_parameters() + 1) > parameter_limit) {
376 return AbortOptimization(kTooManyParameters);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100377 }
378
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000379 const int locals_limit = LUnallocated::kMaxFixedSlotIndex;
380 if (info()->is_osr() &&
381 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
382 return AbortOptimization(kTooManyParametersLocals);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100383 }
384
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385 if (scope->HasIllegalRedeclaration()) {
386 return AbortOptimization(kFunctionWithIllegalRedeclaration);
387 }
388
389 // Check the whitelist for Crankshaft.
390 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) {
391 return AbortOptimization(kHydrogenFilter);
392 }
393
394 // Crankshaft requires a version of fullcode with deoptimization support.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100395 // Recompile the unoptimized version of the code if the current version
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 // doesn't have deoptimization support already.
397 // Otherwise, if we are gathering compilation time and space statistics
398 // for hydrogen, gather baseline statistics for a fullcode compilation.
399 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
Steve Block44f0eee2011-05-26 01:26:41 +0100400 if (should_recompile || FLAG_hydrogen_stats) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 base::ElapsedTimer timer;
402 if (FLAG_hydrogen_stats) {
403 timer.Start();
404 }
405 if (!Compiler::EnsureDeoptimizationSupport(info())) {
406 return SetLastStatus(FAILED);
407 }
408 if (FLAG_hydrogen_stats) {
409 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100410 }
411 }
412
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 DCHECK(info()->shared_info()->has_deoptimization_support());
414
415 // Check the whitelist for TurboFan.
416 if ((FLAG_turbo_asm && info()->shared_info()->asm_function()) ||
417 info()->closure()->PassesFilter(FLAG_turbo_filter)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400418 if (FLAG_trace_opt) {
419 OFStream os(stdout);
420 os << "[compiling method " << Brief(*info()->closure())
421 << " using TurboFan]" << std::endl;
422 }
423 Timer t(this, &time_taken_to_create_graph_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 compiler::Pipeline pipeline(info());
425 pipeline.GenerateCode();
426 if (!info()->code().is_null()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 return SetLastStatus(SUCCEEDED);
428 }
429 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100430
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400431 if (FLAG_trace_opt) {
432 OFStream os(stdout);
433 os << "[compiling method " << Brief(*info()->closure())
434 << " using Crankshaft]" << std::endl;
435 }
436
Ben Murdochb0fe1622011-05-05 13:52:32 +0100437 if (FLAG_trace_hydrogen) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 isolate()->GetHTracer()->TraceCompilation(info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100439 }
440
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441 // Type-check the function.
442 AstTyper::Run(info());
443
444 graph_builder_ = (FLAG_hydrogen_track_positions || FLAG_trace_ic)
445 ? new(info()->zone()) HOptimizedGraphBuilderWithPositions(info())
446 : new(info()->zone()) HOptimizedGraphBuilder(info());
447
448 Timer t(this, &time_taken_to_create_graph_);
449 info()->set_this_has_uses(false);
450 graph_ = graph_builder_->CreateGraph();
451
452 if (isolate()->has_pending_exception()) {
453 return SetLastStatus(FAILED);
Steve Block1e0659c2011-05-24 12:43:12 +0100454 }
455
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456 if (graph_ == NULL) return SetLastStatus(BAILED_OUT);
457
458 if (info()->HasAbortedDueToDependencyChange()) {
459 // Dependency has changed during graph creation. Let's try again later.
460 return RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100461 }
462
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 return SetLastStatus(SUCCEEDED);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100464}
465
466
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() {
468 DisallowHeapAllocation no_allocation;
469 DisallowHandleAllocation no_handles;
470 DisallowHandleDereference no_deref;
471 DisallowCodeDependencyChange no_dependency_change;
Ben Murdoch257744e2011-11-30 15:57:28 +0000472
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473 DCHECK(last_status() == SUCCEEDED);
474 // TODO(turbofan): Currently everything is done in the first phase.
475 if (!info()->code().is_null()) {
476 return last_status();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100477 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478
479 Timer t(this, &time_taken_to_optimize_);
480 DCHECK(graph_ != NULL);
481 BailoutReason bailout_reason = kNoReason;
482
483 if (graph_->Optimize(&bailout_reason)) {
484 chunk_ = LChunk::NewChunk(graph_);
485 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
486 } else if (bailout_reason != kNoReason) {
487 graph_builder_->Bailout(bailout_reason);
488 }
489
490 return SetLastStatus(BAILED_OUT);
Steve Block6ded16b2010-05-10 14:33:55 +0100491}
Steve Block6ded16b2010-05-10 14:33:55 +0100492
493
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
495 DCHECK(last_status() == SUCCEEDED);
496 // TODO(turbofan): Currently everything is done in the first phase.
497 if (!info()->code().is_null()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400498 if (FLAG_turbo_deoptimization) {
499 info()->context()->native_context()->AddOptimizedCode(*info()->code());
500 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 RecordOptimizationStats();
502 return last_status();
503 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000504
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 DCHECK(!info()->HasAbortedDueToDependencyChange());
506 DisallowCodeDependencyChange no_dependency_change;
507 DisallowJavascriptExecution no_js(isolate());
508 { // Scope for timer.
509 Timer timer(this, &time_taken_to_codegen_);
510 DCHECK(chunk_ != NULL);
511 DCHECK(graph_ != NULL);
512 // Deferred handles reference objects that were accessible during
513 // graph creation. To make sure that we don't encounter inconsistencies
514 // between graph creation and code generation, we disallow accessing
515 // objects through deferred handles during the latter, with exceptions.
516 DisallowDeferredHandleDereference no_deferred_handle_deref;
517 Handle<Code> optimized_code = chunk_->Codegen();
518 if (optimized_code.is_null()) {
519 if (info()->bailout_reason() == kNoReason) {
520 return AbortOptimization(kCodeGenerationFailed);
Leon Clarke4515c472010-02-03 11:58:03 +0000521 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 return SetLastStatus(BAILED_OUT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000523 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524 info()->SetCode(optimized_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 RecordOptimizationStats();
527 // Add to the weak list of optimized code objects.
528 info()->context()->native_context()->AddOptimizedCode(*info()->code());
529 return SetLastStatus(SUCCEEDED);
Steve Blocka7e24c12009-10-30 11:49:00 +0000530}
531
532
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533void OptimizedCompileJob::RecordOptimizationStats() {
534 Handle<JSFunction> function = info()->closure();
535 if (!function->IsOptimized()) {
536 // Concurrent recompilation and OSR may race. Increment only once.
537 int opt_count = function->shared()->opt_count();
538 function->shared()->set_opt_count(opt_count + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000540 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
541 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
542 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
543 if (FLAG_trace_opt) {
544 PrintF("[optimizing ");
545 function->ShortPrint();
546 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
547 ms_codegen);
Steve Blocka7e24c12009-10-30 11:49:00 +0000548 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549 if (FLAG_trace_opt_stats) {
550 static double compilation_time = 0.0;
551 static int compiled_functions = 0;
552 static int code_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000553
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000554 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
555 compiled_functions++;
556 code_size += function->shared()->SourceSize();
557 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
558 compiled_functions,
559 code_size,
560 compilation_time);
561 }
562 if (FLAG_hydrogen_stats) {
563 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
564 time_taken_to_optimize_,
565 time_taken_to_codegen_);
566 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000567}
568
569
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570// Sets the expected number of properties based on estimate from compiler.
571void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
572 int estimate) {
573 // If no properties are added in the constructor, they are more likely
574 // to be added later.
575 if (estimate == 0) estimate = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +0000576
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 // TODO(yangguo): check whether those heuristics are still up-to-date.
578 // We do not shrink objects that go into a snapshot (yet), so we adjust
579 // the estimate conservatively.
580 if (shared->GetIsolate()->serializer_enabled()) {
581 estimate += 2;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400582 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 // Inobject slack tracking will reclaim redundant inobject space later,
584 // so we can afford to adjust the estimate generously.
585 estimate += 8;
Steve Blocka7e24c12009-10-30 11:49:00 +0000586 }
587
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000588 shared->set_expected_nof_properties(estimate);
Steve Blockd0582a62009-12-15 09:54:21 +0000589}
590
591
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400592static void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
593 BailoutReason bailout_reason) {
594 if (bailout_reason != kNoReason) {
595 shared_info->DisableOptimization(bailout_reason);
596 }
597}
598
599
Steve Blockd0582a62009-12-15 09:54:21 +0000600// Sets the function info on a function.
601// The start_position points to the first '(' character after the function name
602// in the full script source. When counting characters in the script source the
603// the first character is number 0 (not 1).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
605 FunctionLiteral* lit,
606 bool is_toplevel,
607 Handle<Script> script) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100608 function_info->set_length(lit->parameter_count());
609 function_info->set_formal_parameter_count(lit->parameter_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100610 function_info->set_script(*script);
611 function_info->set_function_token_position(lit->function_token_position());
612 function_info->set_start_position(lit->start_position());
613 function_info->set_end_position(lit->end_position());
614 function_info->set_is_expression(lit->is_expression());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000615 function_info->set_is_anonymous(lit->is_anonymous());
Steve Block6ded16b2010-05-10 14:33:55 +0100616 function_info->set_is_toplevel(is_toplevel);
617 function_info->set_inferred_name(*lit->inferred_name());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100618 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 function_info->set_allows_lazy_compilation_without_context(
620 lit->AllowsLazyCompilationWithoutContext());
621 function_info->set_strict_mode(lit->strict_mode());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000622 function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
623 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100624 function_info->set_ast_node_count(lit->ast_node_count());
625 function_info->set_is_function(lit->is_function());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400626 MaybeDisableOptimization(function_info, lit->dont_optimize_reason());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627 function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
628 function_info->set_kind(lit->kind());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400629 function_info->set_uses_super_property(lit->uses_super_property());
630 function_info->set_uses_super_constructor_call(
631 lit->uses_super_constructor_call());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 function_info->set_asm_function(lit->scope()->asm_function());
Steve Blockd0582a62009-12-15 09:54:21 +0000633}
634
635
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
637 CompilationInfo* info,
638 Handle<SharedFunctionInfo> shared) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100639 // SharedFunctionInfo is passed separately, because if CompilationInfo
640 // was created using Script object, it will not have it.
641
Ben Murdochf87a2032010-10-22 12:50:53 +0100642 // Log the code generation. If source information is available include
643 // script name and line number. Check explicitly whether logging is
644 // enabled as finding the line number is not free.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 if (info->isolate()->logger()->is_logging_code_events() ||
646 info->isolate()->cpu_profiler()->is_profiling()) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100647 Handle<Script> script = info->script();
648 Handle<Code> code = info->code();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649 if (code.is_identical_to(info->isolate()->builtins()->CompileLazy())) {
Steve Block44f0eee2011-05-26 01:26:41 +0100650 return;
Andrei Popescu31002712010-02-23 13:46:05 +0000651 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
653 int column_num =
654 Script::GetColumnNumber(script, shared->start_position()) + 1;
655 String* script_name = script->name()->IsString()
656 ? String::cast(script->name())
657 : info->isolate()->heap()->empty_string();
658 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
659 PROFILE(info->isolate(),
660 CodeCreateEvent(log_tag, *code, *shared, info, script_name,
661 line_num, column_num));
Andrei Popescu31002712010-02-23 13:46:05 +0000662 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100663
Ben Murdoch8b112d22011-06-08 16:22:53 +0100664 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 Handle<Script>(info->script()), Handle<Code>(info->code()),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000666 info));
Andrei Popescu31002712010-02-23 13:46:05 +0000667}
Andrei Popescu31002712010-02-23 13:46:05 +0000668
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669
670static bool CompileUnoptimizedCode(CompilationInfo* info) {
671 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400672 if (!Compiler::Analyze(info) || !FullCodeGenerator::MakeCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673 Isolate* isolate = info->isolate();
674 if (!isolate->has_pending_exception()) isolate->StackOverflow();
675 return false;
676 }
677 return true;
678}
679
680
681MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
682 CompilationInfo* info) {
683 VMState<COMPILER> state(info->isolate());
684 PostponeInterruptsScope postpone(info->isolate());
685
686 // Parse and update CompilationInfo with the results.
687 if (!Parser::Parse(info)) return MaybeHandle<Code>();
688 Handle<SharedFunctionInfo> shared = info->shared_info();
689 FunctionLiteral* lit = info->function();
690 shared->set_strict_mode(lit->strict_mode());
691 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400692 MaybeDisableOptimization(shared, lit->dont_optimize_reason());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000693
694 // Compile unoptimized code.
695 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>();
696
697 CHECK_EQ(Code::FUNCTION, info->code()->kind());
698 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
699
700 // Update the shared function info with the scope info. Allocating the
701 // ScopeInfo object may cause a GC.
702 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(), info->zone());
703 shared->set_scope_info(*scope_info);
704
705 // Update the code and feedback vector for the shared function info.
706 shared->ReplaceCode(*info->code());
707 if (shared->optimization_disabled()) info->code()->set_optimizable(false);
708 shared->set_feedback_vector(*info->feedback_vector());
709
710 return info->code();
711}
712
713
714MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
715 Handle<JSFunction> function, BailoutId osr_ast_id) {
716 if (FLAG_cache_optimized_code) {
717 Handle<SharedFunctionInfo> shared(function->shared());
718 // Bound functions are not cached.
719 if (shared->bound()) return MaybeHandle<Code>();
720 DisallowHeapAllocation no_gc;
721 int index = shared->SearchOptimizedCodeMap(
722 function->context()->native_context(), osr_ast_id);
723 if (index > 0) {
724 if (FLAG_trace_opt) {
725 PrintF("[found optimized code for ");
726 function->ShortPrint();
727 if (!osr_ast_id.IsNone()) {
728 PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
729 }
730 PrintF("]\n");
731 }
732 FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index);
733 if (literals != NULL) function->set_literals(literals);
734 return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index));
735 }
736 }
737 return MaybeHandle<Code>();
738}
739
740
741static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
742 Handle<Code> code = info->code();
743 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
744
745 // Context specialization folds-in the context, so no sharing can occur.
746 if (code->is_turbofanned() && info->is_context_specializing()) return;
747
748 // Cache optimized code.
749 if (FLAG_cache_optimized_code) {
750 Handle<JSFunction> function = info->closure();
751 Handle<SharedFunctionInfo> shared(function->shared());
752 // Do not cache bound functions.
753 if (shared->bound()) return;
754 Handle<FixedArray> literals(function->literals());
755 Handle<Context> native_context(function->context()->native_context());
756 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
757 literals, info->osr_ast_id());
758 }
759}
760
761
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400762static bool Renumber(CompilationInfo* info) {
763 if (!AstNumbering::Renumber(info->function(), info->zone())) return false;
764 if (!info->shared_info().is_null()) {
765 FunctionLiteral* lit = info->function();
766 info->shared_info()->set_ast_node_count(lit->ast_node_count());
767 MaybeDisableOptimization(info->shared_info(), lit->dont_optimize_reason());
768 info->shared_info()->set_dont_cache(lit->flags()->Contains(kDontCache));
769 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 return true;
771}
772
773
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400774static void ThrowSuperConstructorCheckError(CompilationInfo* info,
775 Statement* stmt) {
776 MaybeHandle<Object> obj = info->isolate()->factory()->NewTypeError(
777 "super_constructor_call", HandleVector<Object>(nullptr, 0));
778 Handle<Object> exception;
779 if (!obj.ToHandle(&exception)) return;
780
781 MessageLocation location(info->script(), stmt->position(), stmt->position());
782 USE(info->isolate()->Throw(*exception, &location));
783}
784
785
786static bool CheckSuperConstructorCall(CompilationInfo* info) {
787 FunctionLiteral* function = info->function();
788 if (!function->uses_super_constructor_call()) return true;
789
790 if (function->is_default_constructor()) return true;
791
792 ZoneList<Statement*>* body = function->body();
793 CHECK(body->length() > 0);
794
795 int super_call_index = 0;
796 // Allow 'use strict' and similiar and empty statements.
797 while (true) {
798 CHECK(super_call_index < body->length()); // We know there is a super call.
799 Statement* stmt = body->at(super_call_index);
800 if (stmt->IsExpressionStatement() &&
801 stmt->AsExpressionStatement()->expression()->IsLiteral()) {
802 super_call_index++;
803 continue;
804 }
805 if (stmt->IsEmptyStatement()) {
806 super_call_index++;
807 continue;
808 }
809 break;
810 }
811
812 Statement* stmt = body->at(super_call_index);
813 ExpressionStatement* exprStm = stmt->AsExpressionStatement();
814 if (exprStm == nullptr) {
815 ThrowSuperConstructorCheckError(info, stmt);
816 return false;
817 }
818 Call* callExpr = exprStm->expression()->AsCall();
819 if (callExpr == nullptr) {
820 ThrowSuperConstructorCheckError(info, stmt);
821 return false;
822 }
823
824 if (!callExpr->expression()->IsSuperReference()) {
825 ThrowSuperConstructorCheckError(info, stmt);
826 return false;
827 }
828
829 ZoneList<Expression*>* arguments = callExpr->arguments();
830
831 AstThisAccessVisitor this_access_visitor(info->zone());
832 this_access_visitor.VisitExpressions(arguments);
833
834 if (this_access_visitor.HasStackOverflow()) return false;
835 if (this_access_visitor.UsesThis()) {
836 ThrowSuperConstructorCheckError(info, stmt);
837 return false;
838 }
839
840 return true;
841}
842
843
844bool Compiler::Analyze(CompilationInfo* info) {
845 DCHECK(info->function() != NULL);
846 if (!Rewriter::Rewrite(info)) return false;
847 if (!Scope::Analyze(info)) return false;
848 if (!Renumber(info)) return false;
849 DCHECK(info->scope() != NULL);
850 if (!CheckSuperConstructorCall(info)) return false;
851 return true;
852}
853
854
855bool Compiler::ParseAndAnalyze(CompilationInfo* info) {
856 if (!Parser::Parse(info)) return false;
857 return Compiler::Analyze(info);
858}
859
860
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861static bool GetOptimizedCodeNow(CompilationInfo* info) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862 if (!Compiler::ParseAndAnalyze(info)) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863
864 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
865
866 OptimizedCompileJob job(info);
867 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED ||
868 job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED ||
869 job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) {
870 if (FLAG_trace_opt) {
871 PrintF("[aborted optimizing ");
872 info->closure()->ShortPrint();
873 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
874 }
875 return false;
876 }
877
878 // Success!
879 DCHECK(!info->isolate()->has_pending_exception());
880 InsertCodeIntoOptimizedCodeMap(info);
881 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info,
882 info->shared_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883 return true;
884}
885
886
887static bool GetOptimizedCodeLater(CompilationInfo* info) {
888 Isolate* isolate = info->isolate();
889 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
890 if (FLAG_trace_concurrent_recompilation) {
891 PrintF(" ** Compilation queue full, will retry optimizing ");
892 info->closure()->ShortPrint();
893 PrintF(" later.\n");
894 }
895 return false;
896 }
897
898 CompilationHandleScope handle_scope(info);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400899 if (!Compiler::ParseAndAnalyze(info)) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000900 info->SaveHandles(); // Copy handles to the compilation handle scope.
901
902 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
903
904 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info);
905 OptimizedCompileJob::Status status = job->CreateGraph();
906 if (status != OptimizedCompileJob::SUCCEEDED) return false;
907 isolate->optimizing_compiler_thread()->QueueForOptimization(job);
908
909 if (FLAG_trace_concurrent_recompilation) {
910 PrintF(" ** Queued ");
911 info->closure()->ShortPrint();
912 if (info->is_osr()) {
913 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt());
914 } else {
915 PrintF(" for concurrent optimization.\n");
916 }
917 }
918 return true;
919}
920
921
922MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) {
923 DCHECK(!function->GetIsolate()->has_pending_exception());
924 DCHECK(!function->is_compiled());
925 if (function->shared()->is_compiled()) {
926 return Handle<Code>(function->shared()->code());
927 }
928
929 CompilationInfoWithZone info(function);
930 Handle<Code> result;
931 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result,
932 GetUnoptimizedCodeCommon(&info),
933 Code);
934 return result;
935}
936
937
938MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400939 Isolate* isolate = function->GetIsolate();
940 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941 DCHECK(!function->is_compiled());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400942 // If the debugger is active, do not compile with turbofan unless we can
943 // deopt from turbofan code.
944 if (FLAG_turbo_asm && function->shared()->asm_function() &&
945 (FLAG_turbo_deoptimization || !isolate->debug()->is_active())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 CompilationInfoWithZone info(function);
947
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400948 VMState<COMPILER> state(isolate);
949 PostponeInterruptsScope postpone(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400951 info.SetOptimizing(BailoutId::None(), handle(function->shared()->code()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000952 info.MarkAsContextSpecializing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400954 if (GetOptimizedCodeNow(&info)) {
955 DCHECK(function->shared()->is_compiled());
956 return info.code();
957 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958 }
959
960 if (function->shared()->is_compiled()) {
961 return Handle<Code>(function->shared()->code());
962 }
963
964 CompilationInfoWithZone info(function);
965 Handle<Code> result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400966 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCodeCommon(&info),
967 Code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400969 if (FLAG_always_opt && isolate->use_crankshaft() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 !info.shared_info()->optimization_disabled() &&
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400971 !isolate->DebuggerHasBreakPoints()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 Handle<Code> opt_code;
973 if (Compiler::GetOptimizedCode(
974 function, result,
975 Compiler::NOT_CONCURRENT).ToHandle(&opt_code)) {
976 result = opt_code;
977 }
978 }
979
980 return result;
981}
982
983
984MaybeHandle<Code> Compiler::GetUnoptimizedCode(
985 Handle<SharedFunctionInfo> shared) {
986 DCHECK(!shared->GetIsolate()->has_pending_exception());
987 DCHECK(!shared->is_compiled());
988
989 CompilationInfoWithZone info(shared);
990 return GetUnoptimizedCodeCommon(&info);
991}
992
993
994bool Compiler::EnsureCompiled(Handle<JSFunction> function,
995 ClearExceptionFlag flag) {
996 if (function->is_compiled()) return true;
997 MaybeHandle<Code> maybe_code = Compiler::GetLazyCode(function);
998 Handle<Code> code;
999 if (!maybe_code.ToHandle(&code)) {
1000 if (flag == CLEAR_EXCEPTION) {
1001 function->GetIsolate()->clear_pending_exception();
1002 }
1003 return false;
1004 }
1005 function->ReplaceCode(*code);
1006 DCHECK(function->is_compiled());
1007 return true;
1008}
1009
1010
1011// TODO(turbofan): In the future, unoptimized code with deopt support could
1012// be generated lazily once deopt is triggered.
1013bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001014 DCHECK(info->function() != NULL);
1015 DCHECK(info->scope() != NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016 if (!info->shared_info()->has_deoptimization_support()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001017 Handle<SharedFunctionInfo> shared = info->shared_info();
1018 CompilationInfoWithZone unoptimized(shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 // Note that we use the same AST that we will use for generating the
1020 // optimized code.
1021 unoptimized.SetFunction(info->function());
1022 unoptimized.PrepareForCompilation(info->scope());
1023 unoptimized.SetContext(info->context());
1024 unoptimized.EnableDeoptimizationSupport();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001025 // If the current code has reloc info for serialization, also include
1026 // reloc info for serialization for the new code, so that deopt support
1027 // can be added without losing IC state.
1028 if (shared->code()->kind() == Code::FUNCTION &&
1029 shared->code()->has_reloc_info_for_serialization()) {
1030 unoptimized.PrepareForSerializing();
1031 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001032 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1033
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 shared->EnableDeoptimizationSupport(*unoptimized.code());
1035 shared->set_feedback_vector(*unoptimized.feedback_vector());
1036
1037 // The scope info might not have been set if a lazily compiled
1038 // function is inlined before being called for the first time.
1039 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1040 Handle<ScopeInfo> target_scope_info =
1041 ScopeInfo::Create(info->scope(), info->zone());
1042 shared->set_scope_info(*target_scope_info);
1043 }
1044
1045 // The existing unoptimized code was replaced with the new one.
1046 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
1047 }
1048 return true;
1049}
1050
1051
1052// Compile full code for debugging. This code will have debug break slots
1053// and deoptimization information. Deoptimization information is required
1054// in case that an optimized version of this function is still activated on
1055// the stack. It will also make sure that the full code is compiled with
1056// the same flags as the previous version, that is flags which can change
1057// the code generated. The current method of mapping from already compiled
1058// full code without debug break slots to full code with debug break slots
1059// depends on the generated code is otherwise exactly the same.
1060// If compilation fails, just keep the existing code.
1061MaybeHandle<Code> Compiler::GetDebugCode(Handle<JSFunction> function) {
1062 CompilationInfoWithZone info(function);
1063 Isolate* isolate = info.isolate();
1064 VMState<COMPILER> state(isolate);
1065
1066 info.MarkAsDebug();
1067
1068 DCHECK(!isolate->has_pending_exception());
1069 Handle<Code> old_code(function->shared()->code());
1070 DCHECK(old_code->kind() == Code::FUNCTION);
1071 DCHECK(!old_code->has_debug_break_slots());
1072
1073 info.MarkCompilingForDebugging();
1074 if (old_code->is_compiled_optimizable()) {
1075 info.EnableDeoptimizationSupport();
1076 } else {
1077 info.MarkNonOptimizable();
1078 }
1079 MaybeHandle<Code> maybe_new_code = GetUnoptimizedCodeCommon(&info);
1080 Handle<Code> new_code;
1081 if (!maybe_new_code.ToHandle(&new_code)) {
1082 isolate->clear_pending_exception();
1083 } else {
1084 DCHECK_EQ(old_code->is_compiled_optimizable(),
1085 new_code->is_compiled_optimizable());
1086 }
1087 return maybe_new_code;
1088}
1089
1090
1091void Compiler::CompileForLiveEdit(Handle<Script> script) {
1092 // TODO(635): support extensions.
1093 CompilationInfoWithZone info(script);
1094 PostponeInterruptsScope postpone(info.isolate());
1095 VMState<COMPILER> state(info.isolate());
1096
1097 info.MarkAsGlobal();
1098 if (!Parser::Parse(&info)) return;
1099
1100 LiveEditFunctionTracker tracker(info.isolate(), info.function());
1101 if (!CompileUnoptimizedCode(&info)) return;
1102 if (!info.shared_info().is_null()) {
1103 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info.scope(),
1104 info.zone());
1105 info.shared_info()->set_scope_info(*scope_info);
1106 }
1107 tracker.RecordRootFunctionInfo(info.code());
1108}
1109
1110
1111static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
1112 Isolate* isolate = info->isolate();
1113 PostponeInterruptsScope postpone(isolate);
1114 DCHECK(!isolate->native_context().is_null());
1115 Handle<Script> script = info->script();
1116
1117 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
1118 FixedArray* array = isolate->native_context()->embedder_data();
1119 script->set_context_data(array->get(0));
1120
1121 isolate->debug()->OnBeforeCompile(script);
1122
1123 DCHECK(info->is_eval() || info->is_global());
1124
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001125 info->MarkAsToplevel();
1126
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001127 Handle<SharedFunctionInfo> result;
1128
1129 { VMState<COMPILER> state(info->isolate());
1130 if (info->function() == NULL) {
1131 // Parse the script if needed (if it's already parsed, function() is
1132 // non-NULL).
1133 bool parse_allow_lazy =
1134 (info->compile_options() == ScriptCompiler::kConsumeParserCache ||
1135 String::cast(script->source())->length() >
1136 FLAG_min_preparse_length) &&
1137 !Compiler::DebuggerWantsEagerCompilation(info);
1138
1139 if (!parse_allow_lazy &&
1140 (info->compile_options() == ScriptCompiler::kProduceParserCache ||
1141 info->compile_options() == ScriptCompiler::kConsumeParserCache)) {
1142 // We are going to parse eagerly, but we either 1) have cached data
1143 // produced by lazy parsing or 2) are asked to generate cached data.
1144 // Eager parsing cannot benefit from cached data, and producing cached
1145 // data while parsing eagerly is not implemented.
1146 info->SetCachedData(NULL, ScriptCompiler::kNoCompileOptions);
1147 }
1148 if (!Parser::Parse(info, parse_allow_lazy)) {
1149 return Handle<SharedFunctionInfo>::null();
1150 }
1151 }
1152
1153 FunctionLiteral* lit = info->function();
1154 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
1155
1156 // Measure how long it takes to do the compilation; only take the
1157 // rest of the function into account to avoid overlap with the
1158 // parsing statistics.
1159 HistogramTimer* rate = info->is_eval()
1160 ? info->isolate()->counters()->compile_eval()
1161 : info->isolate()->counters()->compile();
1162 HistogramTimerScope timer(rate);
1163
1164 // Compile the code.
1165 if (!CompileUnoptimizedCode(info)) {
1166 return Handle<SharedFunctionInfo>::null();
1167 }
1168
1169 // Allocate function.
1170 DCHECK(!info->code().is_null());
1171 result = isolate->factory()->NewSharedFunctionInfo(
1172 lit->name(), lit->materialized_literal_count(), lit->kind(),
1173 info->code(), ScopeInfo::Create(info->scope(), info->zone()),
1174 info->feedback_vector());
1175
1176 DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
1177 SetFunctionInfo(result, lit, true, script);
1178
1179 Handle<String> script_name = script->name()->IsString()
1180 ? Handle<String>(String::cast(script->name()))
1181 : isolate->factory()->empty_string();
1182 Logger::LogEventsAndTags log_tag = info->is_eval()
1183 ? Logger::EVAL_TAG
1184 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
1185
1186 PROFILE(isolate, CodeCreateEvent(
1187 log_tag, *info->code(), *result, info, *script_name));
1188 GDBJIT(AddCode(script_name, script, info->code(), info));
1189
1190 // Hint to the runtime system used when allocating space for initial
1191 // property space by setting the expected number of properties for
1192 // the instances of the function.
1193 SetExpectedNofPropertiesFromEstimate(result,
1194 lit->expected_property_count());
1195
1196 if (!script.is_null())
1197 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1198
1199 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
1200 }
1201
1202 isolate->debug()->OnAfterCompile(script);
1203
1204 return result;
1205}
1206
1207
1208MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1209 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1210 Handle<Context> context, StrictMode strict_mode,
1211 ParseRestriction restriction, int scope_position) {
1212 Isolate* isolate = source->GetIsolate();
1213 int source_length = source->length();
1214 isolate->counters()->total_eval_size()->Increment(source_length);
1215 isolate->counters()->total_compile_size()->Increment(source_length);
1216
1217 CompilationCache* compilation_cache = isolate->compilation_cache();
1218 MaybeHandle<SharedFunctionInfo> maybe_shared_info =
1219 compilation_cache->LookupEval(source, outer_info, context, strict_mode,
1220 scope_position);
1221 Handle<SharedFunctionInfo> shared_info;
1222
1223 if (!maybe_shared_info.ToHandle(&shared_info)) {
1224 Handle<Script> script = isolate->factory()->NewScript(source);
1225 CompilationInfoWithZone info(script);
1226 info.MarkAsEval();
1227 if (context->IsNativeContext()) info.MarkAsGlobal();
1228 info.SetStrictMode(strict_mode);
1229 info.SetParseRestriction(restriction);
1230 info.SetContext(context);
1231
1232 Debug::RecordEvalCaller(script);
1233
1234 shared_info = CompileToplevel(&info);
1235
1236 if (shared_info.is_null()) {
1237 return MaybeHandle<JSFunction>();
1238 } else {
1239 // Explicitly disable optimization for eval code. We're not yet prepared
1240 // to handle eval-code in the optimizing compiler.
1241 shared_info->DisableOptimization(kEval);
1242
1243 // If caller is strict mode, the result must be in strict mode as well.
1244 DCHECK(strict_mode == SLOPPY || shared_info->strict_mode() == STRICT);
1245 if (!shared_info->dont_cache()) {
1246 compilation_cache->PutEval(source, outer_info, context, shared_info,
1247 scope_position);
1248 }
1249 }
1250 } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) {
1251 shared_info->ResetForNewContext(isolate->heap()->global_ic_age());
1252 }
1253
1254 return isolate->factory()->NewFunctionFromSharedFunctionInfo(
1255 shared_info, context, NOT_TENURED);
1256}
1257
1258
1259Handle<SharedFunctionInfo> Compiler::CompileScript(
1260 Handle<String> source, Handle<Object> script_name, int line_offset,
1261 int column_offset, bool is_shared_cross_origin, Handle<Context> context,
1262 v8::Extension* extension, ScriptData** cached_data,
1263 ScriptCompiler::CompileOptions compile_options, NativesFlag natives) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001264 Isolate* isolate = source->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265 if (compile_options == ScriptCompiler::kNoCompileOptions) {
1266 cached_data = NULL;
1267 } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1268 compile_options == ScriptCompiler::kProduceCodeCache) {
1269 DCHECK(cached_data && !*cached_data);
1270 DCHECK(extension == NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001271 DCHECK(!isolate->debug()->is_loaded());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 } else {
1273 DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1274 compile_options == ScriptCompiler::kConsumeCodeCache);
1275 DCHECK(cached_data && *cached_data);
1276 DCHECK(extension == NULL);
1277 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001278 int source_length = source->length();
1279 isolate->counters()->total_load_size()->Increment(source_length);
1280 isolate->counters()->total_compile_size()->Increment(source_length);
1281
1282 CompilationCache* compilation_cache = isolate->compilation_cache();
1283
1284 // Do a lookup in the compilation cache but not for extensions.
1285 MaybeHandle<SharedFunctionInfo> maybe_result;
1286 Handle<SharedFunctionInfo> result;
1287 if (extension == NULL) {
1288 if (FLAG_serialize_toplevel &&
1289 compile_options == ScriptCompiler::kConsumeCodeCache &&
1290 !isolate->debug()->is_loaded()) {
1291 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001292 Handle<SharedFunctionInfo> result;
1293 if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1294 .ToHandle(&result)) {
1295 return result;
1296 }
1297 // Deserializer failed. Fall through to compile.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298 } else {
1299 maybe_result = compilation_cache->LookupScript(
1300 source, script_name, line_offset, column_offset,
1301 is_shared_cross_origin, context);
1302 }
1303 }
1304
1305 base::ElapsedTimer timer;
1306 if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
1307 compile_options == ScriptCompiler::kProduceCodeCache) {
1308 timer.Start();
1309 }
1310
1311 if (!maybe_result.ToHandle(&result)) {
1312 // No cache entry found. Compile the script.
1313
1314 // Create a script object describing the script to be compiled.
1315 Handle<Script> script = isolate->factory()->NewScript(source);
1316 if (natives == NATIVES_CODE) {
1317 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
1318 }
1319 if (!script_name.is_null()) {
1320 script->set_name(*script_name);
1321 script->set_line_offset(Smi::FromInt(line_offset));
1322 script->set_column_offset(Smi::FromInt(column_offset));
1323 }
1324 script->set_is_shared_cross_origin(is_shared_cross_origin);
1325
1326 // Compile the function and add it to the cache.
1327 CompilationInfoWithZone info(script);
1328 info.MarkAsGlobal();
1329 info.SetCachedData(cached_data, compile_options);
1330 info.SetExtension(extension);
1331 info.SetContext(context);
1332 if (FLAG_serialize_toplevel &&
1333 compile_options == ScriptCompiler::kProduceCodeCache) {
1334 info.PrepareForSerializing();
1335 }
1336 if (FLAG_use_strict) info.SetStrictMode(STRICT);
1337
1338 result = CompileToplevel(&info);
1339 if (extension == NULL && !result.is_null() && !result->dont_cache()) {
1340 compilation_cache->PutScript(source, context, result);
1341 if (FLAG_serialize_toplevel &&
1342 compile_options == ScriptCompiler::kProduceCodeCache) {
1343 HistogramTimerScope histogram_timer(
1344 isolate->counters()->compile_serialize());
1345 *cached_data = CodeSerializer::Serialize(isolate, result, source);
1346 if (FLAG_profile_deserialization) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001347 PrintF("[Compiling and serializing took %0.3f ms]\n",
1348 timer.Elapsed().InMillisecondsF());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349 }
1350 }
1351 }
1352
1353 if (result.is_null()) isolate->ReportPendingMessages();
1354 } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1355 result->ResetForNewContext(isolate->heap()->global_ic_age());
1356 }
1357 return result;
1358}
1359
1360
1361Handle<SharedFunctionInfo> Compiler::CompileStreamedScript(
1362 CompilationInfo* info, int source_length) {
1363 Isolate* isolate = info->isolate();
1364 isolate->counters()->total_load_size()->Increment(source_length);
1365 isolate->counters()->total_compile_size()->Increment(source_length);
1366
1367 if (FLAG_use_strict) info->SetStrictMode(STRICT);
1368 // TODO(marja): FLAG_serialize_toplevel is not honoured and won't be; when the
1369 // real code caching lands, streaming needs to be adapted to use it.
1370 return CompileToplevel(info);
1371}
1372
1373
1374Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
1375 FunctionLiteral* literal, Handle<Script> script,
1376 CompilationInfo* outer_info) {
1377 // Precondition: code has been parsed and scopes have been analyzed.
1378 CompilationInfoWithZone info(script);
1379 info.SetFunction(literal);
1380 info.PrepareForCompilation(literal->scope());
1381 info.SetStrictMode(literal->scope()->strict_mode());
1382 if (outer_info->will_serialize()) info.PrepareForSerializing();
1383
1384 Isolate* isolate = info.isolate();
1385 Factory* factory = isolate->factory();
1386 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
1387 // Determine if the function can be lazily compiled. This is necessary to
1388 // allow some of our builtin JS files to be lazily compiled. These
1389 // builtins cannot be handled lazily by the parser, since we have to know
1390 // if a function uses the special natives syntax, which is something the
1391 // parser records.
1392 // If the debugger requests compilation for break points, we cannot be
1393 // aggressive about lazy compilation, because it might trigger compilation
1394 // of functions without an outer context when setting a breakpoint through
1395 // Debug::FindSharedFunctionInfoInScript.
1396 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
1397 bool allow_lazy = literal->AllowsLazyCompilation() &&
1398 !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
1399
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001400 if (outer_info->is_toplevel() && outer_info->will_serialize()) {
1401 // Make sure that if the toplevel code (possibly to be serialized),
1402 // the inner function must be allowed to be compiled lazily.
1403 // This is necessary to serialize toplevel code without inner functions.
1404 DCHECK(allow_lazy);
1405 }
1406
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407 // Generate code
1408 Handle<ScopeInfo> scope_info;
1409 if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
1410 Handle<Code> code = isolate->builtins()->CompileLazy();
1411 info.SetCode(code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001412 // There's no need in theory for a lazy-compiled function to have a type
1413 // feedback vector, but some parts of the system expect all
1414 // SharedFunctionInfo instances to have one. The size of the vector depends
1415 // on how many feedback-needing nodes are in the tree, and when lazily
1416 // parsing we might not know that, if this function was never parsed before.
1417 // In that case the vector will be replaced the next time MakeCode is
1418 // called.
1419 info.EnsureFeedbackVector();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001421 } else if (Renumber(&info) && FullCodeGenerator::MakeCode(&info)) {
1422 // MakeCode will ensure that the feedback vector is present and
1423 // appropriately sized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001424 DCHECK(!info.code().is_null());
1425 scope_info = ScopeInfo::Create(info.scope(), info.zone());
1426 } else {
1427 return Handle<SharedFunctionInfo>::null();
1428 }
1429
1430 // Create a shared function info object.
1431 Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo(
1432 literal->name(), literal->materialized_literal_count(), literal->kind(),
1433 info.code(), scope_info, info.feedback_vector());
1434 SetFunctionInfo(result, literal, false, script);
1435 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1436 result->set_allows_lazy_compilation(allow_lazy);
1437 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1438
1439 // Set the expected number of properties for instances and return
1440 // the resulting function.
1441 SetExpectedNofPropertiesFromEstimate(result,
1442 literal->expected_property_count());
1443 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
1444 return result;
1445}
1446
1447
1448MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
1449 Handle<Code> current_code,
1450 ConcurrencyMode mode,
1451 BailoutId osr_ast_id) {
1452 Handle<Code> cached_code;
1453 if (GetCodeFromOptimizedCodeMap(
1454 function, osr_ast_id).ToHandle(&cached_code)) {
1455 return cached_code;
1456 }
1457
1458 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function));
1459 Isolate* isolate = info->isolate();
1460 DCHECK(AllowCompilation::IsAllowed(isolate));
1461 VMState<COMPILER> state(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001462 DCHECK(isolate->use_crankshaft());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 DCHECK(!isolate->has_pending_exception());
1464 PostponeInterruptsScope postpone(isolate);
1465
1466 Handle<SharedFunctionInfo> shared = info->shared_info();
1467 if (shared->code()->kind() != Code::FUNCTION ||
1468 ScopeInfo::Empty(isolate) == shared->scope_info()) {
1469 // The function was never compiled. Compile it unoptimized first.
1470 // TODO(titzer): reuse the AST and scope info from this compile.
1471 CompilationInfoWithZone nested(function);
1472 nested.EnableDeoptimizationSupport();
1473 if (!GetUnoptimizedCodeCommon(&nested).ToHandle(&current_code)) {
1474 return MaybeHandle<Code>();
1475 }
1476 shared->ReplaceCode(*current_code);
1477 }
1478 current_code->set_profiler_ticks(0);
1479
1480 info->SetOptimizing(osr_ast_id, current_code);
1481
1482 if (mode == CONCURRENT) {
1483 if (GetOptimizedCodeLater(info.get())) {
1484 info.Detach(); // The background recompile job owns this now.
1485 return isolate->builtins()->InOptimizationQueue();
1486 }
1487 } else {
1488 if (GetOptimizedCodeNow(info.get())) return info->code();
1489 }
1490
1491 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1492 return MaybeHandle<Code>();
1493}
1494
1495
1496Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) {
1497 // Take ownership of compilation info. Deleting compilation info
1498 // also tears down the zone and the recompile job.
1499 SmartPointer<CompilationInfo> info(job->info());
1500 Isolate* isolate = info->isolate();
1501
1502 VMState<COMPILER> state(isolate);
1503 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
1504
1505 Handle<SharedFunctionInfo> shared = info->shared_info();
1506 shared->code()->set_profiler_ticks(0);
1507
1508 // 1) Optimization on the concurrent thread may have failed.
1509 // 2) The function may have already been optimized by OSR. Simply continue.
1510 // Except when OSR already disabled optimization for some reason.
1511 // 3) The code may have already been invalidated due to dependency change.
1512 // 4) Debugger may have been activated.
1513 // 5) Code generation may have failed.
1514 if (job->last_status() == OptimizedCompileJob::SUCCEEDED) {
1515 if (shared->optimization_disabled()) {
1516 job->RetryOptimization(kOptimizationDisabled);
1517 } else if (info->HasAbortedDueToDependencyChange()) {
1518 job->RetryOptimization(kBailedOutDueToDependencyChange);
1519 } else if (isolate->DebuggerHasBreakPoints()) {
1520 job->RetryOptimization(kDebuggerHasBreakPoints);
1521 } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
1522 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared);
1523 if (info->shared_info()->SearchOptimizedCodeMap(
1524 info->context()->native_context(), info->osr_ast_id()) == -1) {
1525 InsertCodeIntoOptimizedCodeMap(info.get());
1526 }
1527 if (FLAG_trace_opt) {
1528 PrintF("[completed optimizing ");
1529 info->closure()->ShortPrint();
1530 PrintF("]\n");
1531 }
1532 return Handle<Code>(*info->code());
1533 }
1534 }
1535
1536 DCHECK(job->last_status() != OptimizedCompileJob::SUCCEEDED);
1537 if (FLAG_trace_opt) {
1538 PrintF("[aborted optimizing ");
1539 info->closure()->ShortPrint();
1540 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
1541 }
1542 return Handle<Code>::null();
1543}
1544
1545
1546bool Compiler::DebuggerWantsEagerCompilation(CompilationInfo* info,
1547 bool allow_lazy_without_ctx) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001548 if (LiveEditFunctionTracker::IsActive(info->isolate())) return true;
1549 Debug* debug = info->isolate()->debug();
1550 bool debugging = debug->is_active() || debug->has_break_points();
1551 return debugging && !allow_lazy_without_ctx;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552}
1553
1554
1555CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info)
1556 : name_(name), info_(info), zone_(info->isolate()) {
1557 if (FLAG_hydrogen_stats) {
1558 info_zone_start_allocation_size_ = info->zone()->allocation_size();
1559 timer_.Start();
1560 }
1561}
1562
1563
1564CompilationPhase::~CompilationPhase() {
1565 if (FLAG_hydrogen_stats) {
1566 unsigned size = zone()->allocation_size();
1567 size += info_->zone()->allocation_size() - info_zone_start_allocation_size_;
1568 isolate()->GetHStatistics()->SaveTiming(name_, timer_.Elapsed(), size);
1569 }
1570}
1571
1572
1573bool CompilationPhase::ShouldProduceTraceOutput() const {
1574 // Trace if the appropriate trace flag is set and the phase name's first
1575 // character is in the FLAG_trace_phase command line parameter.
1576 AllowHandleDereference allow_deref;
1577 bool tracing_on = info()->IsStub()
1578 ? FLAG_trace_hydrogen_stubs
1579 : (FLAG_trace_hydrogen &&
1580 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
1581 return (tracing_on &&
1582 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1583}
1584
Steve Blocka7e24c12009-10-30 11:49:00 +00001585} } // namespace v8::internal