blob: c47e1b7bee8a88c226b19dafdcdd8e9b9016cce6 [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 Murdochf87a2032010-10-22 12:50:53 +010040
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041#define PARSE_INFO_GETTER(type, name) \
42 type CompilationInfo::name() const { \
43 CHECK(parse_info()); \
44 return parse_info()->name(); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046
47
48#define PARSE_INFO_GETTER_WITH_DEFAULT(type, name, def) \
49 type CompilationInfo::name() const { \
50 return parse_info() ? parse_info()->name() : def; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052
53
54PARSE_INFO_GETTER(Handle<Script>, script)
55PARSE_INFO_GETTER(bool, is_eval)
56PARSE_INFO_GETTER(bool, is_native)
57PARSE_INFO_GETTER(bool, is_module)
58PARSE_INFO_GETTER(FunctionLiteral*, literal)
59PARSE_INFO_GETTER_WITH_DEFAULT(LanguageMode, language_mode, STRICT)
60PARSE_INFO_GETTER_WITH_DEFAULT(Handle<JSFunction>, closure,
61 Handle<JSFunction>::null())
62PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr)
63PARSE_INFO_GETTER(Handle<Context>, context)
64PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
65
66#undef PARSE_INFO_GETTER
67#undef PARSE_INFO_GETTER_WITH_DEFAULT
68
69
70// Exactly like a CompilationInfo, except being allocated via {new} and it also
71// creates and enters a Zone on construction and deallocates it on destruction.
72class CompilationInfoWithZone : public CompilationInfo {
73 public:
74 explicit CompilationInfoWithZone(Handle<JSFunction> function)
75 : CompilationInfo(new ParseInfo(&zone_, function)) {}
76
77 // Virtual destructor because a CompilationInfoWithZone has to exit the
78 // zone scope and get rid of dependent maps even when the destructor is
79 // called when cast as a CompilationInfo.
80 virtual ~CompilationInfoWithZone() {
81 DisableFutureOptimization();
82 dependencies()->Rollback();
83 delete parse_info_;
84 parse_info_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000085 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086
87 private:
88 Zone zone_;
89};
90
91
92bool CompilationInfo::has_shared_info() const {
93 return parse_info_ && !parse_info_->shared_info().is_null();
94}
95
96
97bool CompilationInfo::has_context() const {
98 return parse_info_ && !parse_info_->context().is_null();
99}
100
101
102bool CompilationInfo::has_literal() const {
103 return parse_info_ && parse_info_->literal() != nullptr;
104}
105
106
107bool CompilationInfo::has_scope() const {
108 return parse_info_ && parse_info_->scope() != nullptr;
109}
110
111
112CompilationInfo::CompilationInfo(ParseInfo* parse_info)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100113 : CompilationInfo(parse_info, nullptr, Code::ComputeFlags(Code::FUNCTION),
114 BASE, parse_info->isolate(), parse_info->zone()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115 // Compiling for the snapshot typically results in different code than
116 // compiling later on. This means that code recompiled with deoptimization
117 // support won't be "equivalent" (as defined by SharedFunctionInfo::
118 // EnableDeoptimizationSupport), so it will replace the old code and all
119 // its type feedback. To avoid this, always compile functions in the snapshot
120 // with deoptimization support.
121 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124 if (FLAG_turbo_inlining) MarkAsInliningEnabled();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled();
126 if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 if (FLAG_turbo_types) MarkAsTypingEnabled();
128
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 if (has_shared_info()) {
130 if (shared_info()->is_compiled()) {
131 // We should initialize the CompilationInfo feedback vector from the
132 // passed in shared info, rather than creating a new one.
133 feedback_vector_ = Handle<TypeFeedbackVector>(
134 shared_info()->feedback_vector(), parse_info->isolate());
135 }
136 if (shared_info()->never_compiled()) MarkAsFirstCompile();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141CompilationInfo::CompilationInfo(const char* debug_name, Isolate* isolate,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100142 Zone* zone, Code::Flags code_flags)
143 : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144
Ben Murdoch097c5b22016-05-18 11:27:45 +0100145CompilationInfo::CompilationInfo(ParseInfo* parse_info, const char* debug_name,
146 Code::Flags code_flags, Mode mode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 Isolate* isolate, Zone* zone)
148 : parse_info_(parse_info),
149 isolate_(isolate),
150 flags_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100151 code_flags_(code_flags),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 mode_(mode),
153 osr_ast_id_(BailoutId::None()),
154 zone_(zone),
155 deferred_handles_(nullptr),
156 dependencies_(isolate, zone),
157 bailout_reason_(kNoReason),
158 prologue_offset_(Code::kPrologueOffsetNotSet),
159 track_positions_(FLAG_hydrogen_track_positions ||
160 isolate->cpu_profiler()->is_profiling()),
161 opt_count_(has_shared_info() ? shared_info()->opt_count() : 0),
162 parameter_count_(0),
163 optimization_id_(-1),
164 osr_expr_stack_height_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100165 debug_name_(debug_name) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166
167
168CompilationInfo::~CompilationInfo() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 DisableFutureOptimization();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 delete deferred_handles_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171#ifdef DEBUG
172 // Check that no dependent maps have been added or added dependent maps have
173 // been rolled back or committed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 DCHECK(dependencies()->IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175#endif // DEBUG
176}
177
178
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179int CompilationInfo::num_parameters() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 return has_scope() ? scope()->num_parameters() : parameter_count_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181}
182
183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184int CompilationInfo::num_parameters_including_this() const {
185 return num_parameters() + (is_this_defined() ? 1 : 0);
186}
187
188
189bool CompilationInfo::is_this_defined() const { return !IsStub(); }
190
191
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192int CompilationInfo::num_heap_slots() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 return has_scope() ? scope()->num_heap_slots() : 0;
Ben Murdoch257744e2011-11-30 15:57:28 +0000194}
Ben Murdochb8e0da22011-05-16 14:20:40 +0100195
Ben Murdoch257744e2011-11-30 15:57:28 +0000196
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100197// Primitive functions are unlikely to be picked up by the stack-walking
198// profiler, so they trigger their own optimization when they're called
199// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
200bool CompilationInfo::ShouldSelfOptimize() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 return FLAG_crankshaft &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
203 !literal()->dont_optimize() &&
204 literal()->scope()->AllowsLazyCompilation() &&
205 (!has_shared_info() || !shared_info()->optimization_disabled());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208
209void CompilationInfo::EnsureFeedbackVector() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 if (feedback_vector_.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 Handle<TypeFeedbackMetadata> feedback_metadata =
212 TypeFeedbackMetadata::New(isolate(), literal()->feedback_vector_spec());
213 feedback_vector_ = TypeFeedbackVector::New(isolate(), feedback_metadata);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215
216 // It's very important that recompiles do not alter the structure of the
217 // type feedback vector.
218 CHECK(!feedback_vector_->metadata()->SpecDiffersFrom(
219 literal()->feedback_vector_spec()));
220}
221
222
223bool CompilationInfo::has_simple_parameters() {
224 return scope()->has_simple_parameters();
225}
226
227
228int CompilationInfo::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
229 SourcePosition position,
230 int parent_id) {
231 DCHECK(track_positions_);
232
233 int inline_id = static_cast<int>(inlined_function_infos_.size());
234 InlinedFunctionInfo info(parent_id, position, UnboundScript::kNoScriptId,
235 shared->start_position());
236 if (!shared->script()->IsUndefined()) {
237 Handle<Script> script(Script::cast(shared->script()));
238 info.script_id = script->id();
239
240 if (FLAG_hydrogen_track_positions && !script->source()->IsUndefined()) {
241 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
242 OFStream os(tracing_scope.file());
243 os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
244 << ") id{" << optimization_id() << "," << inline_id << "} ---\n";
245 {
246 DisallowHeapAllocation no_allocation;
247 int start = shared->start_position();
248 int len = shared->end_position() - start;
249 String::SubStringRange source(String::cast(script->source()), start,
250 len);
251 for (const auto& c : source) {
252 os << AsReversiblyEscapedUC16(c);
253 }
254 }
255
256 os << "\n--- END ---\n";
257 }
258 }
259
260 inlined_function_infos_.push_back(info);
261
262 if (FLAG_hydrogen_track_positions && inline_id != 0) {
263 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
264 OFStream os(tracing_scope.file());
265 os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
266 << optimization_id() << "," << inline_id << "} AS " << inline_id
267 << " AT " << position << std::endl;
268 }
269
270 return inline_id;
271}
272
273
274void CompilationInfo::LogDeoptCallPosition(int pc_offset, int inlining_id) {
275 if (!track_positions_ || IsStub()) return;
276 DCHECK_LT(static_cast<size_t>(inlining_id), inlined_function_infos_.size());
277 inlined_function_infos_.at(inlining_id).deopt_pc_offsets.push_back(pc_offset);
278}
279
280
281base::SmartArrayPointer<char> CompilationInfo::GetDebugName() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100282 if (parse_info() && parse_info()->literal()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 AllowHandleDereference allow_deref;
284 return parse_info()->literal()->debug_name()->ToCString();
285 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100286 if (parse_info() && !parse_info()->shared_info().is_null()) {
287 return parse_info()->shared_info()->DebugName()->ToCString();
288 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 const char* str = debug_name_ ? debug_name_ : "unknown";
290 size_t len = strlen(str) + 1;
291 base::SmartArrayPointer<char> name(new char[len]);
292 memcpy(name.get(), str, len);
293 return name;
294}
295
296
297bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
298 return is_sloppy(language_mode()) && !is_native();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100299}
300
301
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
303 public:
304 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
305 : HOptimizedGraphBuilder(info) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100306 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100307
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308#define DEF_VISIT(type) \
309 void Visit##type(type* node) override { \
310 SourcePosition old_position = SourcePosition::Unknown(); \
311 if (node->position() != RelocInfo::kNoPosition) { \
312 old_position = source_position(); \
313 SetSourcePosition(node->position()); \
314 } \
315 HOptimizedGraphBuilder::Visit##type(node); \
316 if (!old_position.IsUnknown()) { \
317 set_source_position(old_position); \
318 } \
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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323#define DEF_VISIT(type) \
324 void Visit##type(type* node) override { \
325 SourcePosition old_position = SourcePosition::Unknown(); \
326 if (node->position() != RelocInfo::kNoPosition) { \
327 old_position = source_position(); \
328 SetSourcePosition(node->position()); \
329 } \
330 HOptimizedGraphBuilder::Visit##type(node); \
331 if (!old_position.IsUnknown()) { \
332 set_source_position(old_position); \
333 } \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334 }
335 STATEMENT_NODE_LIST(DEF_VISIT)
336#undef DEF_VISIT
337
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400338#define DEF_VISIT(type) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 void Visit##type(type* node) override { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340 HOptimizedGraphBuilder::Visit##type(node); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 DECLARATION_NODE_LIST(DEF_VISIT)
343#undef DEF_VISIT
344};
345
346
347OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 DCHECK(info()->IsOptimizing());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100349
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 // Do not use Crankshaft/TurboFan if we need to be able to set break points.
351 if (info()->shared_info()->HasDebugInfo()) {
352 return AbortOptimization(kFunctionBeingDebugged);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400353 }
Steve Block44f0eee2011-05-26 01:26:41 +0100354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 // Limit the number of times we try to optimize functions.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100356 const int kMaxOptCount =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000357 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
358 if (info()->opt_count() > kMaxOptCount) {
359 return AbortOptimization(kOptimizedTooManyTimes);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100360 }
361
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 // Check the whitelist for Crankshaft.
363 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) {
364 return AbortOptimization(kHydrogenFilter);
365 }
366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 // Optimization requires a version of fullcode with deoptimization support.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100368 // Recompile the unoptimized version of the code if the current version
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 // doesn't have deoptimization support already.
370 // Otherwise, if we are gathering compilation time and space statistics
371 // for hydrogen, gather baseline statistics for a fullcode compilation.
372 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
Steve Block44f0eee2011-05-26 01:26:41 +0100373 if (should_recompile || FLAG_hydrogen_stats) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 base::ElapsedTimer timer;
375 if (FLAG_hydrogen_stats) {
376 timer.Start();
377 }
378 if (!Compiler::EnsureDeoptimizationSupport(info())) {
379 return SetLastStatus(FAILED);
380 }
381 if (FLAG_hydrogen_stats) {
382 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100383 }
384 }
385
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000386 DCHECK(info()->shared_info()->has_deoptimization_support());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387 DCHECK(!info()->is_first_compile());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 bool optimization_disabled = info()->shared_info()->optimization_disabled();
390 bool dont_crankshaft = info()->shared_info()->dont_crankshaft();
391
392 // Check the enabling conditions for Turbofan.
393 // 1. "use asm" code.
394 bool is_turbofanable_asm = FLAG_turbo_asm &&
395 info()->shared_info()->asm_function() &&
396 !optimization_disabled;
397
398 // 2. Fallback for features unsupported by Crankshaft.
399 bool is_unsupported_by_crankshaft_but_turbofanable =
400 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
401 !optimization_disabled;
402
403 // 3. Explicitly enabled by the command-line filter.
404 bool passes_turbo_filter = info()->closure()->PassesFilter(FLAG_turbo_filter);
405
406 // If this is OSR request, OSR must be enabled by Turbofan.
407 bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr();
408
409 if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
410 passes_turbo_filter) &&
411 passes_osr_test) {
412 // Use TurboFan for the compilation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400413 if (FLAG_trace_opt) {
414 OFStream os(stdout);
415 os << "[compiling method " << Brief(*info()->closure())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 << " using TurboFan";
417 if (info()->is_osr()) os << " OSR";
418 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400419 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420
421 if (info()->shared_info()->asm_function()) {
422 if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
423 info()->MarkAsFunctionContextSpecializing();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100424 } else {
425 if (!FLAG_always_opt) {
426 info()->MarkAsBailoutOnUninitialized();
427 }
428 if (FLAG_native_context_specialization) {
429 info()->MarkAsNativeContextSpecializing();
430 info()->MarkAsTypingEnabled();
431 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432 }
433 if (!info()->shared_info()->asm_function() ||
434 FLAG_turbo_asm_deoptimization) {
435 info()->MarkAsDeoptimizationEnabled();
436 }
437
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400438 Timer t(this, &time_taken_to_create_graph_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439 compiler::Pipeline pipeline(info());
440 pipeline.GenerateCode();
441 if (!info()->code().is_null()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442 return SetLastStatus(SUCCEEDED);
443 }
444 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 if (!isolate()->use_crankshaft() || dont_crankshaft) {
447 // Crankshaft is entirely disabled.
448 return SetLastStatus(FAILED);
449 }
450
451 Scope* scope = info()->scope();
452 if (LUnallocated::TooManyParameters(scope->num_parameters())) {
453 // Crankshaft would require too many Lithium operands.
454 return AbortOptimization(kTooManyParameters);
455 }
456
457 if (info()->is_osr() &&
458 LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
459 scope->num_stack_slots())) {
460 // Crankshaft would require too many Lithium operands.
461 return AbortOptimization(kTooManyParametersLocals);
462 }
463
464 if (scope->HasIllegalRedeclaration()) {
465 // Crankshaft cannot handle illegal redeclarations.
466 return AbortOptimization(kFunctionWithIllegalRedeclaration);
467 }
468
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400469 if (FLAG_trace_opt) {
470 OFStream os(stdout);
471 os << "[compiling method " << Brief(*info()->closure())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000472 << " using Crankshaft";
473 if (info()->is_osr()) os << " OSR";
474 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 }
476
Ben Murdochb0fe1622011-05-05 13:52:32 +0100477 if (FLAG_trace_hydrogen) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478 isolate()->GetHTracer()->TraceCompilation(info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100479 }
480
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 // Type-check the function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482 AstTyper(info()->isolate(), info()->zone(), info()->closure(),
483 info()->scope(), info()->osr_ast_id(), info()->literal())
484 .Run();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486 // Optimization could have been disabled by the parser. Note that this check
487 // is only needed because the Hydrogen graph builder is missing some bailouts.
488 if (info()->shared_info()->optimization_disabled()) {
489 return AbortOptimization(
490 info()->shared_info()->disable_optimization_reason());
491 }
492
493 graph_builder_ = (info()->is_tracking_positions() || FLAG_trace_ic)
494 ? new (info()->zone())
495 HOptimizedGraphBuilderWithPositions(info())
496 : new (info()->zone()) HOptimizedGraphBuilder(info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497
498 Timer t(this, &time_taken_to_create_graph_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 graph_ = graph_builder_->CreateGraph();
500
501 if (isolate()->has_pending_exception()) {
502 return SetLastStatus(FAILED);
Steve Block1e0659c2011-05-24 12:43:12 +0100503 }
504
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 if (graph_ == NULL) return SetLastStatus(BAILED_OUT);
506
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000507 if (info()->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 // Dependency has changed during graph creation. Let's try again later.
509 return RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100510 }
511
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 return SetLastStatus(SUCCEEDED);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100513}
514
515
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() {
517 DisallowHeapAllocation no_allocation;
518 DisallowHandleAllocation no_handles;
519 DisallowHandleDereference no_deref;
520 DisallowCodeDependencyChange no_dependency_change;
Ben Murdoch257744e2011-11-30 15:57:28 +0000521
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000522 DCHECK(last_status() == SUCCEEDED);
523 // TODO(turbofan): Currently everything is done in the first phase.
524 if (!info()->code().is_null()) {
525 return last_status();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100526 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527
528 Timer t(this, &time_taken_to_optimize_);
529 DCHECK(graph_ != NULL);
530 BailoutReason bailout_reason = kNoReason;
531
532 if (graph_->Optimize(&bailout_reason)) {
533 chunk_ = LChunk::NewChunk(graph_);
534 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
535 } else if (bailout_reason != kNoReason) {
536 graph_builder_->Bailout(bailout_reason);
537 }
538
539 return SetLastStatus(BAILED_OUT);
Steve Block6ded16b2010-05-10 14:33:55 +0100540}
Steve Block6ded16b2010-05-10 14:33:55 +0100541
542
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000543namespace {
544
545void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
546 Handle<Code> code) {
547 Handle<WeakCell> cell = Code::WeakCellFor(code);
548 Heap* heap = isolate->heap();
549 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
550 dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
551 heap->AddWeakObjectToCodeDependency(object, dep);
552}
553
554
555void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
556 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
557 Isolate* const isolate = code->GetIsolate();
558 DCHECK(code->is_optimized_code());
559 std::vector<Handle<Map>> maps;
560 std::vector<Handle<HeapObject>> objects;
561 {
562 DisallowHeapAllocation no_gc;
563 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
564 RelocInfo::ModeMask(RelocInfo::CELL);
565 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
566 RelocInfo::Mode mode = it.rinfo()->rmode();
567 if (mode == RelocInfo::CELL &&
568 code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
569 objects.push_back(handle(it.rinfo()->target_cell(), isolate));
570 } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
571 code->IsWeakObjectInOptimizedCode(
572 it.rinfo()->target_object())) {
573 Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
574 isolate);
575 if (object->IsMap()) {
576 maps.push_back(Handle<Map>::cast(object));
577 } else {
578 objects.push_back(object);
579 }
580 }
581 }
582 }
583 for (Handle<Map> map : maps) {
584 if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) {
585 isolate->heap()->AddRetainedMap(map);
586 }
587 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code);
588 }
589 for (Handle<HeapObject> object : objects) {
590 AddWeakObjectToCodeDependency(isolate, object, code);
591 }
592 code->set_can_have_weak_objects(true);
593}
594
595} // namespace
596
597
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
599 DCHECK(last_status() == SUCCEEDED);
600 // TODO(turbofan): Currently everything is done in the first phase.
601 if (!info()->code().is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 info()->dependencies()->Commit(info()->code());
603 if (info()->is_deoptimization_enabled()) {
604 info()->parse_info()->context()->native_context()->AddOptimizedCode(
605 *info()->code());
606 RegisterWeakObjectsInOptimizedCode(info()->code());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400607 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000608 RecordOptimizationStats();
609 return last_status();
610 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000611
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 DCHECK(!info()->dependencies()->HasAborted());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 DisallowCodeDependencyChange no_dependency_change;
614 DisallowJavascriptExecution no_js(isolate());
615 { // Scope for timer.
616 Timer timer(this, &time_taken_to_codegen_);
617 DCHECK(chunk_ != NULL);
618 DCHECK(graph_ != NULL);
619 // Deferred handles reference objects that were accessible during
620 // graph creation. To make sure that we don't encounter inconsistencies
621 // between graph creation and code generation, we disallow accessing
622 // objects through deferred handles during the latter, with exceptions.
623 DisallowDeferredHandleDereference no_deferred_handle_deref;
624 Handle<Code> optimized_code = chunk_->Codegen();
625 if (optimized_code.is_null()) {
626 if (info()->bailout_reason() == kNoReason) {
627 return AbortOptimization(kCodeGenerationFailed);
Leon Clarke4515c472010-02-03 11:58:03 +0000628 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 return SetLastStatus(BAILED_OUT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000630 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 RegisterWeakObjectsInOptimizedCode(optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 info()->SetCode(optimized_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000633 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 RecordOptimizationStats();
635 // Add to the weak list of optimized code objects.
636 info()->context()->native_context()->AddOptimizedCode(*info()->code());
637 return SetLastStatus(SUCCEEDED);
Steve Blocka7e24c12009-10-30 11:49:00 +0000638}
639
640
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641void OptimizedCompileJob::RecordOptimizationStats() {
642 Handle<JSFunction> function = info()->closure();
643 if (!function->IsOptimized()) {
644 // Concurrent recompilation and OSR may race. Increment only once.
645 int opt_count = function->shared()->opt_count();
646 function->shared()->set_opt_count(opt_count + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
649 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
650 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
651 if (FLAG_trace_opt) {
652 PrintF("[optimizing ");
653 function->ShortPrint();
654 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
655 ms_codegen);
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657 if (FLAG_trace_opt_stats) {
658 static double compilation_time = 0.0;
659 static int compiled_functions = 0;
660 static int code_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000661
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
663 compiled_functions++;
664 code_size += function->shared()->SourceSize();
665 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
666 compiled_functions,
667 code_size,
668 compilation_time);
669 }
670 if (FLAG_hydrogen_stats) {
671 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
672 time_taken_to_optimize_,
673 time_taken_to_codegen_);
674 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000675}
676
677
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678// Sets the expected number of properties based on estimate from compiler.
679void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
680 int estimate) {
681 // If no properties are added in the constructor, they are more likely
682 // to be added later.
683 if (estimate == 0) estimate = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +0000684
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000685 // TODO(yangguo): check whether those heuristics are still up-to-date.
686 // We do not shrink objects that go into a snapshot (yet), so we adjust
687 // the estimate conservatively.
688 if (shared->GetIsolate()->serializer_enabled()) {
689 estimate += 2;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400690 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000691 // Inobject slack tracking will reclaim redundant inobject space later,
692 // so we can afford to adjust the estimate generously.
693 estimate += 8;
Steve Blocka7e24c12009-10-30 11:49:00 +0000694 }
695
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000696 shared->set_expected_nof_properties(estimate);
Steve Blockd0582a62009-12-15 09:54:21 +0000697}
698
699
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400700static void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
701 BailoutReason bailout_reason) {
702 if (bailout_reason != kNoReason) {
703 shared_info->DisableOptimization(bailout_reason);
704 }
705}
706
707
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
709 CompilationInfo* info,
710 Handle<SharedFunctionInfo> shared) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100711 // SharedFunctionInfo is passed separately, because if CompilationInfo
712 // was created using Script object, it will not have it.
713
Ben Murdochf87a2032010-10-22 12:50:53 +0100714 // Log the code generation. If source information is available include
715 // script name and line number. Check explicitly whether logging is
716 // enabled as finding the line number is not free.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717 if (info->isolate()->logger()->is_logging_code_events() ||
718 info->isolate()->cpu_profiler()->is_profiling()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719 Handle<Script> script = info->parse_info()->script();
Ben Murdochf87a2032010-10-22 12:50:53 +0100720 Handle<Code> code = info->code();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721 if (code.is_identical_to(info->isolate()->builtins()->CompileLazy())) {
Steve Block44f0eee2011-05-26 01:26:41 +0100722 return;
Andrei Popescu31002712010-02-23 13:46:05 +0000723 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000724 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
725 int column_num =
726 Script::GetColumnNumber(script, shared->start_position()) + 1;
727 String* script_name = script->name()->IsString()
728 ? String::cast(script->name())
729 : info->isolate()->heap()->empty_string();
730 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
731 PROFILE(info->isolate(),
732 CodeCreateEvent(log_tag, *code, *shared, info, script_name,
733 line_num, column_num));
Andrei Popescu31002712010-02-23 13:46:05 +0000734 }
735}
Andrei Popescu31002712010-02-23 13:46:05 +0000736
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737static bool CompileUnoptimizedCode(CompilationInfo* info) {
738 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739 if (!Compiler::Analyze(info->parse_info()) ||
740 !FullCodeGenerator::MakeCode(info)) {
741 Isolate* isolate = info->isolate();
742 if (!isolate->has_pending_exception()) isolate->StackOverflow();
743 return false;
744 }
745 return true;
746}
747
748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749static bool UseIgnition(CompilationInfo* info) {
750 // Cannot use Ignition when the {function_data} is already used.
751 if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId()) {
752 return false;
753 }
754
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 // Checks whether top level functions should be passed by the filter.
756 if (info->closure().is_null()) {
757 Vector<const char> filter = CStrVector(FLAG_ignition_filter);
758 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
759 }
760
761 // Finally respect the filter.
762 return info->closure()->PassesFilter(FLAG_ignition_filter);
763}
764
Ben Murdoch097c5b22016-05-18 11:27:45 +0100765static int CodeAndMetadataSize(CompilationInfo* info) {
766 int size = 0;
767 if (info->has_bytecode_array()) {
768 Handle<BytecodeArray> bytecode_array = info->bytecode_array();
769 size += bytecode_array->BytecodeArraySize();
770 size += bytecode_array->constant_pool()->Size();
771 size += bytecode_array->handler_table()->Size();
772 size += bytecode_array->source_position_table()->Size();
773 } else {
774 Handle<Code> code = info->code();
775 size += code->CodeSize();
776 size += code->relocation_info()->Size();
777 size += code->deoptimization_data()->Size();
778 size += code->handler_table()->Size();
779 }
780 return size;
781}
782
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783
784static bool GenerateBaselineCode(CompilationInfo* info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100785 bool success;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000786 if (FLAG_ignition && UseIgnition(info)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100787 success = interpreter::Interpreter::MakeBytecode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100789 success = FullCodeGenerator::MakeCode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000790 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100791 if (success) {
792 Isolate* isolate = info->isolate();
793 Counters* counters = isolate->counters();
794 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info));
795 counters->total_baseline_compile_count()->Increment(1);
796 }
797 return success;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000798}
799
800
801static bool CompileBaselineCode(CompilationInfo* info) {
802 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
803 if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 Isolate* isolate = info->isolate();
805 if (!isolate->has_pending_exception()) isolate->StackOverflow();
806 return false;
807 }
808 return true;
809}
810
811
812MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon(
813 CompilationInfo* info) {
814 VMState<COMPILER> state(info->isolate());
815 PostponeInterruptsScope postpone(info->isolate());
816
817 // Parse and update CompilationInfo with the results.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000819 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000820 FunctionLiteral* lit = info->literal();
821 DCHECK_EQ(shared->language_mode(), lit->language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000822 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400823 MaybeDisableOptimization(shared, lit->dont_optimize_reason());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 // Compile either unoptimized code or bytecode for the interpreter.
826 if (!CompileBaselineCode(info)) return MaybeHandle<Code>();
827 if (info->code()->kind() == Code::FUNCTION) { // Only for full code.
828 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
829 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830
831 // Update the shared function info with the scope info. Allocating the
832 // ScopeInfo object may cause a GC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000833 Handle<ScopeInfo> scope_info =
834 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 shared->set_scope_info(*scope_info);
836
837 // Update the code and feedback vector for the shared function info.
838 shared->ReplaceCode(*info->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 shared->set_feedback_vector(*info->feedback_vector());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840 if (info->has_bytecode_array()) {
841 DCHECK(shared->function_data()->IsUndefined());
842 shared->set_function_data(*info->bytecode_array());
843 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000844
845 return info->code();
846}
847
848
849MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
850 Handle<JSFunction> function, BailoutId osr_ast_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000851 Handle<SharedFunctionInfo> shared(function->shared());
852 DisallowHeapAllocation no_gc;
853 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
854 function->context()->native_context(), osr_ast_id);
855 if (cached.code != nullptr) {
856 // Caching of optimized code enabled and optimized code found.
857 if (cached.literals != nullptr) function->set_literals(cached.literals);
858 DCHECK(!cached.code->marked_for_deoptimization());
859 DCHECK(function->shared()->is_compiled());
860 return Handle<Code>(cached.code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861 }
862 return MaybeHandle<Code>();
863}
864
865
866static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
867 Handle<Code> code = info->code();
868 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 // Function context specialization folds-in the function context,
871 // so no sharing can occur.
872 if (info->is_function_context_specializing()) return;
873 // Frame specialization implies function context specialization.
874 DCHECK(!info->is_frame_specializing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 // Cache optimized context-specific code.
877 Handle<JSFunction> function = info->closure();
878 Handle<SharedFunctionInfo> shared(function->shared());
879 Handle<LiteralsArray> literals(function->literals());
880 Handle<Context> native_context(function->context()->native_context());
881 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
882 literals, info->osr_ast_id());
883
884 // Do not cache (native) context-independent code compiled for OSR.
885 if (code->is_turbofanned() && info->is_osr()) return;
886
887 // Cache optimized (native) context-independent code.
888 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
889 !info->is_native_context_specializing()) {
890 DCHECK(!info->is_function_context_specializing());
891 DCHECK(info->osr_ast_id().IsNone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000892 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000893 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894 }
895}
896
897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898static bool Renumber(ParseInfo* parse_info) {
899 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
900 parse_info->literal())) {
901 return false;
902 }
903 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info();
904 if (!shared_info.is_null()) {
905 FunctionLiteral* lit = parse_info->literal();
906 shared_info->set_ast_node_count(lit->ast_node_count());
907 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason());
908 shared_info->set_dont_crankshaft(lit->flags() &
909 AstProperties::kDontCrankshaft);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400910 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000911 return true;
912}
913
914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000915bool Compiler::Analyze(ParseInfo* info) {
916 DCHECK_NOT_NULL(info->literal());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400917 if (!Rewriter::Rewrite(info)) return false;
918 if (!Scope::Analyze(info)) return false;
919 if (!Renumber(info)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 DCHECK_NOT_NULL(info->scope());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400921 return true;
922}
923
924
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925bool Compiler::ParseAndAnalyze(ParseInfo* info) {
926 if (!Parser::ParseStatic(info)) return false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400927 return Compiler::Analyze(info);
928}
929
930
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931static bool GetOptimizedCodeNow(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 Isolate* isolate = info->isolate();
933 CanonicalHandleScope canonical(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100934 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
935 TRACE_EVENT0("v8", "V8.OptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
938
939 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100940 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941
942 OptimizedCompileJob job(info);
943 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED ||
944 job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED ||
945 job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) {
946 if (FLAG_trace_opt) {
947 PrintF("[aborted optimizing ");
948 info->closure()->ShortPrint();
949 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
950 }
951 return false;
952 }
953
954 // Success!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956 InsertCodeIntoOptimizedCodeMap(info);
957 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info,
958 info->shared_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000959 return true;
960}
961
962
963static bool GetOptimizedCodeLater(CompilationInfo* info) {
964 Isolate* isolate = info->isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 CanonicalHandleScope canonical(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100966 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
967 TRACE_EVENT0("v8", "V8.OptimizeCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968
969 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 if (FLAG_trace_concurrent_recompilation) {
971 PrintF(" ** Compilation queue full, will retry optimizing ");
972 info->closure()->ShortPrint();
973 PrintF(" later.\n");
974 }
975 return false;
976 }
977
978 CompilationHandleScope handle_scope(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000979 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
980
981 // Reopen handles in the new CompilationHandleScope.
982 info->ReopenHandlesInNewHandleScope();
983 info->parse_info()->ReopenHandlesInNewHandleScope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000984
985 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100986 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987
988 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info);
989 OptimizedCompileJob::Status status = job->CreateGraph();
990 if (status != OptimizedCompileJob::SUCCEEDED) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992
993 if (FLAG_trace_concurrent_recompilation) {
994 PrintF(" ** Queued ");
995 info->closure()->ShortPrint();
996 if (info->is_osr()) {
997 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt());
998 } else {
999 PrintF(" for concurrent optimization.\n");
1000 }
1001 }
1002 return true;
1003}
1004
1005
1006MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) {
1007 DCHECK(!function->GetIsolate()->has_pending_exception());
1008 DCHECK(!function->is_compiled());
1009 if (function->shared()->is_compiled()) {
1010 return Handle<Code>(function->shared()->code());
1011 }
1012
1013 CompilationInfoWithZone info(function);
1014 Handle<Code> result;
1015 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result,
1016 GetUnoptimizedCodeCommon(&info),
1017 Code);
1018 return result;
1019}
1020
1021
1022MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001023 Isolate* isolate = function->GetIsolate();
1024 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025 DCHECK(!function->is_compiled());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001026 TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1027 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001029 // If the debugger is active, do not compile with turbofan unless we can
1030 // deopt from turbofan code.
1031 if (FLAG_turbo_asm && function->shared()->asm_function() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001032 (FLAG_turbo_asm_deoptimization || !isolate->debug()->is_active()) &&
1033 !FLAG_turbo_osr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 CompilationInfoWithZone info(function);
1035
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001036 VMState<COMPILER> state(isolate);
1037 PostponeInterruptsScope postpone(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038
Ben Murdoch097c5b22016-05-18 11:27:45 +01001039 info.SetOptimizing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001041 if (GetOptimizedCodeNow(&info)) {
1042 DCHECK(function->shared()->is_compiled());
1043 return info.code();
1044 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 // We have failed compilation. If there was an exception clear it so that
1046 // we can compile unoptimized code.
1047 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 }
1049
1050 if (function->shared()->is_compiled()) {
1051 return Handle<Code>(function->shared()->code());
1052 }
1053
1054 CompilationInfoWithZone info(function);
1055 Handle<Code> result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001056 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCodeCommon(&info),
1057 Code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001058
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001059 if (FLAG_always_opt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001060 Handle<Code> opt_code;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001061 if (Compiler::GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
1062 .ToHandle(&opt_code)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001063 result = opt_code;
1064 }
1065 }
1066
1067 return result;
1068}
1069
1070
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001071bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001072 if (function->is_compiled()) return true;
1073 MaybeHandle<Code> maybe_code = Compiler::GetLazyCode(function);
1074 Handle<Code> code;
1075 if (!maybe_code.ToHandle(&code)) {
1076 if (flag == CLEAR_EXCEPTION) {
1077 function->GetIsolate()->clear_pending_exception();
1078 }
1079 return false;
1080 }
1081 function->ReplaceCode(*code);
1082 DCHECK(function->is_compiled());
1083 return true;
1084}
1085
1086
1087// TODO(turbofan): In the future, unoptimized code with deopt support could
1088// be generated lazily once deopt is triggered.
1089bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001090 DCHECK_NOT_NULL(info->literal());
1091 DCHECK(info->has_scope());
1092 Handle<SharedFunctionInfo> shared = info->shared_info();
1093 if (!shared->has_deoptimization_support()) {
1094 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
1095 CompilationInfoWithZone unoptimized(info->closure());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001096 // Note that we use the same AST that we will use for generating the
1097 // optimized code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001098 ParseInfo* parse_info = unoptimized.parse_info();
1099 parse_info->set_literal(info->literal());
1100 parse_info->set_scope(info->scope());
1101 parse_info->set_context(info->context());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 unoptimized.EnableDeoptimizationSupport();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001103 // If the current code has reloc info for serialization, also include
1104 // reloc info for serialization for the new code, so that deopt support
1105 // can be added without losing IC state.
1106 if (shared->code()->kind() == Code::FUNCTION &&
1107 shared->code()->has_reloc_info_for_serialization()) {
1108 unoptimized.PrepareForSerializing();
1109 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001110 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1111
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 shared->EnableDeoptimizationSupport(*unoptimized.code());
1113 shared->set_feedback_vector(*unoptimized.feedback_vector());
1114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001115 info->MarkAsCompiled();
1116
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001117 // The scope info might not have been set if a lazily compiled
1118 // function is inlined before being called for the first time.
1119 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1120 Handle<ScopeInfo> target_scope_info =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122 shared->set_scope_info(*target_scope_info);
1123 }
1124
1125 // The existing unoptimized code was replaced with the new one.
1126 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
1127 }
1128 return true;
1129}
1130
1131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001132bool CompileEvalForDebugging(Handle<JSFunction> function,
1133 Handle<SharedFunctionInfo> shared) {
1134 Handle<Script> script(Script::cast(shared->script()));
1135 Handle<Context> context(function->context());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137 Zone zone;
1138 ParseInfo parse_info(&zone, script);
1139 CompilationInfo info(&parse_info);
1140 Isolate* isolate = info.isolate();
1141
1142 parse_info.set_eval();
1143 parse_info.set_context(context);
1144 if (context->IsNativeContext()) parse_info.set_global();
1145 parse_info.set_toplevel();
1146 parse_info.set_allow_lazy_parsing(false);
1147 parse_info.set_language_mode(shared->language_mode());
1148 parse_info.set_parse_restriction(NO_PARSE_RESTRICTION);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001149 info.MarkAsDebug();
1150
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001151 VMState<COMPILER> state(info.isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001152
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001153 if (!Parser::ParseStatic(&parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001154 isolate->clear_pending_exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001155 return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001156 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157
1158 FunctionLiteral* lit = parse_info.literal();
1159 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
1160
1161 if (!CompileUnoptimizedCode(&info)) {
1162 isolate->clear_pending_exception();
1163 return false;
1164 }
1165 shared->ReplaceCode(*info.code());
1166 return true;
1167}
1168
1169
1170bool CompileForDebugging(CompilationInfo* info) {
1171 info->MarkAsDebug();
1172 if (GetUnoptimizedCodeCommon(info).is_null()) {
1173 info->isolate()->clear_pending_exception();
1174 return false;
1175 }
1176 return true;
1177}
1178
1179
1180static inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
1181 return shared->is_toplevel() && shared->script()->IsScript() &&
1182 Script::cast(shared->script())->compilation_type() ==
1183 Script::COMPILATION_TYPE_EVAL;
1184}
1185
1186
1187bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
1188 Handle<SharedFunctionInfo> shared(function->shared());
1189 if (IsEvalToplevel(shared)) {
1190 return CompileEvalForDebugging(function, shared);
1191 } else {
1192 CompilationInfoWithZone info(function);
1193 return CompileForDebugging(&info);
1194 }
1195}
1196
1197
1198bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1199 DCHECK(shared->allows_lazy_compilation_without_context());
1200 DCHECK(!IsEvalToplevel(shared));
1201 Zone zone;
1202 ParseInfo parse_info(&zone, shared);
1203 CompilationInfo info(&parse_info);
1204 return CompileForDebugging(&info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001205}
1206
1207
1208void Compiler::CompileForLiveEdit(Handle<Script> script) {
1209 // TODO(635): support extensions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001210 Zone zone;
1211 ParseInfo parse_info(&zone, script);
1212 CompilationInfo info(&parse_info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001213 PostponeInterruptsScope postpone(info.isolate());
1214 VMState<COMPILER> state(info.isolate());
1215
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001216 // Get rid of old list of shared function infos.
1217 info.MarkAsFirstCompile();
1218 info.MarkAsDebug();
1219 info.parse_info()->set_global();
1220 if (!Parser::ParseStatic(info.parse_info())) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001222 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001223 if (!CompileUnoptimizedCode(&info)) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 if (info.has_shared_info()) {
1225 Handle<ScopeInfo> scope_info =
1226 ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001227 info.shared_info()->set_scope_info(*scope_info);
1228 }
1229 tracker.RecordRootFunctionInfo(info.code());
1230}
1231
1232
1233static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
1234 Isolate* isolate = info->isolate();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001235 TimerEventScope<TimerEventCompileCode> timer(isolate);
1236 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 PostponeInterruptsScope postpone(isolate);
1238 DCHECK(!isolate->native_context().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 ParseInfo* parse_info = info->parse_info();
1240 Handle<Script> script = parse_info->script();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241
1242 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
1243 FixedArray* array = isolate->native_context()->embedder_data();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001244 script->set_context_data(array->get(v8::Context::kDebugIdIndex));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001245
1246 isolate->debug()->OnBeforeCompile(script);
1247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001248 DCHECK(parse_info->is_eval() || parse_info->is_global() ||
1249 parse_info->is_module());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001250
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001251 parse_info->set_toplevel();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001252
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253 Handle<SharedFunctionInfo> result;
1254
1255 { VMState<COMPILER> state(info->isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001256 if (parse_info->literal() == NULL) {
1257 // Parse the script if needed (if it's already parsed, literal() is
1258 // non-NULL). If compiling for debugging, we may eagerly compile inner
1259 // functions, so do not parse lazily in that case.
1260 ScriptCompiler::CompileOptions options = parse_info->compile_options();
1261 bool parse_allow_lazy = (options == ScriptCompiler::kConsumeParserCache ||
1262 String::cast(script->source())->length() >
1263 FLAG_min_preparse_length) &&
1264 !info->is_debug();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001266 parse_info->set_allow_lazy_parsing(parse_allow_lazy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267 if (!parse_allow_lazy &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001268 (options == ScriptCompiler::kProduceParserCache ||
1269 options == ScriptCompiler::kConsumeParserCache)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001270 // We are going to parse eagerly, but we either 1) have cached data
1271 // produced by lazy parsing or 2) are asked to generate cached data.
1272 // Eager parsing cannot benefit from cached data, and producing cached
1273 // data while parsing eagerly is not implemented.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 parse_info->set_cached_data(nullptr);
1275 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001277 if (!Parser::ParseStatic(parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001278 return Handle<SharedFunctionInfo>::null();
1279 }
1280 }
1281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing());
1283
1284 info->MarkAsFirstCompile();
1285
1286 FunctionLiteral* lit = parse_info->literal();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
1288
1289 // Measure how long it takes to do the compilation; only take the
1290 // rest of the function into account to avoid overlap with the
1291 // parsing statistics.
1292 HistogramTimer* rate = info->is_eval()
1293 ? info->isolate()->counters()->compile_eval()
1294 : info->isolate()->counters()->compile();
1295 HistogramTimerScope timer(rate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001296 TRACE_EVENT0("v8", info->is_eval() ? "V8.CompileEval" : "V8.Compile");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297
1298 // Compile the code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299 if (!CompileBaselineCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001300 return Handle<SharedFunctionInfo>::null();
1301 }
1302
1303 // Allocate function.
1304 DCHECK(!info->code().is_null());
1305 result = isolate->factory()->NewSharedFunctionInfo(
1306 lit->name(), lit->materialized_literal_count(), lit->kind(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001307 info->code(),
1308 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001309 info->feedback_vector());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 if (info->has_bytecode_array()) {
1311 DCHECK(result->function_data()->IsUndefined());
1312 result->set_function_data(*info->bytecode_array());
1313 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314
1315 DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 SharedFunctionInfo::InitFromFunctionLiteral(result, lit);
1317 SharedFunctionInfo::SetScript(result, script);
1318 result->set_is_toplevel(true);
1319 if (info->is_eval()) {
1320 // Eval scripts cannot be (re-)compiled without context.
1321 result->set_allows_lazy_compilation_without_context(false);
1322 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001324 Handle<String> script_name =
1325 script->name()->IsString()
1326 ? Handle<String>(String::cast(script->name()))
1327 : isolate->factory()->empty_string();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001328 Logger::LogEventsAndTags log_tag = info->is_eval()
1329 ? Logger::EVAL_TAG
1330 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
1331
1332 PROFILE(isolate, CodeCreateEvent(
1333 log_tag, *info->code(), *result, info, *script_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334
1335 // Hint to the runtime system used when allocating space for initial
1336 // property space by setting the expected number of properties for
1337 // the instances of the function.
1338 SetExpectedNofPropertiesFromEstimate(result,
1339 lit->expected_property_count());
1340
1341 if (!script.is_null())
1342 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1343
1344 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
1345 }
1346
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 return result;
1348}
1349
1350
1351MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1352 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001353 Handle<Context> context, LanguageMode language_mode,
1354 ParseRestriction restriction, int line_offset, int column_offset,
1355 Handle<Object> script_name, ScriptOriginOptions options) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 Isolate* isolate = source->GetIsolate();
1357 int source_length = source->length();
1358 isolate->counters()->total_eval_size()->Increment(source_length);
1359 isolate->counters()->total_compile_size()->Increment(source_length);
1360
1361 CompilationCache* compilation_cache = isolate->compilation_cache();
1362 MaybeHandle<SharedFunctionInfo> maybe_shared_info =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 compilation_cache->LookupEval(source, outer_info, context, language_mode,
1364 line_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365 Handle<SharedFunctionInfo> shared_info;
1366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001367 Handle<Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 if (!maybe_shared_info.ToHandle(&shared_info)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 script = isolate->factory()->NewScript(source);
1370 if (!script_name.is_null()) {
1371 script->set_name(*script_name);
1372 script->set_line_offset(line_offset);
1373 script->set_column_offset(column_offset);
1374 }
1375 script->set_origin_options(options);
1376 Zone zone;
1377 ParseInfo parse_info(&zone, script);
1378 CompilationInfo info(&parse_info);
1379 parse_info.set_eval();
1380 if (context->IsNativeContext()) parse_info.set_global();
1381 parse_info.set_language_mode(language_mode);
1382 parse_info.set_parse_restriction(restriction);
1383 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384
1385 Debug::RecordEvalCaller(script);
1386
1387 shared_info = CompileToplevel(&info);
1388
1389 if (shared_info.is_null()) {
1390 return MaybeHandle<JSFunction>();
1391 } else {
1392 // Explicitly disable optimization for eval code. We're not yet prepared
1393 // to handle eval-code in the optimizing compiler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001394 if (restriction != ONLY_SINGLE_FUNCTION_LITERAL) {
1395 shared_info->DisableOptimization(kEval);
1396 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001397
1398 // If caller is strict mode, the result must be in strict mode as well.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 DCHECK(is_sloppy(language_mode) ||
1400 is_strict(shared_info->language_mode()));
1401 compilation_cache->PutEval(source, outer_info, context, shared_info,
1402 line_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001403 }
1404 } else if (shared_info->ic_age() != isolate->heap()->global_ic_age()) {
1405 shared_info->ResetForNewContext(isolate->heap()->global_ic_age());
1406 }
1407
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001408 Handle<JSFunction> result =
1409 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1410 shared_info, context, NOT_TENURED);
1411
1412 // OnAfterCompile has to be called after we create the JSFunction, which we
1413 // may require to recompile the eval for debugging, if we find a function
1414 // that contains break points in the eval script.
1415 isolate->debug()->OnAfterCompile(script);
1416
1417 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418}
1419
1420
1421Handle<SharedFunctionInfo> Compiler::CompileScript(
1422 Handle<String> source, Handle<Object> script_name, int line_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001423 int column_offset, ScriptOriginOptions resource_options,
1424 Handle<Object> source_map_url, Handle<Context> context,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001425 v8::Extension* extension, ScriptData** cached_data,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001426 ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
1427 bool is_module) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001428 Isolate* isolate = source->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001429 if (compile_options == ScriptCompiler::kNoCompileOptions) {
1430 cached_data = NULL;
1431 } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1432 compile_options == ScriptCompiler::kProduceCodeCache) {
1433 DCHECK(cached_data && !*cached_data);
1434 DCHECK(extension == NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001435 DCHECK(!isolate->debug()->is_loaded());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436 } else {
1437 DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1438 compile_options == ScriptCompiler::kConsumeCodeCache);
1439 DCHECK(cached_data && *cached_data);
1440 DCHECK(extension == NULL);
1441 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442 int source_length = source->length();
1443 isolate->counters()->total_load_size()->Increment(source_length);
1444 isolate->counters()->total_compile_size()->Increment(source_length);
1445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001446 // TODO(rossberg): The natives do not yet obey strong mode rules
1447 // (for example, some macros use '==').
1448 bool use_strong = FLAG_use_strong && !isolate->bootstrapper()->IsActive();
1449 LanguageMode language_mode =
1450 construct_language_mode(FLAG_use_strict, use_strong);
1451
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001452 CompilationCache* compilation_cache = isolate->compilation_cache();
1453
1454 // Do a lookup in the compilation cache but not for extensions.
1455 MaybeHandle<SharedFunctionInfo> maybe_result;
1456 Handle<SharedFunctionInfo> result;
1457 if (extension == NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001458 // First check per-isolate compilation cache.
1459 maybe_result = compilation_cache->LookupScript(
1460 source, script_name, line_offset, column_offset, resource_options,
1461 context, language_mode);
1462 if (maybe_result.is_null() && FLAG_serialize_toplevel &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 compile_options == ScriptCompiler::kConsumeCodeCache &&
1464 !isolate->debug()->is_loaded()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001465 // Then check cached code provided by embedder.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001467 TRACE_EVENT0("v8", "V8.CompileDeserialize");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001468 Handle<SharedFunctionInfo> result;
1469 if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1470 .ToHandle(&result)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001471 // Promote to per-isolate compilation cache.
1472 compilation_cache->PutScript(source, context, language_mode, result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001473 return result;
1474 }
1475 // Deserializer failed. Fall through to compile.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476 }
1477 }
1478
1479 base::ElapsedTimer timer;
1480 if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
1481 compile_options == ScriptCompiler::kProduceCodeCache) {
1482 timer.Start();
1483 }
1484
1485 if (!maybe_result.ToHandle(&result)) {
1486 // No cache entry found. Compile the script.
1487
1488 // Create a script object describing the script to be compiled.
1489 Handle<Script> script = isolate->factory()->NewScript(source);
1490 if (natives == NATIVES_CODE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001491 script->set_type(Script::TYPE_NATIVE);
1492 script->set_hide_source(true);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001493 } else if (natives == EXTENSION_CODE) {
1494 script->set_type(Script::TYPE_EXTENSION);
1495 script->set_hide_source(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496 }
1497 if (!script_name.is_null()) {
1498 script->set_name(*script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001499 script->set_line_offset(line_offset);
1500 script->set_column_offset(column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001502 script->set_origin_options(resource_options);
1503 if (!source_map_url.is_null()) {
1504 script->set_source_mapping_url(*source_map_url);
1505 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001506
1507 // Compile the function and add it to the cache.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001508 Zone zone;
1509 ParseInfo parse_info(&zone, script);
1510 CompilationInfo info(&parse_info);
1511 if (FLAG_harmony_modules && is_module) {
1512 parse_info.set_module();
1513 } else {
1514 parse_info.set_global();
1515 }
1516 if (compile_options != ScriptCompiler::kNoCompileOptions) {
1517 parse_info.set_cached_data(cached_data);
1518 }
1519 parse_info.set_compile_options(compile_options);
1520 parse_info.set_extension(extension);
1521 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001522 if (FLAG_serialize_toplevel &&
1523 compile_options == ScriptCompiler::kProduceCodeCache) {
1524 info.PrepareForSerializing();
1525 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527 parse_info.set_language_mode(
1528 static_cast<LanguageMode>(info.language_mode() | language_mode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001529 result = CompileToplevel(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001530 if (extension == NULL && !result.is_null()) {
1531 compilation_cache->PutScript(source, context, language_mode, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001532 if (FLAG_serialize_toplevel &&
1533 compile_options == ScriptCompiler::kProduceCodeCache) {
1534 HistogramTimerScope histogram_timer(
1535 isolate->counters()->compile_serialize());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001536 TRACE_EVENT0("v8", "V8.CompileSerialize");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001537 *cached_data = CodeSerializer::Serialize(isolate, result, source);
1538 if (FLAG_profile_deserialization) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001539 PrintF("[Compiling and serializing took %0.3f ms]\n",
1540 timer.Elapsed().InMillisecondsF());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541 }
1542 }
1543 }
1544
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001545 if (result.is_null()) {
1546 isolate->ReportPendingMessages();
1547 } else {
1548 isolate->debug()->OnAfterCompile(script);
1549 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550 } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1551 result->ResetForNewContext(isolate->heap()->global_ic_age());
1552 }
1553 return result;
1554}
1555
1556
1557Handle<SharedFunctionInfo> Compiler::CompileStreamedScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001558 Handle<Script> script, ParseInfo* parse_info, int source_length) {
1559 Isolate* isolate = script->GetIsolate();
1560 // TODO(titzer): increment the counters in caller.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561 isolate->counters()->total_load_size()->Increment(source_length);
1562 isolate->counters()->total_compile_size()->Increment(source_length);
1563
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001564 LanguageMode language_mode =
1565 construct_language_mode(FLAG_use_strict, FLAG_use_strong);
1566 parse_info->set_language_mode(
1567 static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1568
1569 CompilationInfo compile_info(parse_info);
1570
1571 // The source was parsed lazily, so compiling for debugging is not possible.
1572 DCHECK(!compile_info.is_debug());
1573
1574 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
1575 if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
1576 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001577}
1578
1579
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001581 FunctionLiteral* literal, Handle<Script> script,
1582 CompilationInfo* outer_info) {
1583 // Precondition: code has been parsed and scopes have been analyzed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 Isolate* isolate = outer_info->isolate();
1585 MaybeHandle<SharedFunctionInfo> maybe_existing;
1586 if (outer_info->is_first_compile()) {
1587 // On the first compile, there are no existing shared function info for
1588 // inner functions yet, so do not try to find them. All bets are off for
1589 // live edit though.
1590 DCHECK(script->FindSharedFunctionInfo(literal).is_null() ||
1591 isolate->debug()->live_edit_enabled());
1592 } else {
1593 maybe_existing = script->FindSharedFunctionInfo(literal);
1594 }
1595 // We found an existing shared function info. If it's already compiled,
1596 // don't worry about compiling it, and simply return it. If it's not yet
1597 // compiled, continue to decide whether to eagerly compile.
1598 // Carry on if we are compiling eager to obtain code for debugging,
1599 // unless we already have code with debut break slots.
1600 Handle<SharedFunctionInfo> existing;
1601 if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) {
1602 if (!outer_info->is_debug() || existing->HasDebugCode()) {
1603 return existing;
1604 }
1605 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001606
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001607 Zone zone;
1608 ParseInfo parse_info(&zone, script);
1609 CompilationInfo info(&parse_info);
1610 parse_info.set_literal(literal);
1611 parse_info.set_scope(literal->scope());
1612 parse_info.set_language_mode(literal->scope()->language_mode());
1613 if (outer_info->will_serialize()) info.PrepareForSerializing();
1614 if (outer_info->is_first_compile()) info.MarkAsFirstCompile();
1615 if (outer_info->is_debug()) info.MarkAsDebug();
1616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
1618 // Determine if the function can be lazily compiled. This is necessary to
1619 // allow some of our builtin JS files to be lazily compiled. These
1620 // builtins cannot be handled lazily by the parser, since we have to know
1621 // if a function uses the special natives syntax, which is something the
1622 // parser records.
1623 // If the debugger requests compilation for break points, we cannot be
1624 // aggressive about lazy compilation, because it might trigger compilation
1625 // of functions without an outer context when setting a breakpoint through
1626 // Debug::FindSharedFunctionInfoInScript.
1627 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001628 // Compile eagerly for live edit. When compiling debug code, eagerly compile
1629 // unless we can lazily compile without the context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001630 bool allow_lazy = literal->AllowsLazyCompilation() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001631 !LiveEditFunctionTracker::IsActive(isolate) &&
1632 (!info.is_debug() || allow_lazy_without_ctx);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001633
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001634 bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001635
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001636 // Generate code
Ben Murdoch097c5b22016-05-18 11:27:45 +01001637 TimerEventScope<TimerEventCompileCode> timer(isolate);
1638 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001639 Handle<ScopeInfo> scope_info;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001640 if (lazy) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641 Handle<Code> code = isolate->builtins()->CompileLazy();
1642 info.SetCode(code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001643 // There's no need in theory for a lazy-compiled function to have a type
1644 // feedback vector, but some parts of the system expect all
1645 // SharedFunctionInfo instances to have one. The size of the vector depends
1646 // on how many feedback-needing nodes are in the tree, and when lazily
1647 // parsing we might not know that, if this function was never parsed before.
1648 // In that case the vector will be replaced the next time MakeCode is
1649 // called.
1650 info.EnsureFeedbackVector();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001651 scope_info = Handle<ScopeInfo>(ScopeInfo::Empty(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001652 } else if (Renumber(info.parse_info()) && GenerateBaselineCode(&info)) {
1653 // Code generation will ensure that the feedback vector is present and
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001654 // appropriately sized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001655 DCHECK(!info.code().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001656 scope_info = ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
1657 if (literal->should_eager_compile() &&
1658 literal->should_be_used_once_hint()) {
1659 info.code()->MarkToBeExecutedOnce(isolate);
1660 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001661 } else {
1662 return Handle<SharedFunctionInfo>::null();
1663 }
1664
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001665 if (maybe_existing.is_null()) {
1666 // Create a shared function info object.
1667 Handle<SharedFunctionInfo> result =
1668 isolate->factory()->NewSharedFunctionInfo(
1669 literal->name(), literal->materialized_literal_count(),
1670 literal->kind(), info.code(), scope_info, info.feedback_vector());
1671 if (info.has_bytecode_array()) {
1672 DCHECK(result->function_data()->IsUndefined());
1673 result->set_function_data(*info.bytecode_array());
1674 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001675
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001676 SharedFunctionInfo::InitFromFunctionLiteral(result, literal);
1677 SharedFunctionInfo::SetScript(result, script);
1678 result->set_is_toplevel(false);
1679 // If the outer function has been compiled before, we cannot be sure that
1680 // shared function info for this function literal has been created for the
1681 // first time. It may have already been compiled previously.
1682 result->set_never_compiled(outer_info->is_first_compile() && lazy);
1683
1684 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1685 result->set_allows_lazy_compilation(literal->AllowsLazyCompilation());
1686 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1687
1688 // Set the expected number of properties for instances and return
1689 // the resulting function.
1690 SetExpectedNofPropertiesFromEstimate(result,
1691 literal->expected_property_count());
1692 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
1693 return result;
1694 } else if (!lazy) {
1695 // Assert that we are not overwriting (possibly patched) debug code.
1696 DCHECK(!existing->HasDebugCode());
1697 existing->ReplaceCode(*info.code());
1698 existing->set_scope_info(*scope_info);
1699 existing->set_feedback_vector(*info.feedback_vector());
1700 }
1701 return existing;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001702}
1703
Ben Murdoch097c5b22016-05-18 11:27:45 +01001704Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
1705 v8::Extension* extension, Handle<String> name) {
1706 Isolate* isolate = name->GetIsolate();
1707 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1708
1709 // Compute the function template for the native function.
1710 v8::Local<v8::FunctionTemplate> fun_template =
1711 extension->GetNativeFunctionTemplate(v8_isolate,
1712 v8::Utils::ToLocal(name));
1713 DCHECK(!fun_template.IsEmpty());
1714
1715 // Instantiate the function and create a shared function info from it.
1716 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
1717 *fun_template->GetFunction(v8_isolate->GetCurrentContext())
1718 .ToLocalChecked()));
1719 const int literals = fun->NumberOfLiterals();
1720 Handle<Code> code = Handle<Code>(fun->shared()->code());
1721 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1722 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
1723 name, literals, FunctionKind::kNormalFunction, code,
1724 Handle<ScopeInfo>(fun->shared()->scope_info()),
1725 Handle<TypeFeedbackVector>(fun->shared()->feedback_vector()));
1726 shared->set_construct_stub(*construct_stub);
1727
1728 // Copy the function data to the shared function info.
1729 shared->set_function_data(fun->shared()->function_data());
1730 int parameters = fun->shared()->internal_formal_parameter_count();
1731 shared->set_internal_formal_parameter_count(parameters);
1732
1733 return shared;
1734}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001735
1736MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001737 ConcurrencyMode mode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001738 BailoutId osr_ast_id,
1739 JavaScriptFrame* osr_frame) {
1740 Isolate* isolate = function->GetIsolate();
1741 Handle<SharedFunctionInfo> shared(function->shared(), isolate);
1742 if (shared->HasDebugInfo()) return MaybeHandle<Code>();
1743
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001744 Handle<Code> cached_code;
1745 if (GetCodeFromOptimizedCodeMap(
1746 function, osr_ast_id).ToHandle(&cached_code)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001747 if (FLAG_trace_opt) {
1748 PrintF("[found optimized code for ");
1749 function->ShortPrint();
1750 if (!osr_ast_id.IsNone()) {
1751 PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
1752 }
1753 PrintF("]\n");
1754 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001755 return cached_code;
1756 }
1757
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001758 DCHECK(AllowCompilation::IsAllowed(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001759
Ben Murdoch097c5b22016-05-18 11:27:45 +01001760 Handle<Code> current_code(shared->code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001761 if (!shared->is_compiled() ||
1762 shared->scope_info() == ScopeInfo::Empty(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001763 // The function was never compiled. Compile it unoptimized first.
1764 // TODO(titzer): reuse the AST and scope info from this compile.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001765 CompilationInfoWithZone unoptimized(function);
1766 unoptimized.EnableDeoptimizationSupport();
1767 if (!GetUnoptimizedCodeCommon(&unoptimized).ToHandle(&current_code)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001768 return MaybeHandle<Code>();
1769 }
1770 shared->ReplaceCode(*current_code);
1771 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001772
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001773 current_code->set_profiler_ticks(0);
1774
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001775 // TODO(mstarzinger): We cannot properly deserialize a scope chain containing
1776 // an eval scope and hence would fail at parsing the eval source again.
1777 if (shared->disable_optimization_reason() == kEval) {
1778 return MaybeHandle<Code>();
1779 }
1780
1781 // TODO(mstarzinger): We cannot properly deserialize a scope chain for the
1782 // builtin context, hence Genesis::InstallExperimentalNatives would fail.
1783 if (shared->is_toplevel() && isolate->bootstrapper()->IsActive()) {
1784 return MaybeHandle<Code>();
1785 }
1786
1787 base::SmartPointer<CompilationInfo> info(
1788 new CompilationInfoWithZone(function));
1789 VMState<COMPILER> state(isolate);
1790 DCHECK(!isolate->has_pending_exception());
1791 PostponeInterruptsScope postpone(isolate);
1792
Ben Murdoch097c5b22016-05-18 11:27:45 +01001793 info->SetOptimizingForOsr(osr_ast_id, current_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001794
1795 if (mode == CONCURRENT) {
1796 if (GetOptimizedCodeLater(info.get())) {
1797 info.Detach(); // The background recompile job owns this now.
1798 return isolate->builtins()->InOptimizationQueue();
1799 }
1800 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001801 info->set_osr_frame(osr_frame);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802 if (GetOptimizedCodeNow(info.get())) return info->code();
1803 }
1804
1805 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1806 return MaybeHandle<Code>();
1807}
1808
Ben Murdoch097c5b22016-05-18 11:27:45 +01001809MaybeHandle<Code> Compiler::GetConcurrentlyOptimizedCode(
1810 OptimizedCompileJob* job) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001811 // Take ownership of compilation info. Deleting compilation info
1812 // also tears down the zone and the recompile job.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001813 base::SmartPointer<CompilationInfo> info(job->info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001814 Isolate* isolate = info->isolate();
1815
1816 VMState<COMPILER> state(isolate);
1817 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001818 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001819
1820 Handle<SharedFunctionInfo> shared = info->shared_info();
1821 shared->code()->set_profiler_ticks(0);
1822
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001823 DCHECK(!shared->HasDebugInfo());
1824
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001825 // 1) Optimization on the concurrent thread may have failed.
1826 // 2) The function may have already been optimized by OSR. Simply continue.
1827 // Except when OSR already disabled optimization for some reason.
1828 // 3) The code may have already been invalidated due to dependency change.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001829 // 4) Code generation may have failed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001830 if (job->last_status() == OptimizedCompileJob::SUCCEEDED) {
1831 if (shared->optimization_disabled()) {
1832 job->RetryOptimization(kOptimizationDisabled);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001833 } else if (info->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001834 job->RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001835 } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
1836 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001837 if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
1838 info->osr_ast_id()).code == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001839 InsertCodeIntoOptimizedCodeMap(info.get());
1840 }
1841 if (FLAG_trace_opt) {
1842 PrintF("[completed optimizing ");
1843 info->closure()->ShortPrint();
1844 PrintF("]\n");
1845 }
1846 return Handle<Code>(*info->code());
1847 }
1848 }
1849
1850 DCHECK(job->last_status() != OptimizedCompileJob::SUCCEEDED);
1851 if (FLAG_trace_opt) {
1852 PrintF("[aborted optimizing ");
1853 info->closure()->ShortPrint();
1854 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
1855 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001856 return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001857}
1858
1859
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001860CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001861 : name_(name), info_(info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001862 if (FLAG_hydrogen_stats) {
1863 info_zone_start_allocation_size_ = info->zone()->allocation_size();
1864 timer_.Start();
1865 }
1866}
1867
1868
1869CompilationPhase::~CompilationPhase() {
1870 if (FLAG_hydrogen_stats) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001871 size_t size = zone()->allocation_size();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001872 size += info_->zone()->allocation_size() - info_zone_start_allocation_size_;
1873 isolate()->GetHStatistics()->SaveTiming(name_, timer_.Elapsed(), size);
1874 }
1875}
1876
1877
1878bool CompilationPhase::ShouldProduceTraceOutput() const {
1879 // Trace if the appropriate trace flag is set and the phase name's first
1880 // character is in the FLAG_trace_phase command line parameter.
1881 AllowHandleDereference allow_deref;
1882 bool tracing_on = info()->IsStub()
1883 ? FLAG_trace_hydrogen_stubs
1884 : (FLAG_trace_hydrogen &&
1885 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
1886 return (tracing_on &&
1887 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
1888}
1889
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001890#if DEBUG
1891void CompilationInfo::PrintAstForTesting() {
1892 PrintF("--- Source from AST ---\n%s\n",
1893 PrettyPrinter(isolate()).PrintProgram(literal()));
1894}
1895#endif
1896} // namespace internal
1897} // namespace v8