blob: 2a0eda0a551229eface54be75d02400b6c0be6ff [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"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/debug/debug.h"
19#include "src/debug/liveedit.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/deoptimizer.h"
Ben Murdochc5610432016-08-08 18:44:38 +010021#include "src/frames-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022#include "src/full-codegen/full-codegen.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023#include "src/interpreter/interpreter.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/isolate-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025#include "src/log-inl.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040026#include "src/messages.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027#include "src/parsing/parser.h"
28#include "src/parsing/rewriter.h"
29#include "src/parsing/scanner-character-streams.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/runtime-profiler.h"
Ben Murdochda12d292016-06-02 14:46:10 +010031#include "src/snapshot/code-serializer.h"
Ben Murdochc5610432016-08-08 18:44:38 +010032#include "src/typing-asm.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034
35namespace v8 {
36namespace internal {
37
Ben Murdochf87a2032010-10-22 12:50:53 +010038
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039#define PARSE_INFO_GETTER(type, name) \
40 type CompilationInfo::name() const { \
41 CHECK(parse_info()); \
42 return parse_info()->name(); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044
45
46#define PARSE_INFO_GETTER_WITH_DEFAULT(type, name, def) \
47 type CompilationInfo::name() const { \
48 return parse_info() ? parse_info()->name() : def; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050
51
52PARSE_INFO_GETTER(Handle<Script>, script)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053PARSE_INFO_GETTER(FunctionLiteral*, literal)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr)
Ben Murdochc5610432016-08-08 18:44:38 +010055PARSE_INFO_GETTER_WITH_DEFAULT(Handle<Context>, context,
56 Handle<Context>::null())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
58
59#undef PARSE_INFO_GETTER
60#undef PARSE_INFO_GETTER_WITH_DEFAULT
61
Ben Murdochda12d292016-06-02 14:46:10 +010062// A wrapper around a CompilationInfo that detaches the Handles from
63// the underlying DeferredHandleScope and stores them in info_ on
64// destruction.
65class CompilationHandleScope BASE_EMBEDDED {
66 public:
67 explicit CompilationHandleScope(CompilationInfo* info)
68 : deferred_(info->isolate()), info_(info) {}
69 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
70
71 private:
72 DeferredHandleScope deferred_;
73 CompilationInfo* info_;
74};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075
Ben Murdochc5610432016-08-08 18:44:38 +010076// Helper that times a scoped region and records the elapsed time.
77struct ScopedTimer {
78 explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
79 DCHECK(location_ != NULL);
80 timer_.Start();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082
Ben Murdochc5610432016-08-08 18:44:38 +010083 ~ScopedTimer() { *location_ += timer_.Elapsed(); }
84
85 base::ElapsedTimer timer_;
86 base::TimeDelta* location_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087};
88
Ben Murdochda12d292016-06-02 14:46:10 +010089// ----------------------------------------------------------------------------
90// Implementation of CompilationInfo
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091
92bool CompilationInfo::has_shared_info() const {
93 return parse_info_ && !parse_info_->shared_info().is_null();
94}
95
Ben Murdochc5610432016-08-08 18:44:38 +010096CompilationInfo::CompilationInfo(ParseInfo* parse_info,
97 Handle<JSFunction> closure)
98 : CompilationInfo(parse_info, {}, Code::ComputeFlags(Code::FUNCTION), BASE,
99 parse_info->isolate(), parse_info->zone()) {
100 closure_ = closure;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400102 // Compiling for the snapshot typically results in different code than
103 // compiling later on. This means that code recompiled with deoptimization
104 // support won't be "equivalent" (as defined by SharedFunctionInfo::
105 // EnableDeoptimizationSupport), so it will replace the old code and all
106 // its type feedback. To avoid this, always compile functions in the snapshot
107 // with deoptimization support.
108 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
109
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111 if (FLAG_turbo_inlining) MarkAsInliningEnabled();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled();
113 if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115
Ben Murdochc5610432016-08-08 18:44:38 +0100116CompilationInfo::CompilationInfo(Vector<const char> debug_name,
117 Isolate* isolate, Zone* zone,
118 Code::Flags code_flags)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100119 : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120
Ben Murdochc5610432016-08-08 18:44:38 +0100121CompilationInfo::CompilationInfo(ParseInfo* parse_info,
122 Vector<const char> debug_name,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100123 Code::Flags code_flags, Mode mode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 Isolate* isolate, Zone* zone)
125 : parse_info_(parse_info),
126 isolate_(isolate),
127 flags_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100128 code_flags_(code_flags),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 mode_(mode),
130 osr_ast_id_(BailoutId::None()),
131 zone_(zone),
132 deferred_handles_(nullptr),
133 dependencies_(isolate, zone),
134 bailout_reason_(kNoReason),
135 prologue_offset_(Code::kPrologueOffsetNotSet),
136 track_positions_(FLAG_hydrogen_track_positions ||
Ben Murdoch61f157c2016-09-16 13:49:30 +0100137 isolate->is_profiling()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 parameter_count_(0),
139 optimization_id_(-1),
140 osr_expr_stack_height_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100141 debug_name_(debug_name) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143CompilationInfo::~CompilationInfo() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144 DisableFutureOptimization();
Ben Murdochc5610432016-08-08 18:44:38 +0100145 dependencies()->Rollback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 delete deferred_handles_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147}
148
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150int CompilationInfo::num_parameters() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100151 return !IsStub() ? scope()->num_parameters() : parameter_count_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152}
153
154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155int CompilationInfo::num_parameters_including_this() const {
156 return num_parameters() + (is_this_defined() ? 1 : 0);
157}
158
159
160bool CompilationInfo::is_this_defined() const { return !IsStub(); }
161
162
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100163// Primitive functions are unlikely to be picked up by the stack-walking
164// profiler, so they trigger their own optimization when they're called
165// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
166bool CompilationInfo::ShouldSelfOptimize() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 return FLAG_crankshaft &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
169 !literal()->dont_optimize() &&
170 literal()->scope()->AllowsLazyCompilation() &&
Ben Murdochc5610432016-08-08 18:44:38 +0100171 !shared_info()->optimization_disabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400172}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175bool CompilationInfo::has_simple_parameters() {
176 return scope()->has_simple_parameters();
177}
178
179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180base::SmartArrayPointer<char> CompilationInfo::GetDebugName() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181 if (parse_info() && parse_info()->literal()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 AllowHandleDereference allow_deref;
183 return parse_info()->literal()->debug_name()->ToCString();
184 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100185 if (parse_info() && !parse_info()->shared_info().is_null()) {
186 return parse_info()->shared_info()->DebugName()->ToCString();
187 }
Ben Murdochc5610432016-08-08 18:44:38 +0100188 Vector<const char> name_vec = debug_name_;
189 if (name_vec.is_empty()) name_vec = ArrayVector("unknown");
190 base::SmartArrayPointer<char> name(new char[name_vec.length() + 1]);
191 memcpy(name.get(), name_vec.start(), name_vec.length());
192 name[name_vec.length()] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 return name;
194}
195
Ben Murdochda12d292016-06-02 14:46:10 +0100196StackFrame::Type CompilationInfo::GetOutputStackFrameType() const {
197 switch (output_code_kind()) {
198 case Code::STUB:
199 case Code::BYTECODE_HANDLER:
200 case Code::HANDLER:
201 case Code::BUILTIN:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100202#define CASE_KIND(kind) case Code::kind:
203 IC_KIND_LIST(CASE_KIND)
204#undef CASE_KIND
Ben Murdochda12d292016-06-02 14:46:10 +0100205 return StackFrame::STUB;
206 case Code::WASM_FUNCTION:
207 return StackFrame::WASM;
208 case Code::JS_TO_WASM_FUNCTION:
209 return StackFrame::JS_TO_WASM;
210 case Code::WASM_TO_JS_FUNCTION:
211 return StackFrame::WASM_TO_JS;
212 default:
213 UNIMPLEMENTED();
214 return StackFrame::NONE;
215 }
216}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217
Ben Murdochc5610432016-08-08 18:44:38 +0100218int CompilationInfo::GetDeclareGlobalsFlags() const {
219 DCHECK(DeclareGlobalsLanguageMode::is_valid(parse_info()->language_mode()));
220 return DeclareGlobalsEvalFlag::encode(parse_info()->is_eval()) |
221 DeclareGlobalsNativeFlag::encode(parse_info()->is_native()) |
222 DeclareGlobalsLanguageMode::encode(parse_info()->language_mode());
223}
224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
Ben Murdochc5610432016-08-08 18:44:38 +0100226 return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100227}
228
Ben Murdochda12d292016-06-02 14:46:10 +0100229#if DEBUG
230void CompilationInfo::PrintAstForTesting() {
231 PrintF("--- Source from AST ---\n%s\n",
232 PrettyPrinter(isolate()).PrintProgram(literal()));
233}
234#endif
235
236// ----------------------------------------------------------------------------
Ben Murdochc5610432016-08-08 18:44:38 +0100237// Implementation of CompilationJob
Ben Murdochb8e0da22011-05-16 14:20:40 +0100238
Ben Murdochc5610432016-08-08 18:44:38 +0100239CompilationJob::Status CompilationJob::CreateGraph() {
240 DisallowJavascriptExecution no_js(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 DCHECK(info()->IsOptimizing());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100242
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400243 if (FLAG_trace_opt) {
244 OFStream os(stdout);
Ben Murdochc5610432016-08-08 18:44:38 +0100245 os << "[compiling method " << Brief(*info()->closure()) << " using "
246 << compiler_name_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247 if (info()->is_osr()) os << " OSR";
248 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400249 }
250
Ben Murdochc5610432016-08-08 18:44:38 +0100251 // Delegate to the underlying implementation.
252 DCHECK_EQ(SUCCEEDED, last_status());
253 ScopedTimer t(&time_taken_to_create_graph_);
254 return SetLastStatus(CreateGraphImpl());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100255}
256
Ben Murdochc5610432016-08-08 18:44:38 +0100257CompilationJob::Status CompilationJob::OptimizeGraph() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 DisallowHeapAllocation no_allocation;
259 DisallowHandleAllocation no_handles;
260 DisallowHandleDereference no_deref;
261 DisallowCodeDependencyChange no_dependency_change;
Ben Murdoch257744e2011-11-30 15:57:28 +0000262
Ben Murdochc5610432016-08-08 18:44:38 +0100263 // Delegate to the underlying implementation.
264 DCHECK_EQ(SUCCEEDED, last_status());
265 ScopedTimer t(&time_taken_to_optimize_);
266 return SetLastStatus(OptimizeGraphImpl());
267}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268
Ben Murdochc5610432016-08-08 18:44:38 +0100269CompilationJob::Status CompilationJob::GenerateCode() {
270 DisallowCodeDependencyChange no_dependency_change;
271 DisallowJavascriptExecution no_js(isolate());
272 DCHECK(!info()->dependencies()->HasAborted());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273
Ben Murdochc5610432016-08-08 18:44:38 +0100274 // Delegate to the underlying implementation.
275 DCHECK_EQ(SUCCEEDED, last_status());
276 ScopedTimer t(&time_taken_to_codegen_);
277 return SetLastStatus(GenerateCodeImpl());
Steve Block6ded16b2010-05-10 14:33:55 +0100278}
Steve Block6ded16b2010-05-10 14:33:55 +0100279
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281namespace {
282
283void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
284 Handle<Code> code) {
285 Handle<WeakCell> cell = Code::WeakCellFor(code);
286 Heap* heap = isolate->heap();
287 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
288 dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
289 heap->AddWeakObjectToCodeDependency(object, dep);
290}
291
Ben Murdochc5610432016-08-08 18:44:38 +0100292} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293
Ben Murdochc5610432016-08-08 18:44:38 +0100294void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
296 Isolate* const isolate = code->GetIsolate();
297 DCHECK(code->is_optimized_code());
298 std::vector<Handle<Map>> maps;
299 std::vector<Handle<HeapObject>> objects;
300 {
301 DisallowHeapAllocation no_gc;
302 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
303 RelocInfo::ModeMask(RelocInfo::CELL);
304 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
305 RelocInfo::Mode mode = it.rinfo()->rmode();
306 if (mode == RelocInfo::CELL &&
307 code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
308 objects.push_back(handle(it.rinfo()->target_cell(), isolate));
309 } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
310 code->IsWeakObjectInOptimizedCode(
311 it.rinfo()->target_object())) {
312 Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
313 isolate);
314 if (object->IsMap()) {
315 maps.push_back(Handle<Map>::cast(object));
316 } else {
317 objects.push_back(object);
318 }
319 }
320 }
321 }
322 for (Handle<Map> map : maps) {
323 if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) {
324 isolate->heap()->AddRetainedMap(map);
325 }
326 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code);
327 }
328 for (Handle<HeapObject> object : objects) {
329 AddWeakObjectToCodeDependency(isolate, object, code);
330 }
331 code->set_can_have_weak_objects(true);
332}
333
Ben Murdochc5610432016-08-08 18:44:38 +0100334void CompilationJob::RecordOptimizationStats() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 Handle<JSFunction> function = info()->closure();
336 if (!function->IsOptimized()) {
337 // Concurrent recompilation and OSR may race. Increment only once.
338 int opt_count = function->shared()->opt_count();
339 function->shared()->set_opt_count(opt_count + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
342 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
343 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
344 if (FLAG_trace_opt) {
345 PrintF("[optimizing ");
346 function->ShortPrint();
347 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
348 ms_codegen);
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 if (FLAG_trace_opt_stats) {
351 static double compilation_time = 0.0;
352 static int compiled_functions = 0;
353 static int code_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000354
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
356 compiled_functions++;
357 code_size += function->shared()->SourceSize();
358 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
359 compiled_functions,
360 code_size,
361 compilation_time);
362 }
363 if (FLAG_hydrogen_stats) {
364 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
365 time_taken_to_optimize_,
366 time_taken_to_codegen_);
367 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000368}
369
Ben Murdochda12d292016-06-02 14:46:10 +0100370// ----------------------------------------------------------------------------
371// Local helper methods that make up the compilation pipeline.
372
373namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +0000374
Ben Murdochc5610432016-08-08 18:44:38 +0100375bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
376 return shared->is_toplevel() && shared->script()->IsScript() &&
377 Script::cast(shared->script())->compilation_type() ==
378 Script::COMPILATION_TYPE_EVAL;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400379}
380
Ben Murdoch61f157c2016-09-16 13:49:30 +0100381void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
Ben Murdochc5610432016-08-08 18:44:38 +0100382 CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100383 // Log the code generation. If source information is available include
384 // script name and line number. Check explicitly whether logging is
385 // enabled as finding the line number is not free.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000386 if (info->isolate()->logger()->is_logging_code_events() ||
Ben Murdoch61f157c2016-09-16 13:49:30 +0100387 info->isolate()->is_profiling()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100388 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 Handle<Script> script = info->parse_info()->script();
Ben Murdochc5610432016-08-08 18:44:38 +0100390 Handle<AbstractCode> abstract_code =
391 info->has_bytecode_array()
392 ? Handle<AbstractCode>::cast(info->bytecode_array())
393 : Handle<AbstractCode>::cast(info->code());
Ben Murdochda12d292016-06-02 14:46:10 +0100394 if (abstract_code.is_identical_to(
395 info->isolate()->builtins()->CompileLazy())) {
Steve Block44f0eee2011-05-26 01:26:41 +0100396 return;
Andrei Popescu31002712010-02-23 13:46:05 +0000397 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
399 int column_num =
400 Script::GetColumnNumber(script, shared->start_position()) + 1;
401 String* script_name = script->name()->IsString()
402 ? String::cast(script->name())
403 : info->isolate()->heap()->empty_string();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100404 CodeEventListener::LogEventsAndTags log_tag =
405 Logger::ToNativeByScript(tag, *script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 PROFILE(info->isolate(),
Ben Murdochc5610432016-08-08 18:44:38 +0100407 CodeCreateEvent(log_tag, *abstract_code, *shared, script_name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 line_num, column_num));
Andrei Popescu31002712010-02-23 13:46:05 +0000409 }
410}
Andrei Popescu31002712010-02-23 13:46:05 +0000411
Ben Murdoch61f157c2016-09-16 13:49:30 +0100412void EnsureFeedbackMetadata(CompilationInfo* info) {
Ben Murdochc5610432016-08-08 18:44:38 +0100413 DCHECK(info->has_shared_info());
Ben Murdochda12d292016-06-02 14:46:10 +0100414
Ben Murdoch61f157c2016-09-16 13:49:30 +0100415 // If no type feedback metadata exists, we create it now. At this point the
Ben Murdochda12d292016-06-02 14:46:10 +0100416 // AstNumbering pass has already run. Note the snapshot can contain outdated
417 // vectors for a different configuration, hence we also recreate a new vector
418 // when the function is not compiled (i.e. no code was serialized).
Ben Murdoch61f157c2016-09-16 13:49:30 +0100419
420 // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata().
421 if (info->shared_info()->feedback_metadata()->length() == 0 ||
Ben Murdochda12d292016-06-02 14:46:10 +0100422 !info->shared_info()->is_compiled()) {
423 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New(
424 info->isolate(), info->literal()->feedback_vector_spec());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100425 info->shared_info()->set_feedback_metadata(*feedback_metadata);
Ben Murdochda12d292016-06-02 14:46:10 +0100426 }
427
428 // It's very important that recompiles do not alter the structure of the type
429 // feedback vector. Verify that the structure fits the function literal.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100430 CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom(
Ben Murdochda12d292016-06-02 14:46:10 +0100431 info->literal()->feedback_vector_spec()));
432}
433
Ben Murdochda12d292016-06-02 14:46:10 +0100434bool UseIgnition(CompilationInfo* info) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100435 DCHECK(info->has_shared_info());
436
437 // When requesting debug code as a replacement for existing code, we provide
438 // the same kind as the existing code (to prevent implicit tier-change).
439 if (info->is_debug() && info->shared_info()->is_compiled()) {
440 return info->shared_info()->HasBytecodeArray();
441 }
442
443 // For generator or async functions we might avoid Ignition wholesale.
Ben Murdochc5610432016-08-08 18:44:38 +0100444 if (info->shared_info()->is_resumable() && !FLAG_ignition_generators) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 return false;
446 }
447
Ben Murdoch61f157c2016-09-16 13:49:30 +0100448 // Since we can't OSR from Ignition, skip Ignition for asm.js functions.
449 if (info->shared_info()->asm_function()) {
450 return false;
451 }
452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 // Checks whether top level functions should be passed by the filter.
Ben Murdochda12d292016-06-02 14:46:10 +0100454 if (info->shared_info()->is_toplevel()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 Vector<const char> filter = CStrVector(FLAG_ignition_filter);
456 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
457 }
458
459 // Finally respect the filter.
Ben Murdochda12d292016-06-02 14:46:10 +0100460 return info->shared_info()->PassesFilter(FLAG_ignition_filter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461}
462
Ben Murdochda12d292016-06-02 14:46:10 +0100463int CodeAndMetadataSize(CompilationInfo* info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100464 if (info->has_bytecode_array()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100465 return info->bytecode_array()->SizeIncludingMetadata();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100466 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100467 return info->code()->SizeIncludingMetadata();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100468}
469
Ben Murdochc5610432016-08-08 18:44:38 +0100470bool GenerateUnoptimizedCode(CompilationInfo* info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100471 bool success;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100472 EnsureFeedbackMetadata(info);
Ben Murdochc5610432016-08-08 18:44:38 +0100473 if (FLAG_validate_asm && info->scope()->asm_module()) {
474 AsmTyper typer(info->isolate(), info->zone(), *(info->script()),
475 info->literal());
476 if (FLAG_enable_simd_asmjs) {
477 typer.set_allow_simd(true);
478 }
479 if (!typer.Validate()) {
480 DCHECK(!info->isolate()->has_pending_exception());
481 PrintF("Validation of asm.js module failed: %s", typer.error_message());
482 }
483 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 if (FLAG_ignition && UseIgnition(info)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100485 success = interpreter::Interpreter::MakeBytecode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100487 success = FullCodeGenerator::MakeCode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100489 if (success) {
490 Isolate* isolate = info->isolate();
491 Counters* counters = isolate->counters();
Ben Murdochc5610432016-08-08 18:44:38 +0100492 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100493 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info));
494 counters->total_baseline_compile_count()->Increment(1);
495 }
496 return success;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497}
498
Ben Murdochc5610432016-08-08 18:44:38 +0100499bool CompileUnoptimizedCode(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
Ben Murdochc5610432016-08-08 18:44:38 +0100501 if (!Compiler::Analyze(info->parse_info()) ||
502 !GenerateUnoptimizedCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 Isolate* isolate = info->isolate();
504 if (!isolate->has_pending_exception()) isolate->StackOverflow();
505 return false;
506 }
507 return true;
508}
509
Ben Murdochc5610432016-08-08 18:44:38 +0100510void InstallSharedScopeInfo(CompilationInfo* info,
511 Handle<SharedFunctionInfo> shared) {
512 Handle<ScopeInfo> scope_info =
513 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
514 shared->set_scope_info(*scope_info);
515}
516
517void InstallSharedCompilationResult(CompilationInfo* info,
518 Handle<SharedFunctionInfo> shared) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100519 // TODO(mstarzinger): Compiling for debug code might be used to reveal inner
520 // functions via {FindSharedFunctionInfoInScript}, in which case we end up
521 // regenerating existing bytecode. Fix this!
522 if (info->is_debug() && info->has_bytecode_array()) {
523 shared->ClearBytecodeArray();
524 }
Ben Murdochda12d292016-06-02 14:46:10 +0100525 // Assert that we are not overwriting (possibly patched) debug code.
Ben Murdochc5610432016-08-08 18:44:38 +0100526 DCHECK(!shared->HasDebugInfo());
Ben Murdochda12d292016-06-02 14:46:10 +0100527 DCHECK(!info->code().is_null());
528 shared->ReplaceCode(*info->code());
Ben Murdochda12d292016-06-02 14:46:10 +0100529 if (info->has_bytecode_array()) {
530 DCHECK(!shared->HasBytecodeArray()); // Only compiled once.
531 shared->set_bytecode_array(*info->bytecode_array());
532 }
533}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534
Ben Murdochc5610432016-08-08 18:44:38 +0100535MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536 VMState<COMPILER> state(info->isolate());
537 PostponeInterruptsScope postpone(info->isolate());
538
539 // Parse and update CompilationInfo with the results.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000541 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdochc5610432016-08-08 18:44:38 +0100542 DCHECK_EQ(shared->language_mode(), info->literal()->language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 // Compile either unoptimized code or bytecode for the interpreter.
Ben Murdochc5610432016-08-08 18:44:38 +0100545 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546
Ben Murdochc5610432016-08-08 18:44:38 +0100547 // Update the shared function info with the scope info.
548 InstallSharedScopeInfo(info, shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549
Ben Murdochda12d292016-06-02 14:46:10 +0100550 // Install compilation result on the shared function info
Ben Murdochc5610432016-08-08 18:44:38 +0100551 InstallSharedCompilationResult(info, shared);
552
553 // Record the function compilation event.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100554 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555
556 return info->code();
557}
558
Ben Murdochda12d292016-06-02 14:46:10 +0100559MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000560 Handle<JSFunction> function, BailoutId osr_ast_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 Handle<SharedFunctionInfo> shared(function->shared());
562 DisallowHeapAllocation no_gc;
563 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
564 function->context()->native_context(), osr_ast_id);
565 if (cached.code != nullptr) {
566 // Caching of optimized code enabled and optimized code found.
567 if (cached.literals != nullptr) function->set_literals(cached.literals);
568 DCHECK(!cached.code->marked_for_deoptimization());
569 DCHECK(function->shared()->is_compiled());
570 return Handle<Code>(cached.code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 }
572 return MaybeHandle<Code>();
573}
574
Ben Murdochda12d292016-06-02 14:46:10 +0100575void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 Handle<Code> code = info->code();
577 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 // Function context specialization folds-in the function context,
580 // so no sharing can occur.
581 if (info->is_function_context_specializing()) return;
582 // Frame specialization implies function context specialization.
583 DCHECK(!info->is_frame_specializing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 // Cache optimized context-specific code.
586 Handle<JSFunction> function = info->closure();
587 Handle<SharedFunctionInfo> shared(function->shared());
588 Handle<LiteralsArray> literals(function->literals());
589 Handle<Context> native_context(function->context()->native_context());
590 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
591 literals, info->osr_ast_id());
592
593 // Do not cache (native) context-independent code compiled for OSR.
594 if (code->is_turbofanned() && info->is_osr()) return;
595
596 // Cache optimized (native) context-independent code.
597 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
598 !info->is_native_context_specializing()) {
599 DCHECK(!info->is_function_context_specializing());
600 DCHECK(info->osr_ast_id().IsNone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 }
604}
605
Ben Murdochda12d292016-06-02 14:46:10 +0100606bool Renumber(ParseInfo* parse_info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
608 parse_info->literal())) {
609 return false;
610 }
611 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info();
612 if (!shared_info.is_null()) {
613 FunctionLiteral* lit = parse_info->literal();
614 shared_info->set_ast_node_count(lit->ast_node_count());
Ben Murdochc5610432016-08-08 18:44:38 +0100615 if (lit->dont_optimize_reason() != kNoReason) {
616 shared_info->DisableOptimization(lit->dont_optimize_reason());
617 }
Ben Murdochda12d292016-06-02 14:46:10 +0100618 shared_info->set_dont_crankshaft(
619 shared_info->dont_crankshaft() ||
620 (lit->flags() & AstProperties::kDontCrankshaft));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400621 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 return true;
623}
624
Ben Murdochc5610432016-08-08 18:44:38 +0100625bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
626 bool optimization_disabled = shared->optimization_disabled();
627 bool dont_crankshaft = shared->dont_crankshaft();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628
Ben Murdochc5610432016-08-08 18:44:38 +0100629 // Check the enabling conditions for Turbofan.
630 // 1. "use asm" code.
631 bool is_turbofanable_asm =
632 FLAG_turbo_asm && shared->asm_function() && !optimization_disabled;
633
634 // 2. Fallback for features unsupported by Crankshaft.
635 bool is_unsupported_by_crankshaft_but_turbofanable =
636 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
637 !optimization_disabled;
638
639 // 3. Explicitly enabled by the command-line filter.
640 bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
641
642 return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
643 passes_turbo_filter;
644}
645
646bool GetOptimizedCodeNow(CompilationJob* job) {
647 CompilationInfo* info = job->info();
648 Isolate* isolate = info->isolate();
649
650 // Parsing is not required when optimizing from existing bytecode.
651 if (!info->is_optimizing_from_bytecode()) {
652 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100653 EnsureFeedbackMetadata(info);
Ben Murdochc5610432016-08-08 18:44:38 +0100654 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655
Ben Murdoch61f157c2016-09-16 13:49:30 +0100656 JSFunction::EnsureLiterals(info->closure());
657
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100659 RuntimeCallTimerScope runtimeTimer(isolate,
660 &RuntimeCallStats::RecompileSynchronous);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100661 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662
Ben Murdochc5610432016-08-08 18:44:38 +0100663 if (job->CreateGraph() != CompilationJob::SUCCEEDED ||
664 job->OptimizeGraph() != CompilationJob::SUCCEEDED ||
665 job->GenerateCode() != CompilationJob::SUCCEEDED) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 if (FLAG_trace_opt) {
667 PrintF("[aborted optimizing ");
668 info->closure()->ShortPrint();
669 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
670 }
671 return false;
672 }
673
674 // Success!
Ben Murdochc5610432016-08-08 18:44:38 +0100675 job->RecordOptimizationStats();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 InsertCodeIntoOptimizedCodeMap(info);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100678 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679 return true;
680}
681
Ben Murdochc5610432016-08-08 18:44:38 +0100682bool GetOptimizedCodeLater(CompilationJob* job) {
683 CompilationInfo* info = job->info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 Isolate* isolate = info->isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000685
686 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000687 if (FLAG_trace_concurrent_recompilation) {
688 PrintF(" ** Compilation queue full, will retry optimizing ");
689 info->closure()->ShortPrint();
690 PrintF(" later.\n");
691 }
692 return false;
693 }
694
Ben Murdochc5610432016-08-08 18:44:38 +0100695 // All handles below this point will be allocated in a deferred handle scope
696 // that is detached and handed off to the background thread when we return.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697 CompilationHandleScope handle_scope(info);
Ben Murdochc5610432016-08-08 18:44:38 +0100698
699 // Parsing is not required when optimizing from existing bytecode.
700 if (!info->is_optimizing_from_bytecode()) {
701 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100702 EnsureFeedbackMetadata(info);
Ben Murdochc5610432016-08-08 18:44:38 +0100703 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704
Ben Murdoch61f157c2016-09-16 13:49:30 +0100705 JSFunction::EnsureLiterals(info->closure());
706
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 // Reopen handles in the new CompilationHandleScope.
708 info->ReopenHandlesInNewHandleScope();
709 info->parse_info()->ReopenHandlesInNewHandleScope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710
711 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100712 RuntimeCallTimerScope runtimeTimer(info->isolate(),
713 &RuntimeCallStats::RecompileSynchronous);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100714 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000715
Ben Murdochc5610432016-08-08 18:44:38 +0100716 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000717 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718
719 if (FLAG_trace_concurrent_recompilation) {
720 PrintF(" ** Queued ");
721 info->closure()->ShortPrint();
Ben Murdochc5610432016-08-08 18:44:38 +0100722 PrintF(" for concurrent optimization.\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 }
724 return true;
725}
726
Ben Murdochda12d292016-06-02 14:46:10 +0100727MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
728 Compiler::ConcurrencyMode mode,
729 BailoutId osr_ast_id = BailoutId::None(),
730 JavaScriptFrame* osr_frame = nullptr) {
731 Isolate* isolate = function->GetIsolate();
732 Handle<SharedFunctionInfo> shared(function->shared(), isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733
Ben Murdochda12d292016-06-02 14:46:10 +0100734 Handle<Code> cached_code;
735 if (GetCodeFromOptimizedCodeMap(function, osr_ast_id)
736 .ToHandle(&cached_code)) {
737 if (FLAG_trace_opt) {
738 PrintF("[found optimized code for ");
739 function->ShortPrint();
740 if (!osr_ast_id.IsNone()) {
741 PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
742 }
743 PrintF("]\n");
744 }
745 return cached_code;
746 }
747
Ben Murdochc5610432016-08-08 18:44:38 +0100748 // Reset profiler ticks, function is no longer considered hot.
Ben Murdochda12d292016-06-02 14:46:10 +0100749 if (shared->is_compiled()) {
750 shared->code()->set_profiler_ticks(0);
751 }
752
Ben Murdochda12d292016-06-02 14:46:10 +0100753 VMState<COMPILER> state(isolate);
754 DCHECK(!isolate->has_pending_exception());
755 PostponeInterruptsScope postpone(isolate);
Ben Murdochc5610432016-08-08 18:44:38 +0100756 bool use_turbofan = UseTurboFan(shared);
757 base::SmartPointer<CompilationJob> job(
758 use_turbofan ? compiler::Pipeline::NewCompilationJob(function)
759 : new HCompilationJob(function));
760 CompilationInfo* info = job->info();
761 ParseInfo* parse_info = info->parse_info();
Ben Murdochda12d292016-06-02 14:46:10 +0100762
Ben Murdochc5610432016-08-08 18:44:38 +0100763 info->SetOptimizingForOsr(osr_ast_id, osr_frame);
764
765 // Do not use Crankshaft/TurboFan if we need to be able to set break points.
766 if (info->shared_info()->HasDebugInfo()) {
767 info->AbortOptimization(kFunctionBeingDebugged);
768 return MaybeHandle<Code>();
769 }
770
771 // Limit the number of times we try to optimize functions.
772 const int kMaxOptCount =
773 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
774 if (info->shared_info()->opt_count() > kMaxOptCount) {
775 info->AbortOptimization(kOptimizedTooManyTimes);
776 return MaybeHandle<Code>();
777 }
778
779 CanonicalHandleScope canonical(isolate);
780 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100781 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
Ben Murdochc5610432016-08-08 18:44:38 +0100782 TRACE_EVENT0("v8", "V8.OptimizeCode");
783
784 // TurboFan can optimize directly from existing bytecode.
785 if (FLAG_turbo_from_bytecode && use_turbofan &&
786 info->shared_info()->HasBytecodeArray()) {
787 info->MarkAsOptimizeFromBytecode();
788 }
789
790 if (IsEvalToplevel(shared)) {
791 parse_info->set_eval();
792 if (function->context()->IsNativeContext()) parse_info->set_global();
793 parse_info->set_toplevel();
794 parse_info->set_allow_lazy_parsing(false);
795 parse_info->set_lazy(false);
796 }
Ben Murdochda12d292016-06-02 14:46:10 +0100797
798 if (mode == Compiler::CONCURRENT) {
Ben Murdochc5610432016-08-08 18:44:38 +0100799 if (GetOptimizedCodeLater(job.get())) {
800 job.Detach(); // The background recompile job owns this now.
Ben Murdochda12d292016-06-02 14:46:10 +0100801 return isolate->builtins()->InOptimizationQueue();
802 }
803 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100804 if (GetOptimizedCodeNow(job.get())) return info->code();
Ben Murdochda12d292016-06-02 14:46:10 +0100805 }
806
807 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
808 return MaybeHandle<Code>();
809}
810
Ben Murdochc5610432016-08-08 18:44:38 +0100811class InterpreterActivationsFinder : public ThreadVisitor,
812 public OptimizedFunctionVisitor {
813 public:
Ben Murdochc5610432016-08-08 18:44:38 +0100814 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared)
815 : shared_(shared), has_activations_(false) {}
816
817 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100818 Address* activation_pc_address = nullptr;
Ben Murdochc5610432016-08-08 18:44:38 +0100819 JavaScriptFrameIterator it(isolate, top);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100820 for (; !it.done(); it.Advance()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100821 JavaScriptFrame* frame = it.frame();
822 if (!frame->is_interpreted()) continue;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100823 if (frame->function()->shared() == shared_) {
824 has_activations_ = true;
825 activation_pc_address = frame->pc_address();
826 }
827 }
828
829 if (activation_pc_address) {
830 activation_pc_addresses_.push_back(activation_pc_address);
Ben Murdochc5610432016-08-08 18:44:38 +0100831 }
832 }
833
834 void VisitFunction(JSFunction* function) {
835 if (function->Inlines(shared_)) has_activations_ = true;
836 }
837
838 void EnterContext(Context* context) {}
839 void LeaveContext(Context* context) {}
Ben Murdoch61f157c2016-09-16 13:49:30 +0100840
841 bool MarkActivationsForBaselineOnReturn(Isolate* isolate) {
842 if (activation_pc_addresses_.empty()) return false;
843
844 for (Address* activation_pc_address : activation_pc_addresses_) {
845 DCHECK(isolate->inner_pointer_to_code_cache()
846 ->GetCacheEntry(*activation_pc_address)
847 ->code->is_interpreter_trampoline_builtin());
848 *activation_pc_address =
849 isolate->builtins()->InterpreterMarkBaselineOnReturn()->entry();
850 }
851 return true;
852 }
853
854 bool has_activations() { return has_activations_; }
855
856 private:
857 SharedFunctionInfo* shared_;
858 bool has_activations_;
859 std::vector<Address*> activation_pc_addresses_;
Ben Murdochc5610432016-08-08 18:44:38 +0100860};
861
Ben Murdoch61f157c2016-09-16 13:49:30 +0100862bool HasInterpreterActivations(
863 Isolate* isolate, InterpreterActivationsFinder* activations_finder) {
864 activations_finder->VisitThread(isolate, isolate->thread_local_top());
865 isolate->thread_manager()->IterateArchivedThreads(activations_finder);
Ben Murdochc5610432016-08-08 18:44:38 +0100866 if (FLAG_turbo_from_bytecode) {
867 // If we are able to optimize functions directly from bytecode, then there
868 // might be optimized functions that rely on bytecode being around. We need
869 // to prevent switching the given function to baseline code in those cases.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100870 Deoptimizer::VisitAllOptimizedFunctions(isolate, activations_finder);
Ben Murdochc5610432016-08-08 18:44:38 +0100871 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100872 return activations_finder->has_activations();
Ben Murdochc5610432016-08-08 18:44:38 +0100873}
874
875MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
876 Isolate* isolate = function->GetIsolate();
877 VMState<COMPILER> state(isolate);
878 PostponeInterruptsScope postpone(isolate);
879 Zone zone(isolate->allocator());
880 ParseInfo parse_info(&zone, function);
881 CompilationInfo info(&parse_info, function);
882
883 // Reset profiler ticks, function is no longer considered hot.
884 if (function->shared()->HasBytecodeArray()) {
885 function->shared()->set_profiler_ticks(0);
886 }
887
888 // Nothing left to do if the function already has baseline code.
889 if (function->shared()->code()->kind() == Code::FUNCTION) {
890 return Handle<Code>(function->shared()->code());
891 }
892
893 // We do not switch to baseline code when the debugger might have created a
894 // copy of the bytecode with break slots to be able to set break points.
895 if (function->shared()->HasDebugInfo()) {
896 return MaybeHandle<Code>();
897 }
898
Ben Murdoch61f157c2016-09-16 13:49:30 +0100899 // TODO(4280): For now we do not switch generators or async functions to
900 // baseline code because there might be suspended activations stored in
901 // generator objects on the heap. We could eventually go directly to
902 // TurboFan in this case.
903 if (function->shared()->is_resumable()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100904 return MaybeHandle<Code>();
905 }
906
907 // TODO(4280): For now we disable switching to baseline code in the presence
908 // of interpreter activations of the given function. The reasons are:
909 // 1) The debugger assumes each function is either full-code or bytecode.
910 // 2) The underlying bytecode is cleared below, breaking stack unwinding.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100911 InterpreterActivationsFinder activations_finder(function->shared());
912 if (HasInterpreterActivations(isolate, &activations_finder)) {
Ben Murdochc5610432016-08-08 18:44:38 +0100913 if (FLAG_trace_opt) {
914 OFStream os(stdout);
915 os << "[unable to switch " << Brief(*function) << " due to activations]"
916 << std::endl;
917 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100918
919 if (activations_finder.MarkActivationsForBaselineOnReturn(isolate)) {
920 if (FLAG_trace_opt) {
921 OFStream os(stdout);
922 os << "[marking " << Brief(function->shared())
923 << " for baseline recompilation on return]" << std::endl;
924 }
925 }
926
Ben Murdochc5610432016-08-08 18:44:38 +0100927 return MaybeHandle<Code>();
928 }
929
930 if (FLAG_trace_opt) {
931 OFStream os(stdout);
932 os << "[switching method " << Brief(*function) << " to baseline code]"
933 << std::endl;
934 }
935
936 // Parse and update CompilationInfo with the results.
937 if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>();
938 Handle<SharedFunctionInfo> shared = info.shared_info();
939 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode());
940
941 // Compile baseline code using the full code generator.
942 if (!Compiler::Analyze(info.parse_info()) ||
943 !FullCodeGenerator::MakeCode(&info)) {
944 if (!isolate->has_pending_exception()) isolate->StackOverflow();
945 return MaybeHandle<Code>();
946 }
947
948 // TODO(4280): For now we play it safe and remove the bytecode array when we
949 // switch to baseline code. We might consider keeping around the bytecode so
950 // that it can be used as the "source of truth" eventually.
951 shared->ClearBytecodeArray();
952
953 // Update the shared function info with the scope info.
954 InstallSharedScopeInfo(&info, shared);
955
956 // Install compilation result on the shared function info
957 InstallSharedCompilationResult(&info, shared);
958
959 // Record the function compilation event.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100960 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, &info);
Ben Murdochc5610432016-08-08 18:44:38 +0100961
962 return info.code();
963}
964
Ben Murdochda12d292016-06-02 14:46:10 +0100965MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400966 Isolate* isolate = function->GetIsolate();
967 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 DCHECK(!function->is_compiled());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100969 TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100970 RuntimeCallTimerScope runtimeTimer(isolate,
971 &RuntimeCallStats::CompileCodeLazy);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100972 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000974
Ben Murdochc5610432016-08-08 18:44:38 +0100975 if (FLAG_turbo_cache_shared_code) {
976 Handle<Code> cached_code;
977 if (GetCodeFromOptimizedCodeMap(function, BailoutId::None())
978 .ToHandle(&cached_code)) {
979 if (FLAG_trace_opt) {
980 PrintF("[found optimized code for ");
981 function->ShortPrint();
982 PrintF(" during unoptimized compile]\n");
983 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400984 DCHECK(function->shared()->is_compiled());
Ben Murdochc5610432016-08-08 18:44:38 +0100985 return cached_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987 }
988
989 if (function->shared()->is_compiled()) {
990 return Handle<Code>(function->shared()->code());
991 }
992
Ben Murdochc5610432016-08-08 18:44:38 +0100993 Zone zone(isolate->allocator());
994 ParseInfo parse_info(&zone, function);
995 CompilationInfo info(&parse_info, function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996 Handle<Code> result;
Ben Murdochc5610432016-08-08 18:44:38 +0100997 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCode(&info), Code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 if (FLAG_always_opt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001000 Handle<Code> opt_code;
Ben Murdochda12d292016-06-02 14:46:10 +01001001 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001002 .ToHandle(&opt_code)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001003 result = opt_code;
1004 }
1005 }
1006
1007 return result;
1008}
1009
1010
Ben Murdochda12d292016-06-02 14:46:10 +01001011Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
1012 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) {
1013 Handle<Code> code = isolate->builtins()->CompileLazy();
1014 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate));
1015 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo(
1016 literal->name(), literal->materialized_literal_count(), literal->kind(),
1017 code, scope_info);
1018 SharedFunctionInfo::InitFromFunctionLiteral(result, literal);
1019 SharedFunctionInfo::SetScript(result, script);
1020 return result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021}
1022
Ben Murdochda12d292016-06-02 14:46:10 +01001023Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024 Isolate* isolate = info->isolate();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001025 TimerEventScope<TimerEventCompileCode> timer(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001026 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001027 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028 PostponeInterruptsScope postpone(isolate);
1029 DCHECK(!isolate->native_context().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001030 ParseInfo* parse_info = info->parse_info();
1031 Handle<Script> script = parse_info->script();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001032
1033 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
1034 FixedArray* array = isolate->native_context()->embedder_data();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 script->set_context_data(array->get(v8::Context::kDebugIdIndex));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036
1037 isolate->debug()->OnBeforeCompile(script);
1038
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001039 DCHECK(parse_info->is_eval() || parse_info->is_global() ||
1040 parse_info->is_module());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001041
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 parse_info->set_toplevel();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001043
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001044 Handle<SharedFunctionInfo> result;
1045
1046 { VMState<COMPILER> state(info->isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 if (parse_info->literal() == NULL) {
1048 // Parse the script if needed (if it's already parsed, literal() is
1049 // non-NULL). If compiling for debugging, we may eagerly compile inner
1050 // functions, so do not parse lazily in that case.
1051 ScriptCompiler::CompileOptions options = parse_info->compile_options();
1052 bool parse_allow_lazy = (options == ScriptCompiler::kConsumeParserCache ||
1053 String::cast(script->source())->length() >
1054 FLAG_min_preparse_length) &&
1055 !info->is_debug();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056
Ben Murdochda12d292016-06-02 14:46:10 +01001057 // Consider parsing eagerly when targeting the code cache.
1058 parse_allow_lazy &= !(FLAG_serialize_eager && info->will_serialize());
1059
1060 // Consider parsing eagerly when targeting Ignition.
1061 parse_allow_lazy &= !(FLAG_ignition && FLAG_ignition_eager &&
1062 !isolate->serializer_enabled());
1063
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001064 parse_info->set_allow_lazy_parsing(parse_allow_lazy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 if (!parse_allow_lazy &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066 (options == ScriptCompiler::kProduceParserCache ||
1067 options == ScriptCompiler::kConsumeParserCache)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068 // We are going to parse eagerly, but we either 1) have cached data
1069 // produced by lazy parsing or 2) are asked to generate cached data.
1070 // Eager parsing cannot benefit from cached data, and producing cached
1071 // data while parsing eagerly is not implemented.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 parse_info->set_cached_data(nullptr);
1073 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001074 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 if (!Parser::ParseStatic(parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076 return Handle<SharedFunctionInfo>::null();
1077 }
1078 }
1079
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing());
1081
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082 FunctionLiteral* lit = parse_info->literal();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083
1084 // Measure how long it takes to do the compilation; only take the
1085 // rest of the function into account to avoid overlap with the
1086 // parsing statistics.
Ben Murdochc5610432016-08-08 18:44:38 +01001087 RuntimeCallTimerScope runtimeTimer(
1088 isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
1089 : &RuntimeCallStats::Compile);
1090 HistogramTimer* rate = parse_info->is_eval()
1091 ? info->isolate()->counters()->compile_eval()
1092 : info->isolate()->counters()->compile();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001093 HistogramTimerScope timer(rate);
Ben Murdochc5610432016-08-08 18:44:38 +01001094 TRACE_EVENT0("v8", parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001095
Ben Murdochda12d292016-06-02 14:46:10 +01001096 // Allocate a shared function info object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001097 DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Ben Murdochda12d292016-06-02 14:46:10 +01001098 result = NewSharedFunctionInfoForLiteral(isolate, lit, script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001099 result->set_is_toplevel(true);
Ben Murdochc5610432016-08-08 18:44:38 +01001100 if (parse_info->is_eval()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 // Eval scripts cannot be (re-)compiled without context.
1102 result->set_allows_lazy_compilation_without_context(false);
1103 }
Ben Murdochda12d292016-06-02 14:46:10 +01001104 parse_info->set_shared_info(result);
1105
1106 // Compile the code.
Ben Murdochc5610432016-08-08 18:44:38 +01001107 if (!CompileUnoptimizedCode(info)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001108 return Handle<SharedFunctionInfo>::null();
1109 }
1110
Ben Murdochc5610432016-08-08 18:44:38 +01001111 // Update the shared function info with the scope info.
1112 InstallSharedScopeInfo(info, result);
1113
Ben Murdochda12d292016-06-02 14:46:10 +01001114 // Install compilation result on the shared function info
Ben Murdochc5610432016-08-08 18:44:38 +01001115 InstallSharedCompilationResult(info, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117 Handle<String> script_name =
1118 script->name()->IsString()
1119 ? Handle<String>(String::cast(script->name()))
1120 : isolate->factory()->empty_string();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001121 CodeEventListener::LogEventsAndTags log_tag =
Ben Murdochc5610432016-08-08 18:44:38 +01001122 parse_info->is_eval()
Ben Murdoch61f157c2016-09-16 13:49:30 +01001123 ? CodeEventListener::EVAL_TAG
1124 : Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001125
Ben Murdochc5610432016-08-08 18:44:38 +01001126 PROFILE(isolate, CodeCreateEvent(log_tag, result->abstract_code(), *result,
1127 *script_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001128
1129 if (!script.is_null())
1130 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 }
1132
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 return result;
1134}
1135
Ben Murdochda12d292016-06-02 14:46:10 +01001136} // namespace
1137
1138// ----------------------------------------------------------------------------
1139// Implementation of Compiler
1140
1141bool Compiler::Analyze(ParseInfo* info) {
1142 DCHECK_NOT_NULL(info->literal());
1143 if (!Rewriter::Rewrite(info)) return false;
1144 if (!Scope::Analyze(info)) return false;
1145 if (!Renumber(info)) return false;
1146 DCHECK_NOT_NULL(info->scope());
1147 return true;
1148}
1149
1150bool Compiler::ParseAndAnalyze(ParseInfo* info) {
1151 if (!Parser::ParseStatic(info)) return false;
Ben Murdochc5610432016-08-08 18:44:38 +01001152 if (!Compiler::Analyze(info)) return false;
1153 DCHECK_NOT_NULL(info->literal());
1154 DCHECK_NOT_NULL(info->scope());
1155 return true;
Ben Murdochda12d292016-06-02 14:46:10 +01001156}
1157
1158bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
1159 if (function->is_compiled()) return true;
Ben Murdochc5610432016-08-08 18:44:38 +01001160 Isolate* isolate = function->GetIsolate();
1161 DCHECK(AllowCompilation::IsAllowed(isolate));
1162
1163 // Start a compilation.
Ben Murdochda12d292016-06-02 14:46:10 +01001164 Handle<Code> code;
Ben Murdochc5610432016-08-08 18:44:38 +01001165 if (!GetLazyCode(function).ToHandle(&code)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001166 if (flag == CLEAR_EXCEPTION) {
Ben Murdochc5610432016-08-08 18:44:38 +01001167 isolate->clear_pending_exception();
Ben Murdochda12d292016-06-02 14:46:10 +01001168 }
1169 return false;
1170 }
Ben Murdochc5610432016-08-08 18:44:38 +01001171
1172 // Install code on closure.
Ben Murdochda12d292016-06-02 14:46:10 +01001173 function->ReplaceCode(*code);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001174 JSFunction::EnsureLiterals(function);
Ben Murdochc5610432016-08-08 18:44:38 +01001175
1176 // Check postconditions on success.
1177 DCHECK(!isolate->has_pending_exception());
1178 DCHECK(function->shared()->is_compiled());
1179 DCHECK(function->is_compiled());
1180 return true;
1181}
1182
1183bool Compiler::CompileBaseline(Handle<JSFunction> function) {
1184 Isolate* isolate = function->GetIsolate();
1185 DCHECK(AllowCompilation::IsAllowed(isolate));
1186
1187 // Start a compilation.
1188 Handle<Code> code;
1189 if (!GetBaselineCode(function).ToHandle(&code)) {
1190 // Baseline generation failed, get unoptimized code.
1191 DCHECK(function->shared()->is_compiled());
1192 code = handle(function->shared()->code());
1193 isolate->clear_pending_exception();
1194 }
1195
1196 // Install code on closure.
1197 function->ReplaceCode(*code);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001198 JSFunction::EnsureLiterals(function);
Ben Murdochc5610432016-08-08 18:44:38 +01001199
1200 // Check postconditions on success.
1201 DCHECK(!isolate->has_pending_exception());
1202 DCHECK(function->shared()->is_compiled());
Ben Murdochda12d292016-06-02 14:46:10 +01001203 DCHECK(function->is_compiled());
1204 return true;
1205}
1206
1207bool Compiler::CompileOptimized(Handle<JSFunction> function,
1208 ConcurrencyMode mode) {
Ben Murdochc5610432016-08-08 18:44:38 +01001209 if (function->IsOptimized()) return true;
1210 Isolate* isolate = function->GetIsolate();
1211 DCHECK(AllowCompilation::IsAllowed(isolate));
1212
1213 // Start a compilation.
Ben Murdochda12d292016-06-02 14:46:10 +01001214 Handle<Code> code;
Ben Murdochc5610432016-08-08 18:44:38 +01001215 if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001216 // Optimization failed, get unoptimized code.
Ben Murdochc5610432016-08-08 18:44:38 +01001217 DCHECK(!isolate->has_pending_exception());
1218 if (function->shared()->is_compiled()) {
1219 code = handle(function->shared()->code(), isolate);
1220 } else {
1221 Zone zone(isolate->allocator());
1222 ParseInfo parse_info(&zone, function);
1223 CompilationInfo info(&parse_info, function);
1224 if (!GetUnoptimizedCode(&info).ToHandle(&code)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001225 return false;
1226 }
1227 }
Ben Murdochda12d292016-06-02 14:46:10 +01001228 }
1229
Ben Murdochc5610432016-08-08 18:44:38 +01001230 // Install code on closure.
1231 function->ReplaceCode(*code);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001232 JSFunction::EnsureLiterals(function);
Ben Murdochc5610432016-08-08 18:44:38 +01001233
1234 // Check postconditions on success.
1235 DCHECK(!isolate->has_pending_exception());
1236 DCHECK(function->shared()->is_compiled());
1237 DCHECK(function->is_compiled());
Ben Murdochda12d292016-06-02 14:46:10 +01001238 return true;
1239}
1240
1241bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
Ben Murdochc5610432016-08-08 18:44:38 +01001242 Isolate* isolate = function->GetIsolate();
1243 DCHECK(AllowCompilation::IsAllowed(isolate));
1244
1245 // Start a compilation.
1246 Zone zone(isolate->allocator());
1247 ParseInfo parse_info(&zone, function);
1248 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
1249 if (IsEvalToplevel(handle(function->shared()))) {
1250 parse_info.set_eval();
1251 if (function->context()->IsNativeContext()) parse_info.set_global();
1252 parse_info.set_toplevel();
1253 parse_info.set_allow_lazy_parsing(false);
1254 parse_info.set_lazy(false);
Ben Murdochda12d292016-06-02 14:46:10 +01001255 }
Ben Murdochc5610432016-08-08 18:44:38 +01001256 info.MarkAsDebug();
1257 if (GetUnoptimizedCode(&info).is_null()) {
1258 isolate->clear_pending_exception();
1259 return false;
1260 }
1261
1262 // Check postconditions on success.
1263 DCHECK(!isolate->has_pending_exception());
1264 DCHECK(function->shared()->is_compiled());
1265 DCHECK(function->shared()->HasDebugCode());
1266 return true;
Ben Murdochda12d292016-06-02 14:46:10 +01001267}
1268
1269bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
Ben Murdochc5610432016-08-08 18:44:38 +01001270 Isolate* isolate = shared->GetIsolate();
1271 DCHECK(AllowCompilation::IsAllowed(isolate));
1272
1273 // Start a compilation.
1274 Zone zone(isolate->allocator());
1275 ParseInfo parse_info(&zone, shared);
1276 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdochda12d292016-06-02 14:46:10 +01001277 DCHECK(shared->allows_lazy_compilation_without_context());
1278 DCHECK(!IsEvalToplevel(shared));
Ben Murdochc5610432016-08-08 18:44:38 +01001279 info.MarkAsDebug();
1280 if (GetUnoptimizedCode(&info).is_null()) {
1281 isolate->clear_pending_exception();
1282 return false;
1283 }
1284
1285 // Check postconditions on success.
1286 DCHECK(!isolate->has_pending_exception());
1287 DCHECK(shared->is_compiled());
1288 DCHECK(shared->HasDebugCode());
1289 return true;
1290}
1291
1292MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
1293 Isolate* isolate = script->GetIsolate();
1294 DCHECK(AllowCompilation::IsAllowed(isolate));
1295
1296 // In order to ensure that live edit function info collection finds the newly
1297 // generated shared function infos, clear the script's list temporarily
1298 // and restore it at the end of this method.
1299 Handle<Object> old_function_infos(script->shared_function_infos(), isolate);
1300 script->set_shared_function_infos(Smi::FromInt(0));
1301
1302 // Start a compilation.
1303 Zone zone(isolate->allocator());
1304 ParseInfo parse_info(&zone, script);
1305 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
1306 parse_info.set_global();
1307 info.MarkAsDebug();
1308
1309 // TODO(635): support extensions.
1310 const bool compilation_succeeded = !CompileToplevel(&info).is_null();
1311 Handle<JSArray> infos;
1312 if (compilation_succeeded) {
1313 // Check postconditions on success.
1314 DCHECK(!isolate->has_pending_exception());
1315 infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1316 &zone, isolate);
1317 }
1318
1319 // Restore the original function info list in order to remain side-effect
1320 // free as much as possible, since some code expects the old shared function
1321 // infos to stick around.
1322 script->set_shared_function_infos(*old_function_infos);
1323
1324 return infos;
Ben Murdochda12d292016-06-02 14:46:10 +01001325}
1326
1327// TODO(turbofan): In the future, unoptimized code with deopt support could
1328// be generated lazily once deopt is triggered.
1329bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
1330 DCHECK_NOT_NULL(info->literal());
Ben Murdochc5610432016-08-08 18:44:38 +01001331 DCHECK_NOT_NULL(info->scope());
Ben Murdochda12d292016-06-02 14:46:10 +01001332 Handle<SharedFunctionInfo> shared = info->shared_info();
1333 if (!shared->has_deoptimization_support()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001334 Zone zone(info->isolate()->allocator());
1335 CompilationInfo unoptimized(info->parse_info(), info->closure());
Ben Murdochda12d292016-06-02 14:46:10 +01001336 unoptimized.EnableDeoptimizationSupport();
Ben Murdochc5610432016-08-08 18:44:38 +01001337
Ben Murdoch61f157c2016-09-16 13:49:30 +01001338 // TODO(4280): For now we do not switch generators or async functions to
1339 // baseline code because there might be suspended activations stored in
1340 // generator objects on the heap. We could eventually go directly to
1341 // TurboFan in this case.
1342 if (shared->is_resumable()) return false;
Ben Murdochc5610432016-08-08 18:44:38 +01001343
1344 // TODO(4280): For now we disable switching to baseline code in the presence
1345 // of interpreter activations of the given function. The reasons are:
1346 // 1) The debugger assumes each function is either full-code or bytecode.
1347 // 2) The underlying bytecode is cleared below, breaking stack unwinding.
1348 // The expensive check for activations only needs to be done when the given
1349 // function has bytecode, otherwise we can be sure there are no activations.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001350 if (shared->HasBytecodeArray()) {
1351 InterpreterActivationsFinder activations_finder(*shared);
1352 if (HasInterpreterActivations(info->isolate(), &activations_finder)) {
1353 return false;
1354 }
Ben Murdochc5610432016-08-08 18:44:38 +01001355 }
1356
Ben Murdochda12d292016-06-02 14:46:10 +01001357 // If the current code has reloc info for serialization, also include
1358 // reloc info for serialization for the new code, so that deopt support
1359 // can be added without losing IC state.
1360 if (shared->code()->kind() == Code::FUNCTION &&
1361 shared->code()->has_reloc_info_for_serialization()) {
1362 unoptimized.PrepareForSerializing();
1363 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001364 EnsureFeedbackMetadata(&unoptimized);
Ben Murdochda12d292016-06-02 14:46:10 +01001365 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1366
Ben Murdochc5610432016-08-08 18:44:38 +01001367 // TODO(4280): For now we play it safe and remove the bytecode array when we
1368 // switch to baseline code. We might consider keeping around the bytecode so
1369 // that it can be used as the "source of truth" eventually.
1370 shared->ClearBytecodeArray();
Ben Murdochda12d292016-06-02 14:46:10 +01001371
1372 // The scope info might not have been set if a lazily compiled
1373 // function is inlined before being called for the first time.
1374 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
Ben Murdochc5610432016-08-08 18:44:38 +01001375 InstallSharedScopeInfo(info, shared);
Ben Murdochda12d292016-06-02 14:46:10 +01001376 }
1377
Ben Murdochc5610432016-08-08 18:44:38 +01001378 // Install compilation result on the shared function info
1379 shared->EnableDeoptimizationSupport(*unoptimized.code());
1380
Ben Murdochda12d292016-06-02 14:46:10 +01001381 // The existing unoptimized code was replaced with the new one.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001382 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
1383 &unoptimized);
Ben Murdochda12d292016-06-02 14:46:10 +01001384 }
1385 return true;
1386}
1387
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001388MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1389 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001390 Handle<Context> context, LanguageMode language_mode,
Ben Murdochc5610432016-08-08 18:44:38 +01001391 ParseRestriction restriction, int eval_scope_position, int eval_position,
1392 int line_offset, int column_offset, Handle<Object> script_name,
1393 ScriptOriginOptions options) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001394 Isolate* isolate = source->GetIsolate();
1395 int source_length = source->length();
1396 isolate->counters()->total_eval_size()->Increment(source_length);
1397 isolate->counters()->total_compile_size()->Increment(source_length);
1398
1399 CompilationCache* compilation_cache = isolate->compilation_cache();
1400 MaybeHandle<SharedFunctionInfo> maybe_shared_info =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401 compilation_cache->LookupEval(source, outer_info, context, language_mode,
Ben Murdochc5610432016-08-08 18:44:38 +01001402 eval_scope_position);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001403 Handle<SharedFunctionInfo> shared_info;
1404
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001405 Handle<Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406 if (!maybe_shared_info.ToHandle(&shared_info)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001407 script = isolate->factory()->NewScript(source);
1408 if (!script_name.is_null()) {
1409 script->set_name(*script_name);
1410 script->set_line_offset(line_offset);
1411 script->set_column_offset(column_offset);
1412 }
1413 script->set_origin_options(options);
Ben Murdochc5610432016-08-08 18:44:38 +01001414 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1415 Script::SetEvalOrigin(script, outer_info, eval_position);
1416
Ben Murdochda12d292016-06-02 14:46:10 +01001417 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001418 ParseInfo parse_info(&zone, script);
Ben Murdochc5610432016-08-08 18:44:38 +01001419 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001420 parse_info.set_eval();
1421 if (context->IsNativeContext()) parse_info.set_global();
1422 parse_info.set_language_mode(language_mode);
1423 parse_info.set_parse_restriction(restriction);
1424 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001425
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426 shared_info = CompileToplevel(&info);
1427
1428 if (shared_info.is_null()) {
1429 return MaybeHandle<JSFunction>();
1430 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 // If caller is strict mode, the result must be in strict mode as well.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001432 DCHECK(is_sloppy(language_mode) ||
1433 is_strict(shared_info->language_mode()));
1434 compilation_cache->PutEval(source, outer_info, context, shared_info,
Ben Murdochc5610432016-08-08 18:44:38 +01001435 eval_scope_position);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001437 }
1438
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001439 Handle<JSFunction> result =
1440 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1441 shared_info, context, NOT_TENURED);
1442
1443 // OnAfterCompile has to be called after we create the JSFunction, which we
1444 // may require to recompile the eval for debugging, if we find a function
1445 // that contains break points in the eval script.
1446 isolate->debug()->OnAfterCompile(script);
1447
1448 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449}
1450
Ben Murdochda12d292016-06-02 14:46:10 +01001451Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001452 Handle<String> source, Handle<Object> script_name, int line_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001453 int column_offset, ScriptOriginOptions resource_options,
1454 Handle<Object> source_map_url, Handle<Context> context,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455 v8::Extension* extension, ScriptData** cached_data,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001456 ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
1457 bool is_module) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001458 Isolate* isolate = source->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001459 if (compile_options == ScriptCompiler::kNoCompileOptions) {
1460 cached_data = NULL;
1461 } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1462 compile_options == ScriptCompiler::kProduceCodeCache) {
1463 DCHECK(cached_data && !*cached_data);
1464 DCHECK(extension == NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001465 DCHECK(!isolate->debug()->is_loaded());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466 } else {
1467 DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1468 compile_options == ScriptCompiler::kConsumeCodeCache);
1469 DCHECK(cached_data && *cached_data);
1470 DCHECK(extension == NULL);
1471 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 int source_length = source->length();
1473 isolate->counters()->total_load_size()->Increment(source_length);
1474 isolate->counters()->total_compile_size()->Increment(source_length);
1475
Ben Murdochda12d292016-06-02 14:46:10 +01001476 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001477 CompilationCache* compilation_cache = isolate->compilation_cache();
1478
1479 // Do a lookup in the compilation cache but not for extensions.
1480 MaybeHandle<SharedFunctionInfo> maybe_result;
1481 Handle<SharedFunctionInfo> result;
1482 if (extension == NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001483 // First check per-isolate compilation cache.
1484 maybe_result = compilation_cache->LookupScript(
1485 source, script_name, line_offset, column_offset, resource_options,
1486 context, language_mode);
1487 if (maybe_result.is_null() && FLAG_serialize_toplevel &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001488 compile_options == ScriptCompiler::kConsumeCodeCache &&
1489 !isolate->debug()->is_loaded()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490 // Then check cached code provided by embedder.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001492 RuntimeCallTimerScope runtimeTimer(isolate,
1493 &RuntimeCallStats::CompileDeserialize);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001494 TRACE_EVENT0("v8", "V8.CompileDeserialize");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001495 Handle<SharedFunctionInfo> result;
1496 if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1497 .ToHandle(&result)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001498 // Promote to per-isolate compilation cache.
1499 compilation_cache->PutScript(source, context, language_mode, result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001500 return result;
1501 }
1502 // Deserializer failed. Fall through to compile.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 }
1504 }
1505
1506 base::ElapsedTimer timer;
1507 if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
1508 compile_options == ScriptCompiler::kProduceCodeCache) {
1509 timer.Start();
1510 }
1511
Ben Murdochc5610432016-08-08 18:44:38 +01001512 if (!maybe_result.ToHandle(&result) ||
1513 (FLAG_serialize_toplevel &&
1514 compile_options == ScriptCompiler::kProduceCodeCache)) {
1515 // No cache entry found, or embedder wants a code cache. Compile the script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516
1517 // Create a script object describing the script to be compiled.
1518 Handle<Script> script = isolate->factory()->NewScript(source);
1519 if (natives == NATIVES_CODE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001520 script->set_type(Script::TYPE_NATIVE);
1521 script->set_hide_source(true);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001522 } else if (natives == EXTENSION_CODE) {
1523 script->set_type(Script::TYPE_EXTENSION);
1524 script->set_hide_source(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525 }
1526 if (!script_name.is_null()) {
1527 script->set_name(*script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528 script->set_line_offset(line_offset);
1529 script->set_column_offset(column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001530 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531 script->set_origin_options(resource_options);
1532 if (!source_map_url.is_null()) {
1533 script->set_source_mapping_url(*source_map_url);
1534 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535
1536 // Compile the function and add it to the cache.
Ben Murdochda12d292016-06-02 14:46:10 +01001537 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001538 ParseInfo parse_info(&zone, script);
Ben Murdochc5610432016-08-08 18:44:38 +01001539 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdochda12d292016-06-02 14:46:10 +01001540 if (is_module) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001541 parse_info.set_module();
1542 } else {
1543 parse_info.set_global();
1544 }
1545 if (compile_options != ScriptCompiler::kNoCompileOptions) {
1546 parse_info.set_cached_data(cached_data);
1547 }
1548 parse_info.set_compile_options(compile_options);
1549 parse_info.set_extension(extension);
1550 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551 if (FLAG_serialize_toplevel &&
1552 compile_options == ScriptCompiler::kProduceCodeCache) {
1553 info.PrepareForSerializing();
1554 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001556 parse_info.set_language_mode(
Ben Murdochc5610432016-08-08 18:44:38 +01001557 static_cast<LanguageMode>(parse_info.language_mode() | language_mode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001558 result = CompileToplevel(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559 if (extension == NULL && !result.is_null()) {
1560 compilation_cache->PutScript(source, context, language_mode, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561 if (FLAG_serialize_toplevel &&
1562 compile_options == ScriptCompiler::kProduceCodeCache) {
1563 HistogramTimerScope histogram_timer(
1564 isolate->counters()->compile_serialize());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001565 RuntimeCallTimerScope runtimeTimer(isolate,
1566 &RuntimeCallStats::CompileSerialize);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001567 TRACE_EVENT0("v8", "V8.CompileSerialize");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001568 *cached_data = CodeSerializer::Serialize(isolate, result, source);
1569 if (FLAG_profile_deserialization) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001570 PrintF("[Compiling and serializing took %0.3f ms]\n",
1571 timer.Elapsed().InMillisecondsF());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001572 }
1573 }
1574 }
1575
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 if (result.is_null()) {
1577 isolate->ReportPendingMessages();
1578 } else {
1579 isolate->debug()->OnAfterCompile(script);
1580 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001581 } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1582 result->ResetForNewContext(isolate->heap()->global_ic_age());
1583 }
1584 return result;
1585}
1586
Ben Murdochda12d292016-06-02 14:46:10 +01001587Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 Handle<Script> script, ParseInfo* parse_info, int source_length) {
1589 Isolate* isolate = script->GetIsolate();
1590 // TODO(titzer): increment the counters in caller.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001591 isolate->counters()->total_load_size()->Increment(source_length);
1592 isolate->counters()->total_compile_size()->Increment(source_length);
1593
Ben Murdochda12d292016-06-02 14:46:10 +01001594 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595 parse_info->set_language_mode(
1596 static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1597
Ben Murdochc5610432016-08-08 18:44:38 +01001598 CompilationInfo compile_info(parse_info, Handle<JSFunction>::null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001599
1600 // The source was parsed lazily, so compiling for debugging is not possible.
1601 DCHECK(!compile_info.is_debug());
1602
1603 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
1604 if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
1605 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001606}
1607
1608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001609Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001610 FunctionLiteral* literal, Handle<Script> script,
1611 CompilationInfo* outer_info) {
1612 // Precondition: code has been parsed and scopes have been analyzed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613 Isolate* isolate = outer_info->isolate();
1614 MaybeHandle<SharedFunctionInfo> maybe_existing;
Ben Murdochc5610432016-08-08 18:44:38 +01001615
1616 // Find any previously allocated shared function info for the given literal.
1617 if (outer_info->shared_info()->never_compiled()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618 // On the first compile, there are no existing shared function info for
1619 // inner functions yet, so do not try to find them. All bets are off for
1620 // live edit though.
Ben Murdochda12d292016-06-02 14:46:10 +01001621 SLOW_DCHECK(script->FindSharedFunctionInfo(literal).is_null() ||
1622 isolate->debug()->live_edit_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001623 } else {
1624 maybe_existing = script->FindSharedFunctionInfo(literal);
1625 }
Ben Murdochc5610432016-08-08 18:44:38 +01001626
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001627 // We found an existing shared function info. If it's already compiled,
1628 // don't worry about compiling it, and simply return it. If it's not yet
1629 // compiled, continue to decide whether to eagerly compile.
1630 // Carry on if we are compiling eager to obtain code for debugging,
1631 // unless we already have code with debut break slots.
1632 Handle<SharedFunctionInfo> existing;
1633 if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001634 DCHECK(!existing->is_toplevel());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635 if (!outer_info->is_debug() || existing->HasDebugCode()) {
1636 return existing;
1637 }
1638 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001639
Ben Murdochda12d292016-06-02 14:46:10 +01001640 // Allocate a shared function info object.
1641 Handle<SharedFunctionInfo> result;
1642 if (!maybe_existing.ToHandle(&result)) {
1643 result = NewSharedFunctionInfoForLiteral(isolate, literal, script);
1644 result->set_is_toplevel(false);
Ben Murdochc5610432016-08-08 18:44:38 +01001645
1646 // If the outer function has been compiled before, we cannot be sure that
1647 // shared function info for this function literal has been created for the
1648 // first time. It may have already been compiled previously.
1649 result->set_never_compiled(outer_info->shared_info()->never_compiled());
Ben Murdochda12d292016-06-02 14:46:10 +01001650 }
1651
1652 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653 ParseInfo parse_info(&zone, script);
Ben Murdochc5610432016-08-08 18:44:38 +01001654 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001655 parse_info.set_literal(literal);
Ben Murdochda12d292016-06-02 14:46:10 +01001656 parse_info.set_shared_info(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001657 parse_info.set_scope(literal->scope());
1658 parse_info.set_language_mode(literal->scope()->language_mode());
1659 if (outer_info->will_serialize()) info.PrepareForSerializing();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001660 if (outer_info->is_debug()) info.MarkAsDebug();
1661
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001662 // Determine if the function can be lazily compiled. This is necessary to
1663 // allow some of our builtin JS files to be lazily compiled. These
1664 // builtins cannot be handled lazily by the parser, since we have to know
1665 // if a function uses the special natives syntax, which is something the
1666 // parser records.
1667 // If the debugger requests compilation for break points, we cannot be
1668 // aggressive about lazy compilation, because it might trigger compilation
1669 // of functions without an outer context when setting a breakpoint through
1670 // Debug::FindSharedFunctionInfoInScript.
Ben Murdochc5610432016-08-08 18:44:38 +01001671 bool allow_lazy = literal->AllowsLazyCompilation() && !info.is_debug();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001672 bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001673
Ben Murdochda12d292016-06-02 14:46:10 +01001674 // Consider compiling eagerly when targeting the code cache.
1675 lazy &= !(FLAG_serialize_eager && info.will_serialize());
1676
1677 // Consider compiling eagerly when compiling bytecode for Ignition.
1678 lazy &=
1679 !(FLAG_ignition && FLAG_ignition_eager && !isolate->serializer_enabled());
1680
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001681 // Generate code
Ben Murdoch097c5b22016-05-18 11:27:45 +01001682 TimerEventScope<TimerEventCompileCode> timer(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001683 RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::CompileCode);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001684 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001685 if (lazy) {
Ben Murdochda12d292016-06-02 14:46:10 +01001686 info.SetCode(isolate->builtins()->CompileLazy());
Ben Murdochc5610432016-08-08 18:44:38 +01001687 } else if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001688 // Code generation will ensure that the feedback vector is present and
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001689 // appropriately sized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001690 DCHECK(!info.code().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001691 if (literal->should_eager_compile() &&
1692 literal->should_be_used_once_hint()) {
1693 info.code()->MarkToBeExecutedOnce(isolate);
1694 }
Ben Murdochc5610432016-08-08 18:44:38 +01001695 // Update the shared function info with the scope info.
1696 InstallSharedScopeInfo(&info, result);
Ben Murdochda12d292016-06-02 14:46:10 +01001697 // Install compilation result on the shared function info.
Ben Murdochc5610432016-08-08 18:44:38 +01001698 InstallSharedCompilationResult(&info, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001699 } else {
1700 return Handle<SharedFunctionInfo>::null();
1701 }
1702
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001703 if (maybe_existing.is_null()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001704 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001705 }
Ben Murdochda12d292016-06-02 14:46:10 +01001706
1707 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001708}
1709
Ben Murdoch097c5b22016-05-18 11:27:45 +01001710Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
1711 v8::Extension* extension, Handle<String> name) {
1712 Isolate* isolate = name->GetIsolate();
1713 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1714
1715 // Compute the function template for the native function.
1716 v8::Local<v8::FunctionTemplate> fun_template =
1717 extension->GetNativeFunctionTemplate(v8_isolate,
1718 v8::Utils::ToLocal(name));
1719 DCHECK(!fun_template.IsEmpty());
1720
1721 // Instantiate the function and create a shared function info from it.
1722 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
1723 *fun_template->GetFunction(v8_isolate->GetCurrentContext())
1724 .ToLocalChecked()));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001725 Handle<Code> code = Handle<Code>(fun->shared()->code());
1726 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1727 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
Ben Murdoch61f157c2016-09-16 13:49:30 +01001728 name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code,
Ben Murdochda12d292016-06-02 14:46:10 +01001729 Handle<ScopeInfo>(fun->shared()->scope_info()));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001730 shared->set_construct_stub(*construct_stub);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001731 shared->set_feedback_metadata(fun->shared()->feedback_metadata());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001732
1733 // Copy the function data to the shared function info.
1734 shared->set_function_data(fun->shared()->function_data());
1735 int parameters = fun->shared()->internal_formal_parameter_count();
1736 shared->set_internal_formal_parameter_count(parameters);
1737
1738 return shared;
1739}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001740
Ben Murdochda12d292016-06-02 14:46:10 +01001741MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1742 BailoutId osr_ast_id,
1743 JavaScriptFrame* osr_frame) {
1744 DCHECK(!osr_ast_id.IsNone());
1745 DCHECK_NOT_NULL(osr_frame);
1746 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001747}
1748
Ben Murdochc5610432016-08-08 18:44:38 +01001749void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
1750 // Take ownership of compilation job. Deleting job also tears down the zone.
1751 base::SmartPointer<CompilationJob> job(raw_job);
1752 CompilationInfo* info = job->info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001753 Isolate* isolate = info->isolate();
1754
1755 VMState<COMPILER> state(isolate);
1756 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001757 RuntimeCallTimerScope runtimeTimer(isolate,
1758 &RuntimeCallStats::RecompileSynchronous);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001759 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001760
1761 Handle<SharedFunctionInfo> shared = info->shared_info();
1762 shared->code()->set_profiler_ticks(0);
1763
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001764 DCHECK(!shared->HasDebugInfo());
1765
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001766 // 1) Optimization on the concurrent thread may have failed.
1767 // 2) The function may have already been optimized by OSR. Simply continue.
1768 // Except when OSR already disabled optimization for some reason.
1769 // 3) The code may have already been invalidated due to dependency change.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 // 4) Code generation may have failed.
Ben Murdochc5610432016-08-08 18:44:38 +01001771 if (job->last_status() == CompilationJob::SUCCEEDED) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001772 if (shared->optimization_disabled()) {
1773 job->RetryOptimization(kOptimizationDisabled);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001774 } else if (info->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001775 job->RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochc5610432016-08-08 18:44:38 +01001776 } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) {
1777 job->RecordOptimizationStats();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001778 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001779 if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
1780 info->osr_ast_id()).code == nullptr) {
Ben Murdochc5610432016-08-08 18:44:38 +01001781 InsertCodeIntoOptimizedCodeMap(info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001782 }
1783 if (FLAG_trace_opt) {
1784 PrintF("[completed optimizing ");
1785 info->closure()->ShortPrint();
1786 PrintF("]\n");
1787 }
Ben Murdochda12d292016-06-02 14:46:10 +01001788 info->closure()->ReplaceCode(*info->code());
1789 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001790 }
1791 }
1792
Ben Murdochc5610432016-08-08 18:44:38 +01001793 DCHECK(job->last_status() != CompilationJob::SUCCEEDED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001794 if (FLAG_trace_opt) {
1795 PrintF("[aborted optimizing ");
1796 info->closure()->ShortPrint();
1797 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
1798 }
Ben Murdochda12d292016-06-02 14:46:10 +01001799 info->closure()->ReplaceCode(shared->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001800}
1801
Ben Murdochda12d292016-06-02 14:46:10 +01001802void Compiler::PostInstantiation(Handle<JSFunction> function,
1803 PretenureFlag pretenure) {
1804 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001805
Ben Murdochda12d292016-06-02 14:46:10 +01001806 if (FLAG_always_opt && shared->allows_lazy_compilation()) {
1807 function->MarkForOptimization();
1808 }
1809
1810 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
1811 function->context()->native_context(), BailoutId::None());
1812 if (cached.code != nullptr) {
1813 // Caching of optimized code enabled and optimized code found.
1814 DCHECK(!cached.code->marked_for_deoptimization());
1815 DCHECK(function->shared()->is_compiled());
1816 function->ReplaceCode(cached.code);
1817 }
1818
1819 if (cached.literals != nullptr) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001820 DCHECK(shared->is_compiled());
Ben Murdochda12d292016-06-02 14:46:10 +01001821 function->set_literals(cached.literals);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001822 } else if (shared->is_compiled()) {
1823 // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
1824 JSFunction::EnsureLiterals(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001825 }
1826}
1827
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001828} // namespace internal
1829} // namespace v8