blob: 8bb53323abb3bfd639cea32dcbbd92b7f92d221c [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 Murdochda12d292016-06-02 14:46:10 +010034#include "src/snapshot/code-serializer.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
Ben Murdochda12d292016-06-02 14:46:10 +010069// A wrapper around a CompilationInfo that detaches the Handles from
70// the underlying DeferredHandleScope and stores them in info_ on
71// destruction.
72class CompilationHandleScope BASE_EMBEDDED {
73 public:
74 explicit CompilationHandleScope(CompilationInfo* info)
75 : deferred_(info->isolate()), info_(info) {}
76 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
77
78 private:
79 DeferredHandleScope deferred_;
80 CompilationInfo* info_;
81};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082
83// Exactly like a CompilationInfo, except being allocated via {new} and it also
84// creates and enters a Zone on construction and deallocates it on destruction.
85class CompilationInfoWithZone : public CompilationInfo {
86 public:
87 explicit CompilationInfoWithZone(Handle<JSFunction> function)
Ben Murdochda12d292016-06-02 14:46:10 +010088 : CompilationInfo(new ParseInfo(&zone_, function)),
89 zone_(function->GetIsolate()->allocator()) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090
91 // Virtual destructor because a CompilationInfoWithZone has to exit the
92 // zone scope and get rid of dependent maps even when the destructor is
93 // called when cast as a CompilationInfo.
94 virtual ~CompilationInfoWithZone() {
95 DisableFutureOptimization();
96 dependencies()->Rollback();
97 delete parse_info_;
98 parse_info_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100
101 private:
102 Zone zone_;
103};
104
Ben Murdochda12d292016-06-02 14:46:10 +0100105// ----------------------------------------------------------------------------
106// Implementation of CompilationInfo
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107
108bool CompilationInfo::has_shared_info() const {
109 return parse_info_ && !parse_info_->shared_info().is_null();
110}
111
112
113bool CompilationInfo::has_context() const {
114 return parse_info_ && !parse_info_->context().is_null();
115}
116
117
118bool CompilationInfo::has_literal() const {
119 return parse_info_ && parse_info_->literal() != nullptr;
120}
121
122
123bool CompilationInfo::has_scope() const {
124 return parse_info_ && parse_info_->scope() != nullptr;
125}
126
127
128CompilationInfo::CompilationInfo(ParseInfo* parse_info)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100129 : CompilationInfo(parse_info, nullptr, Code::ComputeFlags(Code::FUNCTION),
130 BASE, parse_info->isolate(), parse_info->zone()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400131 // Compiling for the snapshot typically results in different code than
132 // compiling later on. This means that code recompiled with deoptimization
133 // support won't be "equivalent" (as defined by SharedFunctionInfo::
134 // EnableDeoptimizationSupport), so it will replace the old code and all
135 // its type feedback. To avoid this, always compile functions in the snapshot
136 // with deoptimization support.
137 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 if (FLAG_turbo_inlining) MarkAsInliningEnabled();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled();
142 if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 if (FLAG_turbo_types) MarkAsTypingEnabled();
144
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 if (has_shared_info()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 if (shared_info()->never_compiled()) MarkAsFirstCompile();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151CompilationInfo::CompilationInfo(const char* debug_name, Isolate* isolate,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100152 Zone* zone, Code::Flags code_flags)
153 : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154
Ben Murdoch097c5b22016-05-18 11:27:45 +0100155CompilationInfo::CompilationInfo(ParseInfo* parse_info, const char* debug_name,
156 Code::Flags code_flags, Mode mode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 Isolate* isolate, Zone* zone)
158 : parse_info_(parse_info),
159 isolate_(isolate),
160 flags_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100161 code_flags_(code_flags),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 mode_(mode),
163 osr_ast_id_(BailoutId::None()),
164 zone_(zone),
165 deferred_handles_(nullptr),
166 dependencies_(isolate, zone),
167 bailout_reason_(kNoReason),
168 prologue_offset_(Code::kPrologueOffsetNotSet),
169 track_positions_(FLAG_hydrogen_track_positions ||
170 isolate->cpu_profiler()->is_profiling()),
171 opt_count_(has_shared_info() ? shared_info()->opt_count() : 0),
172 parameter_count_(0),
173 optimization_id_(-1),
174 osr_expr_stack_height_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100175 debug_name_(debug_name) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176
177
178CompilationInfo::~CompilationInfo() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 DisableFutureOptimization();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 delete deferred_handles_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181#ifdef DEBUG
182 // Check that no dependent maps have been added or added dependent maps have
183 // been rolled back or committed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 DCHECK(dependencies()->IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185#endif // DEBUG
186}
187
188
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189int CompilationInfo::num_parameters() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000190 return has_scope() ? scope()->num_parameters() : parameter_count_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191}
192
193
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194int CompilationInfo::num_parameters_including_this() const {
195 return num_parameters() + (is_this_defined() ? 1 : 0);
196}
197
198
199bool CompilationInfo::is_this_defined() const { return !IsStub(); }
200
201
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202int CompilationInfo::num_heap_slots() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 return has_scope() ? scope()->num_heap_slots() : 0;
Ben Murdoch257744e2011-11-30 15:57:28 +0000204}
Ben Murdochb8e0da22011-05-16 14:20:40 +0100205
Ben Murdoch257744e2011-11-30 15:57:28 +0000206
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100207// Primitive functions are unlikely to be picked up by the stack-walking
208// profiler, so they trigger their own optimization when they're called
209// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
210bool CompilationInfo::ShouldSelfOptimize() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000211 return FLAG_crankshaft &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
213 !literal()->dont_optimize() &&
214 literal()->scope()->AllowsLazyCompilation() &&
215 (!has_shared_info() || !shared_info()->optimization_disabled());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400216}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219bool CompilationInfo::has_simple_parameters() {
220 return scope()->has_simple_parameters();
221}
222
223
224int CompilationInfo::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
225 SourcePosition position,
226 int parent_id) {
227 DCHECK(track_positions_);
228
229 int inline_id = static_cast<int>(inlined_function_infos_.size());
230 InlinedFunctionInfo info(parent_id, position, UnboundScript::kNoScriptId,
231 shared->start_position());
232 if (!shared->script()->IsUndefined()) {
233 Handle<Script> script(Script::cast(shared->script()));
234 info.script_id = script->id();
235
236 if (FLAG_hydrogen_track_positions && !script->source()->IsUndefined()) {
237 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
238 OFStream os(tracing_scope.file());
239 os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
240 << ") id{" << optimization_id() << "," << inline_id << "} ---\n";
241 {
242 DisallowHeapAllocation no_allocation;
243 int start = shared->start_position();
244 int len = shared->end_position() - start;
245 String::SubStringRange source(String::cast(script->source()), start,
246 len);
247 for (const auto& c : source) {
248 os << AsReversiblyEscapedUC16(c);
249 }
250 }
251
252 os << "\n--- END ---\n";
253 }
254 }
255
256 inlined_function_infos_.push_back(info);
257
258 if (FLAG_hydrogen_track_positions && inline_id != 0) {
259 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
260 OFStream os(tracing_scope.file());
261 os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
262 << optimization_id() << "," << inline_id << "} AS " << inline_id
263 << " AT " << position << std::endl;
264 }
265
266 return inline_id;
267}
268
269
270void CompilationInfo::LogDeoptCallPosition(int pc_offset, int inlining_id) {
271 if (!track_positions_ || IsStub()) return;
272 DCHECK_LT(static_cast<size_t>(inlining_id), inlined_function_infos_.size());
273 inlined_function_infos_.at(inlining_id).deopt_pc_offsets.push_back(pc_offset);
274}
275
276
277base::SmartArrayPointer<char> CompilationInfo::GetDebugName() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100278 if (parse_info() && parse_info()->literal()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 AllowHandleDereference allow_deref;
280 return parse_info()->literal()->debug_name()->ToCString();
281 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100282 if (parse_info() && !parse_info()->shared_info().is_null()) {
283 return parse_info()->shared_info()->DebugName()->ToCString();
284 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 const char* str = debug_name_ ? debug_name_ : "unknown";
286 size_t len = strlen(str) + 1;
287 base::SmartArrayPointer<char> name(new char[len]);
288 memcpy(name.get(), str, len);
289 return name;
290}
291
Ben Murdochda12d292016-06-02 14:46:10 +0100292StackFrame::Type CompilationInfo::GetOutputStackFrameType() const {
293 switch (output_code_kind()) {
294 case Code::STUB:
295 case Code::BYTECODE_HANDLER:
296 case Code::HANDLER:
297 case Code::BUILTIN:
298 return StackFrame::STUB;
299 case Code::WASM_FUNCTION:
300 return StackFrame::WASM;
301 case Code::JS_TO_WASM_FUNCTION:
302 return StackFrame::JS_TO_WASM;
303 case Code::WASM_TO_JS_FUNCTION:
304 return StackFrame::WASM_TO_JS;
305 default:
306 UNIMPLEMENTED();
307 return StackFrame::NONE;
308 }
309}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310
311bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
312 return is_sloppy(language_mode()) && !is_native();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100313}
314
Ben Murdochda12d292016-06-02 14:46:10 +0100315#if DEBUG
316void CompilationInfo::PrintAstForTesting() {
317 PrintF("--- Source from AST ---\n%s\n",
318 PrettyPrinter(isolate()).PrintProgram(literal()));
319}
320#endif
321
322// ----------------------------------------------------------------------------
323// Implementation of OptimizedCompileJob
Ben Murdochb8e0da22011-05-16 14:20:40 +0100324
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
326 public:
327 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
328 : HOptimizedGraphBuilder(info) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100329 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100330
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331#define DEF_VISIT(type) \
332 void Visit##type(type* node) override { \
333 SourcePosition old_position = SourcePosition::Unknown(); \
334 if (node->position() != RelocInfo::kNoPosition) { \
335 old_position = source_position(); \
336 SetSourcePosition(node->position()); \
337 } \
338 HOptimizedGraphBuilder::Visit##type(node); \
339 if (!old_position.IsUnknown()) { \
340 set_source_position(old_position); \
341 } \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100342 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000343 EXPRESSION_NODE_LIST(DEF_VISIT)
344#undef DEF_VISIT
Ben Murdochb0fe1622011-05-05 13:52:32 +0100345
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346#define DEF_VISIT(type) \
347 void Visit##type(type* node) override { \
348 SourcePosition old_position = SourcePosition::Unknown(); \
349 if (node->position() != RelocInfo::kNoPosition) { \
350 old_position = source_position(); \
351 SetSourcePosition(node->position()); \
352 } \
353 HOptimizedGraphBuilder::Visit##type(node); \
354 if (!old_position.IsUnknown()) { \
355 set_source_position(old_position); \
356 } \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000357 }
358 STATEMENT_NODE_LIST(DEF_VISIT)
359#undef DEF_VISIT
360
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361#define DEF_VISIT(type) \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 void Visit##type(type* node) override { \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400363 HOptimizedGraphBuilder::Visit##type(node); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000365 DECLARATION_NODE_LIST(DEF_VISIT)
366#undef DEF_VISIT
367};
368
369
370OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 DCHECK(info()->IsOptimizing());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 // Do not use Crankshaft/TurboFan if we need to be able to set break points.
374 if (info()->shared_info()->HasDebugInfo()) {
375 return AbortOptimization(kFunctionBeingDebugged);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400376 }
Steve Block44f0eee2011-05-26 01:26:41 +0100377
Ben Murdochda12d292016-06-02 14:46:10 +0100378 // Resuming a suspended frame is not supported by Crankshaft/TurboFan.
379 if (info()->shared_info()->HasBuiltinFunctionId() &&
380 (info()->shared_info()->builtin_function_id() == kGeneratorObjectNext ||
381 info()->shared_info()->builtin_function_id() == kGeneratorObjectReturn ||
382 info()->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) {
383 return AbortOptimization(kGeneratorResumeMethod);
384 }
385
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 // Limit the number of times we try to optimize functions.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100387 const int kMaxOptCount =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
389 if (info()->opt_count() > kMaxOptCount) {
390 return AbortOptimization(kOptimizedTooManyTimes);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100391 }
392
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 // Check the whitelist for Crankshaft.
Ben Murdochda12d292016-06-02 14:46:10 +0100394 if (!info()->shared_info()->PassesFilter(FLAG_hydrogen_filter)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 return AbortOptimization(kHydrogenFilter);
396 }
397
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398 // Optimization requires a version of fullcode with deoptimization support.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100399 // Recompile the unoptimized version of the code if the current version
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000400 // doesn't have deoptimization support already.
401 // Otherwise, if we are gathering compilation time and space statistics
402 // for hydrogen, gather baseline statistics for a fullcode compilation.
403 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
Steve Block44f0eee2011-05-26 01:26:41 +0100404 if (should_recompile || FLAG_hydrogen_stats) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 base::ElapsedTimer timer;
406 if (FLAG_hydrogen_stats) {
407 timer.Start();
408 }
409 if (!Compiler::EnsureDeoptimizationSupport(info())) {
410 return SetLastStatus(FAILED);
411 }
412 if (FLAG_hydrogen_stats) {
413 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100414 }
415 }
416
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 DCHECK(info()->shared_info()->has_deoptimization_support());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000418 DCHECK(!info()->is_first_compile());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 bool optimization_disabled = info()->shared_info()->optimization_disabled();
421 bool dont_crankshaft = info()->shared_info()->dont_crankshaft();
422
423 // Check the enabling conditions for Turbofan.
424 // 1. "use asm" code.
425 bool is_turbofanable_asm = FLAG_turbo_asm &&
426 info()->shared_info()->asm_function() &&
427 !optimization_disabled;
428
429 // 2. Fallback for features unsupported by Crankshaft.
430 bool is_unsupported_by_crankshaft_but_turbofanable =
431 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
432 !optimization_disabled;
433
434 // 3. Explicitly enabled by the command-line filter.
Ben Murdochda12d292016-06-02 14:46:10 +0100435 bool passes_turbo_filter =
436 info()->shared_info()->PassesFilter(FLAG_turbo_filter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000437
438 // If this is OSR request, OSR must be enabled by Turbofan.
439 bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr();
440
441 if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
442 passes_turbo_filter) &&
443 passes_osr_test) {
444 // Use TurboFan for the compilation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400445 if (FLAG_trace_opt) {
446 OFStream os(stdout);
447 os << "[compiling method " << Brief(*info()->closure())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000448 << " using TurboFan";
449 if (info()->is_osr()) os << " OSR";
450 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400451 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452
453 if (info()->shared_info()->asm_function()) {
454 if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
455 info()->MarkAsFunctionContextSpecializing();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100456 } else {
457 if (!FLAG_always_opt) {
458 info()->MarkAsBailoutOnUninitialized();
459 }
460 if (FLAG_native_context_specialization) {
461 info()->MarkAsNativeContextSpecializing();
462 info()->MarkAsTypingEnabled();
463 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 }
465 if (!info()->shared_info()->asm_function() ||
466 FLAG_turbo_asm_deoptimization) {
467 info()->MarkAsDeoptimizationEnabled();
468 }
469
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400470 Timer t(this, &time_taken_to_create_graph_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471 compiler::Pipeline pipeline(info());
472 pipeline.GenerateCode();
473 if (!info()->code().is_null()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474 return SetLastStatus(SUCCEEDED);
475 }
476 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100477
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 if (!isolate()->use_crankshaft() || dont_crankshaft) {
479 // Crankshaft is entirely disabled.
480 return SetLastStatus(FAILED);
481 }
482
483 Scope* scope = info()->scope();
484 if (LUnallocated::TooManyParameters(scope->num_parameters())) {
485 // Crankshaft would require too many Lithium operands.
486 return AbortOptimization(kTooManyParameters);
487 }
488
489 if (info()->is_osr() &&
490 LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
491 scope->num_stack_slots())) {
492 // Crankshaft would require too many Lithium operands.
493 return AbortOptimization(kTooManyParametersLocals);
494 }
495
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400496 if (FLAG_trace_opt) {
497 OFStream os(stdout);
498 os << "[compiling method " << Brief(*info()->closure())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 << " using Crankshaft";
500 if (info()->is_osr()) os << " OSR";
501 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400502 }
503
Ben Murdochb0fe1622011-05-05 13:52:32 +0100504 if (FLAG_trace_hydrogen) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 isolate()->GetHTracer()->TraceCompilation(info());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100506 }
507
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 // Type-check the function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 AstTyper(info()->isolate(), info()->zone(), info()->closure(),
510 info()->scope(), info()->osr_ast_id(), info()->literal())
511 .Run();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 // Optimization could have been disabled by the parser. Note that this check
514 // is only needed because the Hydrogen graph builder is missing some bailouts.
515 if (info()->shared_info()->optimization_disabled()) {
516 return AbortOptimization(
517 info()->shared_info()->disable_optimization_reason());
518 }
519
Ben Murdochda12d292016-06-02 14:46:10 +0100520 HOptimizedGraphBuilder* graph_builder =
521 (info()->is_tracking_positions() || FLAG_trace_ic)
522 ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
523 : new (info()->zone()) HOptimizedGraphBuilder(info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524
525 Timer t(this, &time_taken_to_create_graph_);
Ben Murdochda12d292016-06-02 14:46:10 +0100526 graph_ = graph_builder->CreateGraph();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527
528 if (isolate()->has_pending_exception()) {
529 return SetLastStatus(FAILED);
Steve Block1e0659c2011-05-24 12:43:12 +0100530 }
531
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 if (graph_ == NULL) return SetLastStatus(BAILED_OUT);
533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534 if (info()->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 // Dependency has changed during graph creation. Let's try again later.
536 return RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100537 }
538
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539 return SetLastStatus(SUCCEEDED);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100540}
541
542
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() {
544 DisallowHeapAllocation no_allocation;
545 DisallowHandleAllocation no_handles;
546 DisallowHandleDereference no_deref;
547 DisallowCodeDependencyChange no_dependency_change;
Ben Murdoch257744e2011-11-30 15:57:28 +0000548
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549 DCHECK(last_status() == SUCCEEDED);
550 // TODO(turbofan): Currently everything is done in the first phase.
551 if (!info()->code().is_null()) {
552 return last_status();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100553 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000554
555 Timer t(this, &time_taken_to_optimize_);
556 DCHECK(graph_ != NULL);
557 BailoutReason bailout_reason = kNoReason;
558
559 if (graph_->Optimize(&bailout_reason)) {
560 chunk_ = LChunk::NewChunk(graph_);
561 if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
562 } else if (bailout_reason != kNoReason) {
Ben Murdochda12d292016-06-02 14:46:10 +0100563 info_->AbortOptimization(bailout_reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 }
565
566 return SetLastStatus(BAILED_OUT);
Steve Block6ded16b2010-05-10 14:33:55 +0100567}
Steve Block6ded16b2010-05-10 14:33:55 +0100568
569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570namespace {
571
572void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
573 Handle<Code> code) {
574 Handle<WeakCell> cell = Code::WeakCellFor(code);
575 Heap* heap = isolate->heap();
576 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
577 dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
578 heap->AddWeakObjectToCodeDependency(object, dep);
579}
580
581
582void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
583 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
584 Isolate* const isolate = code->GetIsolate();
585 DCHECK(code->is_optimized_code());
586 std::vector<Handle<Map>> maps;
587 std::vector<Handle<HeapObject>> objects;
588 {
589 DisallowHeapAllocation no_gc;
590 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
591 RelocInfo::ModeMask(RelocInfo::CELL);
592 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
593 RelocInfo::Mode mode = it.rinfo()->rmode();
594 if (mode == RelocInfo::CELL &&
595 code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
596 objects.push_back(handle(it.rinfo()->target_cell(), isolate));
597 } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
598 code->IsWeakObjectInOptimizedCode(
599 it.rinfo()->target_object())) {
600 Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
601 isolate);
602 if (object->IsMap()) {
603 maps.push_back(Handle<Map>::cast(object));
604 } else {
605 objects.push_back(object);
606 }
607 }
608 }
609 }
610 for (Handle<Map> map : maps) {
611 if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) {
612 isolate->heap()->AddRetainedMap(map);
613 }
614 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code);
615 }
616 for (Handle<HeapObject> object : objects) {
617 AddWeakObjectToCodeDependency(isolate, object, code);
618 }
619 code->set_can_have_weak_objects(true);
620}
621
622} // namespace
623
624
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
626 DCHECK(last_status() == SUCCEEDED);
627 // TODO(turbofan): Currently everything is done in the first phase.
628 if (!info()->code().is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 info()->dependencies()->Commit(info()->code());
630 if (info()->is_deoptimization_enabled()) {
631 info()->parse_info()->context()->native_context()->AddOptimizedCode(
632 *info()->code());
633 RegisterWeakObjectsInOptimizedCode(info()->code());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400634 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000635 RecordOptimizationStats();
636 return last_status();
637 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000638
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 DCHECK(!info()->dependencies()->HasAborted());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640 DisallowCodeDependencyChange no_dependency_change;
641 DisallowJavascriptExecution no_js(isolate());
642 { // Scope for timer.
643 Timer timer(this, &time_taken_to_codegen_);
644 DCHECK(chunk_ != NULL);
645 DCHECK(graph_ != NULL);
646 // Deferred handles reference objects that were accessible during
647 // graph creation. To make sure that we don't encounter inconsistencies
648 // between graph creation and code generation, we disallow accessing
649 // objects through deferred handles during the latter, with exceptions.
650 DisallowDeferredHandleDereference no_deferred_handle_deref;
651 Handle<Code> optimized_code = chunk_->Codegen();
652 if (optimized_code.is_null()) {
653 if (info()->bailout_reason() == kNoReason) {
654 return AbortOptimization(kCodeGenerationFailed);
Leon Clarke4515c472010-02-03 11:58:03 +0000655 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656 return SetLastStatus(BAILED_OUT);
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 RegisterWeakObjectsInOptimizedCode(optimized_code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659 info()->SetCode(optimized_code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000660 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 RecordOptimizationStats();
662 // Add to the weak list of optimized code objects.
663 info()->context()->native_context()->AddOptimizedCode(*info()->code());
664 return SetLastStatus(SUCCEEDED);
Steve Blocka7e24c12009-10-30 11:49:00 +0000665}
666
667
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668void OptimizedCompileJob::RecordOptimizationStats() {
669 Handle<JSFunction> function = info()->closure();
670 if (!function->IsOptimized()) {
671 // Concurrent recompilation and OSR may race. Increment only once.
672 int opt_count = function->shared()->opt_count();
673 function->shared()->set_opt_count(opt_count + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
676 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
677 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
678 if (FLAG_trace_opt) {
679 PrintF("[optimizing ");
680 function->ShortPrint();
681 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
682 ms_codegen);
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 if (FLAG_trace_opt_stats) {
685 static double compilation_time = 0.0;
686 static int compiled_functions = 0;
687 static int code_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000688
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
690 compiled_functions++;
691 code_size += function->shared()->SourceSize();
692 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
693 compiled_functions,
694 code_size,
695 compilation_time);
696 }
697 if (FLAG_hydrogen_stats) {
698 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
699 time_taken_to_optimize_,
700 time_taken_to_codegen_);
701 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000702}
703
Ben Murdochda12d292016-06-02 14:46:10 +0100704// ----------------------------------------------------------------------------
705// Local helper methods that make up the compilation pipeline.
706
707namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +0000708
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000709// Sets the expected number of properties based on estimate from compiler.
710void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
711 int estimate) {
712 // If no properties are added in the constructor, they are more likely
713 // to be added later.
714 if (estimate == 0) estimate = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +0000715
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 // TODO(yangguo): check whether those heuristics are still up-to-date.
717 // We do not shrink objects that go into a snapshot (yet), so we adjust
718 // the estimate conservatively.
719 if (shared->GetIsolate()->serializer_enabled()) {
720 estimate += 2;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400721 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722 // Inobject slack tracking will reclaim redundant inobject space later,
723 // so we can afford to adjust the estimate generously.
724 estimate += 8;
Steve Blocka7e24c12009-10-30 11:49:00 +0000725 }
726
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727 shared->set_expected_nof_properties(estimate);
Steve Blockd0582a62009-12-15 09:54:21 +0000728}
729
Ben Murdochda12d292016-06-02 14:46:10 +0100730void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
731 BailoutReason bailout_reason) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400732 if (bailout_reason != kNoReason) {
733 shared_info->DisableOptimization(bailout_reason);
734 }
735}
736
Ben Murdochda12d292016-06-02 14:46:10 +0100737void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
738 CompilationInfo* info,
739 Handle<SharedFunctionInfo> shared) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100740 // SharedFunctionInfo is passed separately, because if CompilationInfo
741 // was created using Script object, it will not have it.
742
Ben Murdochf87a2032010-10-22 12:50:53 +0100743 // Log the code generation. If source information is available include
744 // script name and line number. Check explicitly whether logging is
745 // enabled as finding the line number is not free.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 if (info->isolate()->logger()->is_logging_code_events() ||
747 info->isolate()->cpu_profiler()->is_profiling()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748 Handle<Script> script = info->parse_info()->script();
Ben Murdochda12d292016-06-02 14:46:10 +0100749 Handle<AbstractCode> abstract_code = info->abstract_code();
750 if (abstract_code.is_identical_to(
751 info->isolate()->builtins()->CompileLazy())) {
Steve Block44f0eee2011-05-26 01:26:41 +0100752 return;
Andrei Popescu31002712010-02-23 13:46:05 +0000753 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000754 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
755 int column_num =
756 Script::GetColumnNumber(script, shared->start_position()) + 1;
757 String* script_name = script->name()->IsString()
758 ? String::cast(script->name())
759 : info->isolate()->heap()->empty_string();
760 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
761 PROFILE(info->isolate(),
Ben Murdochda12d292016-06-02 14:46:10 +0100762 CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000763 line_num, column_num));
Andrei Popescu31002712010-02-23 13:46:05 +0000764 }
765}
Andrei Popescu31002712010-02-23 13:46:05 +0000766
Ben Murdochda12d292016-06-02 14:46:10 +0100767void EnsureFeedbackVector(CompilationInfo* info) {
768 if (!info->has_shared_info()) return;
769
770 // If no type feedback vector exists, we create one now. At this point the
771 // AstNumbering pass has already run. Note the snapshot can contain outdated
772 // vectors for a different configuration, hence we also recreate a new vector
773 // when the function is not compiled (i.e. no code was serialized).
774 if (info->shared_info()->feedback_vector()->is_empty() ||
775 !info->shared_info()->is_compiled()) {
776 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New(
777 info->isolate(), info->literal()->feedback_vector_spec());
778 Handle<TypeFeedbackVector> feedback_vector =
779 TypeFeedbackVector::New(info->isolate(), feedback_metadata);
780 info->shared_info()->set_feedback_vector(*feedback_vector);
781 }
782
783 // It's very important that recompiles do not alter the structure of the type
784 // feedback vector. Verify that the structure fits the function literal.
785 CHECK(!info->shared_info()->feedback_vector()->metadata()->SpecDiffersFrom(
786 info->literal()->feedback_vector_spec()));
787}
788
789bool CompileUnoptimizedCode(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791 if (!Compiler::Analyze(info->parse_info()) ||
Ben Murdochda12d292016-06-02 14:46:10 +0100792 !(EnsureFeedbackVector(info), FullCodeGenerator::MakeCode(info))) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 Isolate* isolate = info->isolate();
794 if (!isolate->has_pending_exception()) isolate->StackOverflow();
795 return false;
796 }
797 return true;
798}
799
Ben Murdochda12d292016-06-02 14:46:10 +0100800bool UseIgnition(CompilationInfo* info) {
801 // TODO(4681): Generator functions are not yet supported.
802 if (info->shared_info()->is_generator()) {
803 return false;
804 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805
Ben Murdochda12d292016-06-02 14:46:10 +0100806 // TODO(4681): Resuming a suspended frame is not supported.
807 if (info->shared_info()->HasBuiltinFunctionId() &&
808 (info->shared_info()->builtin_function_id() == kGeneratorObjectNext ||
809 info->shared_info()->builtin_function_id() == kGeneratorObjectReturn ||
810 info->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811 return false;
812 }
813
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000814 // Checks whether top level functions should be passed by the filter.
Ben Murdochda12d292016-06-02 14:46:10 +0100815 if (info->shared_info()->is_toplevel()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 Vector<const char> filter = CStrVector(FLAG_ignition_filter);
817 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
818 }
819
820 // Finally respect the filter.
Ben Murdochda12d292016-06-02 14:46:10 +0100821 return info->shared_info()->PassesFilter(FLAG_ignition_filter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822}
823
Ben Murdochda12d292016-06-02 14:46:10 +0100824int CodeAndMetadataSize(CompilationInfo* info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100825 int size = 0;
826 if (info->has_bytecode_array()) {
827 Handle<BytecodeArray> bytecode_array = info->bytecode_array();
828 size += bytecode_array->BytecodeArraySize();
829 size += bytecode_array->constant_pool()->Size();
830 size += bytecode_array->handler_table()->Size();
831 size += bytecode_array->source_position_table()->Size();
832 } else {
833 Handle<Code> code = info->code();
834 size += code->CodeSize();
835 size += code->relocation_info()->Size();
836 size += code->deoptimization_data()->Size();
837 size += code->handler_table()->Size();
838 }
839 return size;
840}
841
Ben Murdochda12d292016-06-02 14:46:10 +0100842bool GenerateBaselineCode(CompilationInfo* info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100843 bool success;
Ben Murdochda12d292016-06-02 14:46:10 +0100844 EnsureFeedbackVector(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845 if (FLAG_ignition && UseIgnition(info)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100846 success = interpreter::Interpreter::MakeBytecode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000847 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100848 success = FullCodeGenerator::MakeCode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100850 if (success) {
851 Isolate* isolate = info->isolate();
852 Counters* counters = isolate->counters();
853 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info));
854 counters->total_baseline_compile_count()->Increment(1);
855 }
856 return success;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857}
858
Ben Murdochda12d292016-06-02 14:46:10 +0100859bool CompileBaselineCode(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
861 if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000862 Isolate* isolate = info->isolate();
863 if (!isolate->has_pending_exception()) isolate->StackOverflow();
864 return false;
865 }
866 return true;
867}
868
Ben Murdochda12d292016-06-02 14:46:10 +0100869void InstallBaselineCompilationResult(CompilationInfo* info,
870 Handle<SharedFunctionInfo> shared,
871 Handle<ScopeInfo> scope_info) {
872 // Assert that we are not overwriting (possibly patched) debug code.
873 DCHECK(!shared->HasDebugCode());
874 DCHECK(!info->code().is_null());
875 shared->ReplaceCode(*info->code());
876 shared->set_scope_info(*scope_info);
877 if (info->has_bytecode_array()) {
878 DCHECK(!shared->HasBytecodeArray()); // Only compiled once.
879 shared->set_bytecode_array(*info->bytecode_array());
880 }
881}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882
Ben Murdochda12d292016-06-02 14:46:10 +0100883MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCodeCommon(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884 CompilationInfo* info) {
885 VMState<COMPILER> state(info->isolate());
886 PostponeInterruptsScope postpone(info->isolate());
887
888 // Parse and update CompilationInfo with the results.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000891 FunctionLiteral* lit = info->literal();
892 DCHECK_EQ(shared->language_mode(), lit->language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400894 MaybeDisableOptimization(shared, lit->dont_optimize_reason());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 // Compile either unoptimized code or bytecode for the interpreter.
897 if (!CompileBaselineCode(info)) return MaybeHandle<Code>();
Ben Murdochda12d292016-06-02 14:46:10 +0100898 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899
900 // Update the shared function info with the scope info. Allocating the
901 // ScopeInfo object may cause a GC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 Handle<ScopeInfo> scope_info =
903 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000904
Ben Murdochda12d292016-06-02 14:46:10 +0100905 // Install compilation result on the shared function info
906 InstallBaselineCompilationResult(info, shared, scope_info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907
908 return info->code();
909}
910
Ben Murdochda12d292016-06-02 14:46:10 +0100911MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000912 Handle<JSFunction> function, BailoutId osr_ast_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000913 Handle<SharedFunctionInfo> shared(function->shared());
914 DisallowHeapAllocation no_gc;
915 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
916 function->context()->native_context(), osr_ast_id);
917 if (cached.code != nullptr) {
918 // Caching of optimized code enabled and optimized code found.
919 if (cached.literals != nullptr) function->set_literals(cached.literals);
920 DCHECK(!cached.code->marked_for_deoptimization());
921 DCHECK(function->shared()->is_compiled());
922 return Handle<Code>(cached.code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 }
924 return MaybeHandle<Code>();
925}
926
Ben Murdochda12d292016-06-02 14:46:10 +0100927void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000928 Handle<Code> code = info->code();
929 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
930
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 // Function context specialization folds-in the function context,
932 // so no sharing can occur.
933 if (info->is_function_context_specializing()) return;
934 // Frame specialization implies function context specialization.
935 DCHECK(!info->is_frame_specializing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 // Cache optimized context-specific code.
938 Handle<JSFunction> function = info->closure();
939 Handle<SharedFunctionInfo> shared(function->shared());
940 Handle<LiteralsArray> literals(function->literals());
941 Handle<Context> native_context(function->context()->native_context());
942 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
943 literals, info->osr_ast_id());
944
945 // Do not cache (native) context-independent code compiled for OSR.
946 if (code->is_turbofanned() && info->is_osr()) return;
947
948 // Cache optimized (native) context-independent code.
949 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
950 !info->is_native_context_specializing()) {
951 DCHECK(!info->is_function_context_specializing());
952 DCHECK(info->osr_ast_id().IsNone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000954 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955 }
956}
957
Ben Murdochda12d292016-06-02 14:46:10 +0100958bool Renumber(ParseInfo* parse_info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
960 parse_info->literal())) {
961 return false;
962 }
963 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info();
964 if (!shared_info.is_null()) {
965 FunctionLiteral* lit = parse_info->literal();
966 shared_info->set_ast_node_count(lit->ast_node_count());
967 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason());
Ben Murdochda12d292016-06-02 14:46:10 +0100968 shared_info->set_dont_crankshaft(
969 shared_info->dont_crankshaft() ||
970 (lit->flags() & AstProperties::kDontCrankshaft));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400971 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000972 return true;
973}
974
Ben Murdochda12d292016-06-02 14:46:10 +0100975bool GetOptimizedCodeNow(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 Isolate* isolate = info->isolate();
977 CanonicalHandleScope canonical(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100978 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
979 TRACE_EVENT0("v8", "V8.OptimizeCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
982
983 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100984 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000985
986 OptimizedCompileJob job(info);
987 if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED ||
988 job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED ||
989 job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) {
990 if (FLAG_trace_opt) {
991 PrintF("[aborted optimizing ");
992 info->closure()->ShortPrint();
993 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
994 }
995 return false;
996 }
997
998 // Success!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 InsertCodeIntoOptimizedCodeMap(info);
1001 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info,
1002 info->shared_info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003 return true;
1004}
1005
Ben Murdochda12d292016-06-02 14:46:10 +01001006bool GetOptimizedCodeLater(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007 Isolate* isolate = info->isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 CanonicalHandleScope canonical(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
1010 TRACE_EVENT0("v8", "V8.OptimizeCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011
1012 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013 if (FLAG_trace_concurrent_recompilation) {
1014 PrintF(" ** Compilation queue full, will retry optimizing ");
1015 info->closure()->ShortPrint();
1016 PrintF(" later.\n");
1017 }
1018 return false;
1019 }
1020
1021 CompilationHandleScope handle_scope(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
1023
1024 // Reopen handles in the new CompilationHandleScope.
1025 info->ReopenHandlesInNewHandleScope();
1026 info->parse_info()->ReopenHandlesInNewHandleScope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027
1028 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001029 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030
1031 OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info);
1032 OptimizedCompileJob::Status status = job->CreateGraph();
1033 if (status != OptimizedCompileJob::SUCCEEDED) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035
1036 if (FLAG_trace_concurrent_recompilation) {
1037 PrintF(" ** Queued ");
1038 info->closure()->ShortPrint();
1039 if (info->is_osr()) {
1040 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt());
1041 } else {
1042 PrintF(" for concurrent optimization.\n");
1043 }
1044 }
1045 return true;
1046}
1047
Ben Murdochda12d292016-06-02 14:46:10 +01001048MaybeHandle<Code> GetUnoptimizedCode(Handle<JSFunction> function) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001049 DCHECK(!function->GetIsolate()->has_pending_exception());
1050 DCHECK(!function->is_compiled());
1051 if (function->shared()->is_compiled()) {
1052 return Handle<Code>(function->shared()->code());
1053 }
1054
1055 CompilationInfoWithZone info(function);
1056 Handle<Code> result;
1057 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result,
1058 GetUnoptimizedCodeCommon(&info),
1059 Code);
1060 return result;
1061}
1062
Ben Murdochda12d292016-06-02 14:46:10 +01001063MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
1064 Compiler::ConcurrencyMode mode,
1065 BailoutId osr_ast_id = BailoutId::None(),
1066 JavaScriptFrame* osr_frame = nullptr) {
1067 Isolate* isolate = function->GetIsolate();
1068 Handle<SharedFunctionInfo> shared(function->shared(), isolate);
1069 if (shared->HasDebugInfo()) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001070
Ben Murdochda12d292016-06-02 14:46:10 +01001071 Handle<Code> cached_code;
1072 if (GetCodeFromOptimizedCodeMap(function, osr_ast_id)
1073 .ToHandle(&cached_code)) {
1074 if (FLAG_trace_opt) {
1075 PrintF("[found optimized code for ");
1076 function->ShortPrint();
1077 if (!osr_ast_id.IsNone()) {
1078 PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
1079 }
1080 PrintF("]\n");
1081 }
1082 return cached_code;
1083 }
1084
1085 DCHECK(AllowCompilation::IsAllowed(isolate));
1086
1087 if (shared->is_compiled()) {
1088 shared->code()->set_profiler_ticks(0);
1089 }
1090
1091 // TODO(mstarzinger): We cannot properly deserialize a scope chain containing
1092 // an eval scope and hence would fail at parsing the eval source again.
1093 if (shared->disable_optimization_reason() == kEval) {
1094 return MaybeHandle<Code>();
1095 }
1096
1097 // TODO(mstarzinger): We cannot properly deserialize a scope chain for the
1098 // builtin context, hence Genesis::InstallExperimentalNatives would fail.
1099 if (shared->is_toplevel() && isolate->bootstrapper()->IsActive()) {
1100 return MaybeHandle<Code>();
1101 }
1102
1103 base::SmartPointer<CompilationInfo> info(
1104 new CompilationInfoWithZone(function));
1105 VMState<COMPILER> state(isolate);
1106 DCHECK(!isolate->has_pending_exception());
1107 PostponeInterruptsScope postpone(isolate);
1108
1109 info->SetOptimizingForOsr(osr_ast_id);
1110
1111 if (mode == Compiler::CONCURRENT) {
1112 if (GetOptimizedCodeLater(info.get())) {
1113 info.Detach(); // The background recompile job owns this now.
1114 return isolate->builtins()->InOptimizationQueue();
1115 }
1116 } else {
1117 info->set_osr_frame(osr_frame);
1118 if (GetOptimizedCodeNow(info.get())) return info->code();
1119 }
1120
1121 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
1122 return MaybeHandle<Code>();
1123}
1124
1125MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001126 Isolate* isolate = function->GetIsolate();
1127 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128 DCHECK(!function->is_compiled());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001129 TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1130 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001132 // If the debugger is active, do not compile with turbofan unless we can
1133 // deopt from turbofan code.
1134 if (FLAG_turbo_asm && function->shared()->asm_function() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001135 (FLAG_turbo_asm_deoptimization || !isolate->debug()->is_active()) &&
1136 !FLAG_turbo_osr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 CompilationInfoWithZone info(function);
1138
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001139 VMState<COMPILER> state(isolate);
1140 PostponeInterruptsScope postpone(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141
Ben Murdoch097c5b22016-05-18 11:27:45 +01001142 info.SetOptimizing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001143
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001144 if (GetOptimizedCodeNow(&info)) {
1145 DCHECK(function->shared()->is_compiled());
1146 return info.code();
1147 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 // We have failed compilation. If there was an exception clear it so that
1149 // we can compile unoptimized code.
1150 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001151 }
1152
1153 if (function->shared()->is_compiled()) {
1154 return Handle<Code>(function->shared()->code());
1155 }
1156
1157 CompilationInfoWithZone info(function);
1158 Handle<Code> result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001159 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCodeCommon(&info),
1160 Code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 if (FLAG_always_opt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001163 Handle<Code> opt_code;
Ben Murdochda12d292016-06-02 14:46:10 +01001164 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001165 .ToHandle(&opt_code)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001166 result = opt_code;
1167 }
1168 }
1169
1170 return result;
1171}
1172
1173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174bool CompileEvalForDebugging(Handle<JSFunction> function,
1175 Handle<SharedFunctionInfo> shared) {
1176 Handle<Script> script(Script::cast(shared->script()));
1177 Handle<Context> context(function->context());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001178
Ben Murdochda12d292016-06-02 14:46:10 +01001179 Zone zone(function->GetIsolate()->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 ParseInfo parse_info(&zone, script);
1181 CompilationInfo info(&parse_info);
1182 Isolate* isolate = info.isolate();
1183
1184 parse_info.set_eval();
1185 parse_info.set_context(context);
1186 if (context->IsNativeContext()) parse_info.set_global();
1187 parse_info.set_toplevel();
1188 parse_info.set_allow_lazy_parsing(false);
1189 parse_info.set_language_mode(shared->language_mode());
1190 parse_info.set_parse_restriction(NO_PARSE_RESTRICTION);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 info.MarkAsDebug();
1192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001193 VMState<COMPILER> state(info.isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 if (!Parser::ParseStatic(&parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 isolate->clear_pending_exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001197 return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001198 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199
1200 FunctionLiteral* lit = parse_info.literal();
1201 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
1202
1203 if (!CompileUnoptimizedCode(&info)) {
1204 isolate->clear_pending_exception();
1205 return false;
1206 }
1207 shared->ReplaceCode(*info.code());
1208 return true;
1209}
1210
1211
1212bool CompileForDebugging(CompilationInfo* info) {
1213 info->MarkAsDebug();
1214 if (GetUnoptimizedCodeCommon(info).is_null()) {
1215 info->isolate()->clear_pending_exception();
1216 return false;
1217 }
1218 return true;
1219}
1220
Ben Murdochda12d292016-06-02 14:46:10 +01001221inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001222 return shared->is_toplevel() && shared->script()->IsScript() &&
1223 Script::cast(shared->script())->compilation_type() ==
1224 Script::COMPILATION_TYPE_EVAL;
1225}
1226
Ben Murdochda12d292016-06-02 14:46:10 +01001227Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
1228 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) {
1229 Handle<Code> code = isolate->builtins()->CompileLazy();
1230 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate));
1231 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo(
1232 literal->name(), literal->materialized_literal_count(), literal->kind(),
1233 code, scope_info);
1234 SharedFunctionInfo::InitFromFunctionLiteral(result, literal);
1235 SharedFunctionInfo::SetScript(result, script);
1236 return result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237}
1238
Ben Murdochda12d292016-06-02 14:46:10 +01001239Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001240 Isolate* isolate = info->isolate();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001241 TimerEventScope<TimerEventCompileCode> timer(isolate);
1242 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243 PostponeInterruptsScope postpone(isolate);
1244 DCHECK(!isolate->native_context().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 ParseInfo* parse_info = info->parse_info();
1246 Handle<Script> script = parse_info->script();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001247
1248 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
1249 FixedArray* array = isolate->native_context()->embedder_data();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 script->set_context_data(array->get(v8::Context::kDebugIdIndex));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251
1252 isolate->debug()->OnBeforeCompile(script);
1253
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 DCHECK(parse_info->is_eval() || parse_info->is_global() ||
1255 parse_info->is_module());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001257 parse_info->set_toplevel();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001259 Handle<SharedFunctionInfo> result;
1260
1261 { VMState<COMPILER> state(info->isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001262 if (parse_info->literal() == NULL) {
1263 // Parse the script if needed (if it's already parsed, literal() is
1264 // non-NULL). If compiling for debugging, we may eagerly compile inner
1265 // functions, so do not parse lazily in that case.
1266 ScriptCompiler::CompileOptions options = parse_info->compile_options();
1267 bool parse_allow_lazy = (options == ScriptCompiler::kConsumeParserCache ||
1268 String::cast(script->source())->length() >
1269 FLAG_min_preparse_length) &&
1270 !info->is_debug();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271
Ben Murdochda12d292016-06-02 14:46:10 +01001272 // Consider parsing eagerly when targeting the code cache.
1273 parse_allow_lazy &= !(FLAG_serialize_eager && info->will_serialize());
1274
1275 // Consider parsing eagerly when targeting Ignition.
1276 parse_allow_lazy &= !(FLAG_ignition && FLAG_ignition_eager &&
1277 !isolate->serializer_enabled());
1278
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001279 parse_info->set_allow_lazy_parsing(parse_allow_lazy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001280 if (!parse_allow_lazy &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001281 (options == ScriptCompiler::kProduceParserCache ||
1282 options == ScriptCompiler::kConsumeParserCache)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 // We are going to parse eagerly, but we either 1) have cached data
1284 // produced by lazy parsing or 2) are asked to generate cached data.
1285 // Eager parsing cannot benefit from cached data, and producing cached
1286 // data while parsing eagerly is not implemented.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287 parse_info->set_cached_data(nullptr);
1288 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 if (!Parser::ParseStatic(parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 return Handle<SharedFunctionInfo>::null();
1292 }
1293 }
1294
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001295 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing());
1296
1297 info->MarkAsFirstCompile();
1298
1299 FunctionLiteral* lit = parse_info->literal();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001300 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
1301
1302 // Measure how long it takes to do the compilation; only take the
1303 // rest of the function into account to avoid overlap with the
1304 // parsing statistics.
1305 HistogramTimer* rate = info->is_eval()
1306 ? info->isolate()->counters()->compile_eval()
1307 : info->isolate()->counters()->compile();
1308 HistogramTimerScope timer(rate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001309 TRACE_EVENT0("v8", info->is_eval() ? "V8.CompileEval" : "V8.Compile");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001310
Ben Murdochda12d292016-06-02 14:46:10 +01001311 // Allocate a shared function info object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001312 DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Ben Murdochda12d292016-06-02 14:46:10 +01001313 result = NewSharedFunctionInfoForLiteral(isolate, lit, script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001314 result->set_is_toplevel(true);
1315 if (info->is_eval()) {
1316 // Eval scripts cannot be (re-)compiled without context.
1317 result->set_allows_lazy_compilation_without_context(false);
1318 }
Ben Murdochda12d292016-06-02 14:46:10 +01001319 parse_info->set_shared_info(result);
1320
1321 // Compile the code.
1322 if (!CompileBaselineCode(info)) {
1323 return Handle<SharedFunctionInfo>::null();
1324 }
1325
1326 // Install compilation result on the shared function info
1327 Handle<ScopeInfo> scope_info =
1328 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
1329 InstallBaselineCompilationResult(info, result, scope_info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001331 Handle<String> script_name =
1332 script->name()->IsString()
1333 ? Handle<String>(String::cast(script->name()))
1334 : isolate->factory()->empty_string();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 Logger::LogEventsAndTags log_tag = info->is_eval()
1336 ? Logger::EVAL_TAG
1337 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
1338
Ben Murdochda12d292016-06-02 14:46:10 +01001339 PROFILE(isolate, CodeCreateEvent(log_tag, *info->abstract_code(), *result,
1340 info, *script_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341
1342 // Hint to the runtime system used when allocating space for initial
1343 // property space by setting the expected number of properties for
1344 // the instances of the function.
1345 SetExpectedNofPropertiesFromEstimate(result,
1346 lit->expected_property_count());
1347
1348 if (!script.is_null())
1349 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1350
1351 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
1352 }
1353
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354 return result;
1355}
1356
Ben Murdochda12d292016-06-02 14:46:10 +01001357} // namespace
1358
1359// ----------------------------------------------------------------------------
1360// Implementation of Compiler
1361
1362bool Compiler::Analyze(ParseInfo* info) {
1363 DCHECK_NOT_NULL(info->literal());
1364 if (!Rewriter::Rewrite(info)) return false;
1365 if (!Scope::Analyze(info)) return false;
1366 if (!Renumber(info)) return false;
1367 DCHECK_NOT_NULL(info->scope());
1368 return true;
1369}
1370
1371bool Compiler::ParseAndAnalyze(ParseInfo* info) {
1372 if (!Parser::ParseStatic(info)) return false;
1373 return Compiler::Analyze(info);
1374}
1375
1376bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
1377 if (function->is_compiled()) return true;
1378 MaybeHandle<Code> maybe_code = GetLazyCode(function);
1379 Handle<Code> code;
1380 if (!maybe_code.ToHandle(&code)) {
1381 if (flag == CLEAR_EXCEPTION) {
1382 function->GetIsolate()->clear_pending_exception();
1383 }
1384 return false;
1385 }
1386 DCHECK(code->IsJavaScriptCode());
1387 function->ReplaceCode(*code);
1388 DCHECK(function->is_compiled());
1389 return true;
1390}
1391
1392bool Compiler::CompileOptimized(Handle<JSFunction> function,
1393 ConcurrencyMode mode) {
1394 Handle<Code> code;
1395 if (GetOptimizedCode(function, mode).ToHandle(&code)) {
1396 // Optimization succeeded, return optimized code.
1397 function->ReplaceCode(*code);
1398 } else {
1399 // Optimization failed, get unoptimized code.
1400 Isolate* isolate = function->GetIsolate();
1401 if (isolate->has_pending_exception()) { // Possible stack overflow.
1402 return false;
1403 }
1404 code = Handle<Code>(function->shared()->code(), isolate);
1405 if (code->kind() != Code::FUNCTION &&
1406 code->kind() != Code::OPTIMIZED_FUNCTION) {
1407 if (!GetUnoptimizedCode(function).ToHandle(&code)) {
1408 return false;
1409 }
1410 }
1411 function->ReplaceCode(*code);
1412 }
1413
1414 DCHECK(function->code()->kind() == Code::FUNCTION ||
1415 function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
1416 (function->code()->is_interpreter_entry_trampoline() &&
1417 function->shared()->HasBytecodeArray()) ||
1418 function->IsInOptimizationQueue());
1419 return true;
1420}
1421
1422bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
1423 Handle<SharedFunctionInfo> shared(function->shared());
1424 if (IsEvalToplevel(shared)) {
1425 return CompileEvalForDebugging(function, shared);
1426 } else {
1427 CompilationInfoWithZone info(function);
1428 return CompileForDebugging(&info);
1429 }
1430}
1431
1432bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1433 DCHECK(shared->allows_lazy_compilation_without_context());
1434 DCHECK(!IsEvalToplevel(shared));
1435 Zone zone(shared->GetIsolate()->allocator());
1436 ParseInfo parse_info(&zone, shared);
1437 CompilationInfo info(&parse_info);
1438 return CompileForDebugging(&info);
1439}
1440
1441// TODO(turbofan): In the future, unoptimized code with deopt support could
1442// be generated lazily once deopt is triggered.
1443bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
1444 DCHECK_NOT_NULL(info->literal());
1445 DCHECK(info->has_scope());
1446 Handle<SharedFunctionInfo> shared = info->shared_info();
1447 if (!shared->has_deoptimization_support()) {
1448 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
1449 CompilationInfoWithZone unoptimized(info->closure());
1450 // Note that we use the same AST that we will use for generating the
1451 // optimized code.
1452 ParseInfo* parse_info = unoptimized.parse_info();
1453 parse_info->set_literal(info->literal());
1454 parse_info->set_scope(info->scope());
1455 parse_info->set_context(info->context());
1456 unoptimized.EnableDeoptimizationSupport();
1457 // If the current code has reloc info for serialization, also include
1458 // reloc info for serialization for the new code, so that deopt support
1459 // can be added without losing IC state.
1460 if (shared->code()->kind() == Code::FUNCTION &&
1461 shared->code()->has_reloc_info_for_serialization()) {
1462 unoptimized.PrepareForSerializing();
1463 }
1464 EnsureFeedbackVector(&unoptimized);
1465 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1466
1467 shared->EnableDeoptimizationSupport(*unoptimized.code());
1468
1469 info->MarkAsCompiled();
1470
1471 // The scope info might not have been set if a lazily compiled
1472 // function is inlined before being called for the first time.
1473 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1474 Handle<ScopeInfo> target_scope_info =
1475 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
1476 shared->set_scope_info(*target_scope_info);
1477 }
1478
1479 // The existing unoptimized code was replaced with the new one.
1480 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
1481 }
1482 return true;
1483}
1484
1485void Compiler::CompileForLiveEdit(Handle<Script> script) {
1486 // TODO(635): support extensions.
1487 Zone zone(script->GetIsolate()->allocator());
1488 ParseInfo parse_info(&zone, script);
1489 CompilationInfo info(&parse_info);
1490 PostponeInterruptsScope postpone(info.isolate());
1491 VMState<COMPILER> state(info.isolate());
1492
1493 // Get rid of old list of shared function infos.
1494 info.MarkAsFirstCompile();
1495 info.MarkAsDebug();
1496 info.parse_info()->set_global();
1497 if (!Parser::ParseStatic(info.parse_info())) return;
1498
1499 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
1500 if (!CompileUnoptimizedCode(&info)) return;
1501 tracker.RecordRootFunctionInfo(info.code());
1502}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503
1504MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1505 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001506 Handle<Context> context, LanguageMode language_mode,
1507 ParseRestriction restriction, int line_offset, int column_offset,
1508 Handle<Object> script_name, ScriptOriginOptions options) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001509 Isolate* isolate = source->GetIsolate();
1510 int source_length = source->length();
1511 isolate->counters()->total_eval_size()->Increment(source_length);
1512 isolate->counters()->total_compile_size()->Increment(source_length);
1513
1514 CompilationCache* compilation_cache = isolate->compilation_cache();
1515 MaybeHandle<SharedFunctionInfo> maybe_shared_info =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001516 compilation_cache->LookupEval(source, outer_info, context, language_mode,
1517 line_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001518 Handle<SharedFunctionInfo> shared_info;
1519
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001520 Handle<Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521 if (!maybe_shared_info.ToHandle(&shared_info)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001522 script = isolate->factory()->NewScript(source);
1523 if (!script_name.is_null()) {
1524 script->set_name(*script_name);
1525 script->set_line_offset(line_offset);
1526 script->set_column_offset(column_offset);
1527 }
1528 script->set_origin_options(options);
Ben Murdochda12d292016-06-02 14:46:10 +01001529 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001530 ParseInfo parse_info(&zone, script);
1531 CompilationInfo info(&parse_info);
1532 parse_info.set_eval();
1533 if (context->IsNativeContext()) parse_info.set_global();
1534 parse_info.set_language_mode(language_mode);
1535 parse_info.set_parse_restriction(restriction);
1536 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001537
1538 Debug::RecordEvalCaller(script);
1539
1540 shared_info = CompileToplevel(&info);
1541
1542 if (shared_info.is_null()) {
1543 return MaybeHandle<JSFunction>();
1544 } else {
1545 // Explicitly disable optimization for eval code. We're not yet prepared
1546 // to handle eval-code in the optimizing compiler.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001547 if (restriction != ONLY_SINGLE_FUNCTION_LITERAL) {
1548 shared_info->DisableOptimization(kEval);
1549 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550
1551 // If caller is strict mode, the result must be in strict mode as well.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 DCHECK(is_sloppy(language_mode) ||
1553 is_strict(shared_info->language_mode()));
1554 compilation_cache->PutEval(source, outer_info, context, shared_info,
1555 line_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001556 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001557 }
1558
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559 Handle<JSFunction> result =
1560 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1561 shared_info, context, NOT_TENURED);
1562
1563 // OnAfterCompile has to be called after we create the JSFunction, which we
1564 // may require to recompile the eval for debugging, if we find a function
1565 // that contains break points in the eval script.
1566 isolate->debug()->OnAfterCompile(script);
1567
1568 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569}
1570
Ben Murdochda12d292016-06-02 14:46:10 +01001571Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001572 Handle<String> source, Handle<Object> script_name, int line_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573 int column_offset, ScriptOriginOptions resource_options,
1574 Handle<Object> source_map_url, Handle<Context> context,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001575 v8::Extension* extension, ScriptData** cached_data,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
1577 bool is_module) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001578 Isolate* isolate = source->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001579 if (compile_options == ScriptCompiler::kNoCompileOptions) {
1580 cached_data = NULL;
1581 } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1582 compile_options == ScriptCompiler::kProduceCodeCache) {
1583 DCHECK(cached_data && !*cached_data);
1584 DCHECK(extension == NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001585 DCHECK(!isolate->debug()->is_loaded());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001586 } else {
1587 DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1588 compile_options == ScriptCompiler::kConsumeCodeCache);
1589 DCHECK(cached_data && *cached_data);
1590 DCHECK(extension == NULL);
1591 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001592 int source_length = source->length();
1593 isolate->counters()->total_load_size()->Increment(source_length);
1594 isolate->counters()->total_compile_size()->Increment(source_length);
1595
Ben Murdochda12d292016-06-02 14:46:10 +01001596 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001597 CompilationCache* compilation_cache = isolate->compilation_cache();
1598
1599 // Do a lookup in the compilation cache but not for extensions.
1600 MaybeHandle<SharedFunctionInfo> maybe_result;
1601 Handle<SharedFunctionInfo> result;
1602 if (extension == NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001603 // First check per-isolate compilation cache.
1604 maybe_result = compilation_cache->LookupScript(
1605 source, script_name, line_offset, column_offset, resource_options,
1606 context, language_mode);
1607 if (maybe_result.is_null() && FLAG_serialize_toplevel &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001608 compile_options == ScriptCompiler::kConsumeCodeCache &&
1609 !isolate->debug()->is_loaded()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001610 // Then check cached code provided by embedder.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001611 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001612 TRACE_EVENT0("v8", "V8.CompileDeserialize");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001613 Handle<SharedFunctionInfo> result;
1614 if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1615 .ToHandle(&result)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 // Promote to per-isolate compilation cache.
1617 compilation_cache->PutScript(source, context, language_mode, result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001618 return result;
1619 }
1620 // Deserializer failed. Fall through to compile.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621 }
1622 }
1623
1624 base::ElapsedTimer timer;
1625 if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
1626 compile_options == ScriptCompiler::kProduceCodeCache) {
1627 timer.Start();
1628 }
1629
1630 if (!maybe_result.ToHandle(&result)) {
1631 // No cache entry found. Compile the script.
1632
1633 // Create a script object describing the script to be compiled.
1634 Handle<Script> script = isolate->factory()->NewScript(source);
1635 if (natives == NATIVES_CODE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001636 script->set_type(Script::TYPE_NATIVE);
1637 script->set_hide_source(true);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001638 } else if (natives == EXTENSION_CODE) {
1639 script->set_type(Script::TYPE_EXTENSION);
1640 script->set_hide_source(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641 }
1642 if (!script_name.is_null()) {
1643 script->set_name(*script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001644 script->set_line_offset(line_offset);
1645 script->set_column_offset(column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001646 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001647 script->set_origin_options(resource_options);
1648 if (!source_map_url.is_null()) {
1649 script->set_source_mapping_url(*source_map_url);
1650 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001651
1652 // Compile the function and add it to the cache.
Ben Murdochda12d292016-06-02 14:46:10 +01001653 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001654 ParseInfo parse_info(&zone, script);
1655 CompilationInfo info(&parse_info);
Ben Murdochda12d292016-06-02 14:46:10 +01001656 if (is_module) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001657 parse_info.set_module();
1658 } else {
1659 parse_info.set_global();
1660 }
1661 if (compile_options != ScriptCompiler::kNoCompileOptions) {
1662 parse_info.set_cached_data(cached_data);
1663 }
1664 parse_info.set_compile_options(compile_options);
1665 parse_info.set_extension(extension);
1666 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001667 if (FLAG_serialize_toplevel &&
1668 compile_options == ScriptCompiler::kProduceCodeCache) {
1669 info.PrepareForSerializing();
1670 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001671
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001672 parse_info.set_language_mode(
1673 static_cast<LanguageMode>(info.language_mode() | language_mode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001674 result = CompileToplevel(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675 if (extension == NULL && !result.is_null()) {
1676 compilation_cache->PutScript(source, context, language_mode, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001677 if (FLAG_serialize_toplevel &&
1678 compile_options == ScriptCompiler::kProduceCodeCache) {
1679 HistogramTimerScope histogram_timer(
1680 isolate->counters()->compile_serialize());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001681 TRACE_EVENT0("v8", "V8.CompileSerialize");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001682 *cached_data = CodeSerializer::Serialize(isolate, result, source);
1683 if (FLAG_profile_deserialization) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001684 PrintF("[Compiling and serializing took %0.3f ms]\n",
1685 timer.Elapsed().InMillisecondsF());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001686 }
1687 }
1688 }
1689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001690 if (result.is_null()) {
1691 isolate->ReportPendingMessages();
1692 } else {
1693 isolate->debug()->OnAfterCompile(script);
1694 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001695 } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1696 result->ResetForNewContext(isolate->heap()->global_ic_age());
1697 }
1698 return result;
1699}
1700
Ben Murdochda12d292016-06-02 14:46:10 +01001701Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001702 Handle<Script> script, ParseInfo* parse_info, int source_length) {
1703 Isolate* isolate = script->GetIsolate();
1704 // TODO(titzer): increment the counters in caller.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001705 isolate->counters()->total_load_size()->Increment(source_length);
1706 isolate->counters()->total_compile_size()->Increment(source_length);
1707
Ben Murdochda12d292016-06-02 14:46:10 +01001708 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001709 parse_info->set_language_mode(
1710 static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1711
1712 CompilationInfo compile_info(parse_info);
1713
1714 // The source was parsed lazily, so compiling for debugging is not possible.
1715 DCHECK(!compile_info.is_debug());
1716
1717 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
1718 if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
1719 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001720}
1721
1722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001723Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 FunctionLiteral* literal, Handle<Script> script,
1725 CompilationInfo* outer_info) {
1726 // Precondition: code has been parsed and scopes have been analyzed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001727 Isolate* isolate = outer_info->isolate();
1728 MaybeHandle<SharedFunctionInfo> maybe_existing;
1729 if (outer_info->is_first_compile()) {
1730 // On the first compile, there are no existing shared function info for
1731 // inner functions yet, so do not try to find them. All bets are off for
1732 // live edit though.
Ben Murdochda12d292016-06-02 14:46:10 +01001733 SLOW_DCHECK(script->FindSharedFunctionInfo(literal).is_null() ||
1734 isolate->debug()->live_edit_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001735 } else {
1736 maybe_existing = script->FindSharedFunctionInfo(literal);
1737 }
1738 // We found an existing shared function info. If it's already compiled,
1739 // don't worry about compiling it, and simply return it. If it's not yet
1740 // compiled, continue to decide whether to eagerly compile.
1741 // Carry on if we are compiling eager to obtain code for debugging,
1742 // unless we already have code with debut break slots.
1743 Handle<SharedFunctionInfo> existing;
1744 if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) {
1745 if (!outer_info->is_debug() || existing->HasDebugCode()) {
1746 return existing;
1747 }
1748 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749
Ben Murdochda12d292016-06-02 14:46:10 +01001750 // Allocate a shared function info object.
1751 Handle<SharedFunctionInfo> result;
1752 if (!maybe_existing.ToHandle(&result)) {
1753 result = NewSharedFunctionInfoForLiteral(isolate, literal, script);
1754 result->set_is_toplevel(false);
1755 }
1756
1757 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001758 ParseInfo parse_info(&zone, script);
1759 CompilationInfo info(&parse_info);
1760 parse_info.set_literal(literal);
Ben Murdochda12d292016-06-02 14:46:10 +01001761 parse_info.set_shared_info(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001762 parse_info.set_scope(literal->scope());
1763 parse_info.set_language_mode(literal->scope()->language_mode());
1764 if (outer_info->will_serialize()) info.PrepareForSerializing();
1765 if (outer_info->is_first_compile()) info.MarkAsFirstCompile();
1766 if (outer_info->is_debug()) info.MarkAsDebug();
1767
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001768 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
1769 // Determine if the function can be lazily compiled. This is necessary to
1770 // allow some of our builtin JS files to be lazily compiled. These
1771 // builtins cannot be handled lazily by the parser, since we have to know
1772 // if a function uses the special natives syntax, which is something the
1773 // parser records.
1774 // If the debugger requests compilation for break points, we cannot be
1775 // aggressive about lazy compilation, because it might trigger compilation
1776 // of functions without an outer context when setting a breakpoint through
1777 // Debug::FindSharedFunctionInfoInScript.
1778 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001779 // Compile eagerly for live edit. When compiling debug code, eagerly compile
1780 // unless we can lazily compile without the context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001781 bool allow_lazy = literal->AllowsLazyCompilation() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001782 !LiveEditFunctionTracker::IsActive(isolate) &&
1783 (!info.is_debug() || allow_lazy_without_ctx);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001785 bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001786
Ben Murdochda12d292016-06-02 14:46:10 +01001787 // Consider compiling eagerly when targeting the code cache.
1788 lazy &= !(FLAG_serialize_eager && info.will_serialize());
1789
1790 // Consider compiling eagerly when compiling bytecode for Ignition.
1791 lazy &=
1792 !(FLAG_ignition && FLAG_ignition_eager && !isolate->serializer_enabled());
1793
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001794 // Generate code
Ben Murdoch097c5b22016-05-18 11:27:45 +01001795 TimerEventScope<TimerEventCompileCode> timer(isolate);
1796 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001797 if (lazy) {
Ben Murdochda12d292016-06-02 14:46:10 +01001798 info.SetCode(isolate->builtins()->CompileLazy());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001799 } else if (Renumber(info.parse_info()) && GenerateBaselineCode(&info)) {
1800 // Code generation will ensure that the feedback vector is present and
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001801 // appropriately sized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802 DCHECK(!info.code().is_null());
Ben Murdochda12d292016-06-02 14:46:10 +01001803 Handle<ScopeInfo> scope_info =
1804 ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001805 if (literal->should_eager_compile() &&
1806 literal->should_be_used_once_hint()) {
1807 info.code()->MarkToBeExecutedOnce(isolate);
1808 }
Ben Murdochda12d292016-06-02 14:46:10 +01001809 // Install compilation result on the shared function info.
1810 InstallBaselineCompilationResult(&info, result, scope_info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001811 } else {
1812 return Handle<SharedFunctionInfo>::null();
1813 }
1814
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001815 if (maybe_existing.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001816 // If the outer function has been compiled before, we cannot be sure that
1817 // shared function info for this function literal has been created for the
1818 // first time. It may have already been compiled previously.
1819 result->set_never_compiled(outer_info->is_first_compile() && lazy);
1820
1821 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
1822 result->set_allows_lazy_compilation(literal->AllowsLazyCompilation());
1823 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
1824
1825 // Set the expected number of properties for instances and return
1826 // the resulting function.
1827 SetExpectedNofPropertiesFromEstimate(result,
1828 literal->expected_property_count());
1829 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830 }
Ben Murdochda12d292016-06-02 14:46:10 +01001831
1832 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833}
1834
Ben Murdoch097c5b22016-05-18 11:27:45 +01001835Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
1836 v8::Extension* extension, Handle<String> name) {
1837 Isolate* isolate = name->GetIsolate();
1838 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1839
1840 // Compute the function template for the native function.
1841 v8::Local<v8::FunctionTemplate> fun_template =
1842 extension->GetNativeFunctionTemplate(v8_isolate,
1843 v8::Utils::ToLocal(name));
1844 DCHECK(!fun_template.IsEmpty());
1845
1846 // Instantiate the function and create a shared function info from it.
1847 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
1848 *fun_template->GetFunction(v8_isolate->GetCurrentContext())
1849 .ToLocalChecked()));
1850 const int literals = fun->NumberOfLiterals();
1851 Handle<Code> code = Handle<Code>(fun->shared()->code());
1852 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1853 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
1854 name, literals, FunctionKind::kNormalFunction, code,
Ben Murdochda12d292016-06-02 14:46:10 +01001855 Handle<ScopeInfo>(fun->shared()->scope_info()));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001856 shared->set_construct_stub(*construct_stub);
Ben Murdochda12d292016-06-02 14:46:10 +01001857 shared->set_feedback_vector(fun->shared()->feedback_vector());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001858
1859 // Copy the function data to the shared function info.
1860 shared->set_function_data(fun->shared()->function_data());
1861 int parameters = fun->shared()->internal_formal_parameter_count();
1862 shared->set_internal_formal_parameter_count(parameters);
1863
1864 return shared;
1865}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001866
Ben Murdochda12d292016-06-02 14:46:10 +01001867MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1868 BailoutId osr_ast_id,
1869 JavaScriptFrame* osr_frame) {
1870 DCHECK(!osr_ast_id.IsNone());
1871 DCHECK_NOT_NULL(osr_frame);
1872 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873}
1874
Ben Murdochda12d292016-06-02 14:46:10 +01001875void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876 // Take ownership of compilation info. Deleting compilation info
1877 // also tears down the zone and the recompile job.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001878 base::SmartPointer<CompilationInfo> info(job->info());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001879 Isolate* isolate = info->isolate();
1880
1881 VMState<COMPILER> state(isolate);
1882 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001883 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001884
1885 Handle<SharedFunctionInfo> shared = info->shared_info();
1886 shared->code()->set_profiler_ticks(0);
1887
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001888 DCHECK(!shared->HasDebugInfo());
1889
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001890 // 1) Optimization on the concurrent thread may have failed.
1891 // 2) The function may have already been optimized by OSR. Simply continue.
1892 // Except when OSR already disabled optimization for some reason.
1893 // 3) The code may have already been invalidated due to dependency change.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001894 // 4) Code generation may have failed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001895 if (job->last_status() == OptimizedCompileJob::SUCCEEDED) {
1896 if (shared->optimization_disabled()) {
1897 job->RetryOptimization(kOptimizationDisabled);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001898 } else if (info->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001899 job->RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001900 } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
1901 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001902 if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
1903 info->osr_ast_id()).code == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001904 InsertCodeIntoOptimizedCodeMap(info.get());
1905 }
1906 if (FLAG_trace_opt) {
1907 PrintF("[completed optimizing ");
1908 info->closure()->ShortPrint();
1909 PrintF("]\n");
1910 }
Ben Murdochda12d292016-06-02 14:46:10 +01001911 info->closure()->ReplaceCode(*info->code());
1912 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001913 }
1914 }
1915
1916 DCHECK(job->last_status() != OptimizedCompileJob::SUCCEEDED);
1917 if (FLAG_trace_opt) {
1918 PrintF("[aborted optimizing ");
1919 info->closure()->ShortPrint();
1920 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
1921 }
Ben Murdochda12d292016-06-02 14:46:10 +01001922 info->closure()->ReplaceCode(shared->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001923}
1924
Ben Murdochda12d292016-06-02 14:46:10 +01001925void Compiler::PostInstantiation(Handle<JSFunction> function,
1926 PretenureFlag pretenure) {
1927 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001928
Ben Murdochda12d292016-06-02 14:46:10 +01001929 if (FLAG_always_opt && shared->allows_lazy_compilation()) {
1930 function->MarkForOptimization();
1931 }
1932
1933 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
1934 function->context()->native_context(), BailoutId::None());
1935 if (cached.code != nullptr) {
1936 // Caching of optimized code enabled and optimized code found.
1937 DCHECK(!cached.code->marked_for_deoptimization());
1938 DCHECK(function->shared()->is_compiled());
1939 function->ReplaceCode(cached.code);
1940 }
1941
1942 if (cached.literals != nullptr) {
1943 function->set_literals(cached.literals);
1944 } else {
1945 Isolate* isolate = function->GetIsolate();
1946 int number_of_literals = shared->num_literals();
1947 Handle<LiteralsArray> literals =
1948 LiteralsArray::New(isolate, handle(shared->feedback_vector()),
1949 number_of_literals, pretenure);
1950 function->set_literals(*literals);
1951
1952 // Cache context-specific literals.
1953 MaybeHandle<Code> code;
1954 if (cached.code != nullptr) code = handle(cached.code);
1955 Handle<Context> native_context(function->context()->native_context());
1956 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
1957 literals, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001958 }
1959}
1960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001961} // namespace internal
1962} // namespace v8