blob: d6499509c05549a2c4395168972a692b2a619470 [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"
30#include "src/profiler/cpu-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031#include "src/runtime-profiler.h"
Ben Murdochda12d292016-06-02 14:46:10 +010032#include "src/snapshot/code-serializer.h"
Ben Murdochc5610432016-08-08 18:44:38 +010033#include "src/typing-asm.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035
36namespace v8 {
37namespace internal {
38
Ben Murdochf87a2032010-10-22 12:50:53 +010039
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040#define PARSE_INFO_GETTER(type, name) \
41 type CompilationInfo::name() const { \
42 CHECK(parse_info()); \
43 return parse_info()->name(); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045
46
47#define PARSE_INFO_GETTER_WITH_DEFAULT(type, name, def) \
48 type CompilationInfo::name() const { \
49 return parse_info() ? parse_info()->name() : def; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051
52
53PARSE_INFO_GETTER(Handle<Script>, script)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054PARSE_INFO_GETTER(FunctionLiteral*, literal)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr)
Ben Murdochc5610432016-08-08 18:44:38 +010056PARSE_INFO_GETTER_WITH_DEFAULT(Handle<Context>, context,
57 Handle<Context>::null())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info)
59
60#undef PARSE_INFO_GETTER
61#undef PARSE_INFO_GETTER_WITH_DEFAULT
62
Ben Murdochda12d292016-06-02 14:46:10 +010063// A wrapper around a CompilationInfo that detaches the Handles from
64// the underlying DeferredHandleScope and stores them in info_ on
65// destruction.
66class CompilationHandleScope BASE_EMBEDDED {
67 public:
68 explicit CompilationHandleScope(CompilationInfo* info)
69 : deferred_(info->isolate()), info_(info) {}
70 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
71
72 private:
73 DeferredHandleScope deferred_;
74 CompilationInfo* info_;
75};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076
Ben Murdochc5610432016-08-08 18:44:38 +010077// Helper that times a scoped region and records the elapsed time.
78struct ScopedTimer {
79 explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
80 DCHECK(location_ != NULL);
81 timer_.Start();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083
Ben Murdochc5610432016-08-08 18:44:38 +010084 ~ScopedTimer() { *location_ += timer_.Elapsed(); }
85
86 base::ElapsedTimer timer_;
87 base::TimeDelta* location_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088};
89
Ben Murdochda12d292016-06-02 14:46:10 +010090// ----------------------------------------------------------------------------
91// Implementation of CompilationInfo
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092
93bool CompilationInfo::has_shared_info() const {
94 return parse_info_ && !parse_info_->shared_info().is_null();
95}
96
Ben Murdochc5610432016-08-08 18:44:38 +010097CompilationInfo::CompilationInfo(ParseInfo* parse_info,
98 Handle<JSFunction> closure)
99 : CompilationInfo(parse_info, {}, Code::ComputeFlags(Code::FUNCTION), BASE,
100 parse_info->isolate(), parse_info->zone()) {
101 closure_ = closure;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400103 // Compiling for the snapshot typically results in different code than
104 // compiling later on. This means that code recompiled with deoptimization
105 // support won't be "equivalent" (as defined by SharedFunctionInfo::
106 // EnableDeoptimizationSupport), so it will replace the old code and all
107 // its type feedback. To avoid this, always compile functions in the snapshot
108 // with deoptimization support.
109 if (isolate_->serializer_enabled()) EnableDeoptimizationSupport();
110
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 if (FLAG_function_context_specialization) MarkAsFunctionContextSpecializing();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 if (FLAG_turbo_inlining) MarkAsInliningEnabled();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 if (FLAG_turbo_source_positions) MarkAsSourcePositionsEnabled();
114 if (FLAG_turbo_splitting) MarkAsSplittingEnabled();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116
Ben Murdochc5610432016-08-08 18:44:38 +0100117CompilationInfo::CompilationInfo(Vector<const char> debug_name,
118 Isolate* isolate, Zone* zone,
119 Code::Flags code_flags)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100120 : CompilationInfo(nullptr, debug_name, code_flags, STUB, isolate, zone) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121
Ben Murdochc5610432016-08-08 18:44:38 +0100122CompilationInfo::CompilationInfo(ParseInfo* parse_info,
123 Vector<const char> debug_name,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100124 Code::Flags code_flags, Mode mode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 Isolate* isolate, Zone* zone)
126 : parse_info_(parse_info),
127 isolate_(isolate),
128 flags_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100129 code_flags_(code_flags),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 mode_(mode),
131 osr_ast_id_(BailoutId::None()),
132 zone_(zone),
133 deferred_handles_(nullptr),
134 dependencies_(isolate, zone),
135 bailout_reason_(kNoReason),
136 prologue_offset_(Code::kPrologueOffsetNotSet),
137 track_positions_(FLAG_hydrogen_track_positions ||
138 isolate->cpu_profiler()->is_profiling()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 parameter_count_(0),
140 optimization_id_(-1),
141 osr_expr_stack_height_(0),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100142 debug_name_(debug_name) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144CompilationInfo::~CompilationInfo() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 DisableFutureOptimization();
Ben Murdochc5610432016-08-08 18:44:38 +0100146 dependencies()->Rollback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 delete deferred_handles_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148}
149
150
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151int CompilationInfo::num_parameters() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100152 return !IsStub() ? scope()->num_parameters() : parameter_count_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153}
154
155
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156int CompilationInfo::num_parameters_including_this() const {
157 return num_parameters() + (is_this_defined() ? 1 : 0);
158}
159
160
161bool CompilationInfo::is_this_defined() const { return !IsStub(); }
162
163
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100164// Primitive functions are unlikely to be picked up by the stack-walking
165// profiler, so they trigger their own optimization when they're called
166// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
167bool CompilationInfo::ShouldSelfOptimize() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 return FLAG_crankshaft &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 !(literal()->flags() & AstProperties::kDontSelfOptimize) &&
170 !literal()->dont_optimize() &&
171 literal()->scope()->AllowsLazyCompilation() &&
Ben Murdochc5610432016-08-08 18:44:38 +0100172 !shared_info()->optimization_disabled();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176bool CompilationInfo::has_simple_parameters() {
177 return scope()->has_simple_parameters();
178}
179
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181base::SmartArrayPointer<char> CompilationInfo::GetDebugName() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100182 if (parse_info() && parse_info()->literal()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 AllowHandleDereference allow_deref;
184 return parse_info()->literal()->debug_name()->ToCString();
185 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100186 if (parse_info() && !parse_info()->shared_info().is_null()) {
187 return parse_info()->shared_info()->DebugName()->ToCString();
188 }
Ben Murdochc5610432016-08-08 18:44:38 +0100189 Vector<const char> name_vec = debug_name_;
190 if (name_vec.is_empty()) name_vec = ArrayVector("unknown");
191 base::SmartArrayPointer<char> name(new char[name_vec.length() + 1]);
192 memcpy(name.get(), name_vec.start(), name_vec.length());
193 name[name_vec.length()] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 return name;
195}
196
Ben Murdochda12d292016-06-02 14:46:10 +0100197StackFrame::Type CompilationInfo::GetOutputStackFrameType() const {
198 switch (output_code_kind()) {
199 case Code::STUB:
200 case Code::BYTECODE_HANDLER:
201 case Code::HANDLER:
202 case Code::BUILTIN:
203 return StackFrame::STUB;
204 case Code::WASM_FUNCTION:
205 return StackFrame::WASM;
206 case Code::JS_TO_WASM_FUNCTION:
207 return StackFrame::JS_TO_WASM;
208 case Code::WASM_TO_JS_FUNCTION:
209 return StackFrame::WASM_TO_JS;
210 default:
211 UNIMPLEMENTED();
212 return StackFrame::NONE;
213 }
214}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215
Ben Murdochc5610432016-08-08 18:44:38 +0100216int CompilationInfo::GetDeclareGlobalsFlags() const {
217 DCHECK(DeclareGlobalsLanguageMode::is_valid(parse_info()->language_mode()));
218 return DeclareGlobalsEvalFlag::encode(parse_info()->is_eval()) |
219 DeclareGlobalsNativeFlag::encode(parse_info()->is_native()) |
220 DeclareGlobalsLanguageMode::encode(parse_info()->language_mode());
221}
222
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
Ben Murdochc5610432016-08-08 18:44:38 +0100224 return is_sloppy(parse_info()->language_mode()) && !parse_info()->is_native();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100225}
226
Ben Murdochda12d292016-06-02 14:46:10 +0100227#if DEBUG
228void CompilationInfo::PrintAstForTesting() {
229 PrintF("--- Source from AST ---\n%s\n",
230 PrettyPrinter(isolate()).PrintProgram(literal()));
231}
232#endif
233
234// ----------------------------------------------------------------------------
Ben Murdochc5610432016-08-08 18:44:38 +0100235// Implementation of CompilationJob
Ben Murdochb8e0da22011-05-16 14:20:40 +0100236
Ben Murdochc5610432016-08-08 18:44:38 +0100237CompilationJob::Status CompilationJob::CreateGraph() {
238 DisallowJavascriptExecution no_js(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 DCHECK(info()->IsOptimizing());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100240
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400241 if (FLAG_trace_opt) {
242 OFStream os(stdout);
Ben Murdochc5610432016-08-08 18:44:38 +0100243 os << "[compiling method " << Brief(*info()->closure()) << " using "
244 << compiler_name_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 if (info()->is_osr()) os << " OSR";
246 os << "]" << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400247 }
248
Ben Murdochc5610432016-08-08 18:44:38 +0100249 // Delegate to the underlying implementation.
250 DCHECK_EQ(SUCCEEDED, last_status());
251 ScopedTimer t(&time_taken_to_create_graph_);
252 return SetLastStatus(CreateGraphImpl());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100253}
254
Ben Murdochc5610432016-08-08 18:44:38 +0100255CompilationJob::Status CompilationJob::OptimizeGraph() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256 DisallowHeapAllocation no_allocation;
257 DisallowHandleAllocation no_handles;
258 DisallowHandleDereference no_deref;
259 DisallowCodeDependencyChange no_dependency_change;
Ben Murdoch257744e2011-11-30 15:57:28 +0000260
Ben Murdochc5610432016-08-08 18:44:38 +0100261 // Delegate to the underlying implementation.
262 DCHECK_EQ(SUCCEEDED, last_status());
263 ScopedTimer t(&time_taken_to_optimize_);
264 return SetLastStatus(OptimizeGraphImpl());
265}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266
Ben Murdochc5610432016-08-08 18:44:38 +0100267CompilationJob::Status CompilationJob::GenerateCode() {
268 DisallowCodeDependencyChange no_dependency_change;
269 DisallowJavascriptExecution no_js(isolate());
270 DCHECK(!info()->dependencies()->HasAborted());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271
Ben Murdochc5610432016-08-08 18:44:38 +0100272 // Delegate to the underlying implementation.
273 DCHECK_EQ(SUCCEEDED, last_status());
274 ScopedTimer t(&time_taken_to_codegen_);
275 return SetLastStatus(GenerateCodeImpl());
Steve Block6ded16b2010-05-10 14:33:55 +0100276}
Steve Block6ded16b2010-05-10 14:33:55 +0100277
278
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279namespace {
280
281void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
282 Handle<Code> code) {
283 Handle<WeakCell> cell = Code::WeakCellFor(code);
284 Heap* heap = isolate->heap();
285 Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
286 dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
287 heap->AddWeakObjectToCodeDependency(object, dep);
288}
289
Ben Murdochc5610432016-08-08 18:44:38 +0100290} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291
Ben Murdochc5610432016-08-08 18:44:38 +0100292void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
294 Isolate* const isolate = code->GetIsolate();
295 DCHECK(code->is_optimized_code());
296 std::vector<Handle<Map>> maps;
297 std::vector<Handle<HeapObject>> objects;
298 {
299 DisallowHeapAllocation no_gc;
300 int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
301 RelocInfo::ModeMask(RelocInfo::CELL);
302 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
303 RelocInfo::Mode mode = it.rinfo()->rmode();
304 if (mode == RelocInfo::CELL &&
305 code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
306 objects.push_back(handle(it.rinfo()->target_cell(), isolate));
307 } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
308 code->IsWeakObjectInOptimizedCode(
309 it.rinfo()->target_object())) {
310 Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
311 isolate);
312 if (object->IsMap()) {
313 maps.push_back(Handle<Map>::cast(object));
314 } else {
315 objects.push_back(object);
316 }
317 }
318 }
319 }
320 for (Handle<Map> map : maps) {
321 if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) {
322 isolate->heap()->AddRetainedMap(map);
323 }
324 Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code);
325 }
326 for (Handle<HeapObject> object : objects) {
327 AddWeakObjectToCodeDependency(isolate, object, code);
328 }
329 code->set_can_have_weak_objects(true);
330}
331
Ben Murdochc5610432016-08-08 18:44:38 +0100332void CompilationJob::RecordOptimizationStats() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 Handle<JSFunction> function = info()->closure();
334 if (!function->IsOptimized()) {
335 // Concurrent recompilation and OSR may race. Increment only once.
336 int opt_count = function->shared()->opt_count();
337 function->shared()->set_opt_count(opt_count + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000338 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF();
340 double ms_optimize = time_taken_to_optimize_.InMillisecondsF();
341 double ms_codegen = time_taken_to_codegen_.InMillisecondsF();
342 if (FLAG_trace_opt) {
343 PrintF("[optimizing ");
344 function->ShortPrint();
345 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
346 ms_codegen);
Steve Blocka7e24c12009-10-30 11:49:00 +0000347 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 if (FLAG_trace_opt_stats) {
349 static double compilation_time = 0.0;
350 static int compiled_functions = 0;
351 static int code_size = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000352
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
354 compiled_functions++;
355 code_size += function->shared()->SourceSize();
356 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
357 compiled_functions,
358 code_size,
359 compilation_time);
360 }
361 if (FLAG_hydrogen_stats) {
362 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
363 time_taken_to_optimize_,
364 time_taken_to_codegen_);
365 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000366}
367
Ben Murdochda12d292016-06-02 14:46:10 +0100368// ----------------------------------------------------------------------------
369// Local helper methods that make up the compilation pipeline.
370
371namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +0000372
Ben Murdochc5610432016-08-08 18:44:38 +0100373bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
374 return shared->is_toplevel() && shared->script()->IsScript() &&
375 Script::cast(shared->script())->compilation_type() ==
376 Script::COMPILATION_TYPE_EVAL;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400377}
378
Ben Murdochda12d292016-06-02 14:46:10 +0100379void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Ben Murdochc5610432016-08-08 18:44:38 +0100380 CompilationInfo* info) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100381 // Log the code generation. If source information is available include
382 // script name and line number. Check explicitly whether logging is
383 // enabled as finding the line number is not free.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384 if (info->isolate()->logger()->is_logging_code_events() ||
385 info->isolate()->cpu_profiler()->is_profiling()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100386 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387 Handle<Script> script = info->parse_info()->script();
Ben Murdochc5610432016-08-08 18:44:38 +0100388 Handle<AbstractCode> abstract_code =
389 info->has_bytecode_array()
390 ? Handle<AbstractCode>::cast(info->bytecode_array())
391 : Handle<AbstractCode>::cast(info->code());
Ben Murdochda12d292016-06-02 14:46:10 +0100392 if (abstract_code.is_identical_to(
393 info->isolate()->builtins()->CompileLazy())) {
Steve Block44f0eee2011-05-26 01:26:41 +0100394 return;
Andrei Popescu31002712010-02-23 13:46:05 +0000395 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
397 int column_num =
398 Script::GetColumnNumber(script, shared->start_position()) + 1;
399 String* script_name = script->name()->IsString()
400 ? String::cast(script->name())
401 : info->isolate()->heap()->empty_string();
402 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
403 PROFILE(info->isolate(),
Ben Murdochc5610432016-08-08 18:44:38 +0100404 CodeCreateEvent(log_tag, *abstract_code, *shared, script_name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 line_num, column_num));
Andrei Popescu31002712010-02-23 13:46:05 +0000406 }
407}
Andrei Popescu31002712010-02-23 13:46:05 +0000408
Ben Murdochda12d292016-06-02 14:46:10 +0100409void EnsureFeedbackVector(CompilationInfo* info) {
Ben Murdochc5610432016-08-08 18:44:38 +0100410 DCHECK(info->has_shared_info());
Ben Murdochda12d292016-06-02 14:46:10 +0100411
412 // If no type feedback vector exists, we create one now. At this point the
413 // AstNumbering pass has already run. Note the snapshot can contain outdated
414 // vectors for a different configuration, hence we also recreate a new vector
415 // when the function is not compiled (i.e. no code was serialized).
416 if (info->shared_info()->feedback_vector()->is_empty() ||
417 !info->shared_info()->is_compiled()) {
418 Handle<TypeFeedbackMetadata> feedback_metadata = TypeFeedbackMetadata::New(
419 info->isolate(), info->literal()->feedback_vector_spec());
420 Handle<TypeFeedbackVector> feedback_vector =
421 TypeFeedbackVector::New(info->isolate(), feedback_metadata);
422 info->shared_info()->set_feedback_vector(*feedback_vector);
423 }
424
425 // It's very important that recompiles do not alter the structure of the type
426 // feedback vector. Verify that the structure fits the function literal.
427 CHECK(!info->shared_info()->feedback_vector()->metadata()->SpecDiffersFrom(
428 info->literal()->feedback_vector_spec()));
429}
430
Ben Murdochda12d292016-06-02 14:46:10 +0100431bool UseIgnition(CompilationInfo* info) {
Ben Murdochc5610432016-08-08 18:44:38 +0100432 if (info->is_debug()) return false;
433 if (info->shared_info()->is_resumable() && !FLAG_ignition_generators) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 return false;
435 }
436
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000437 // Checks whether top level functions should be passed by the filter.
Ben Murdochda12d292016-06-02 14:46:10 +0100438 if (info->shared_info()->is_toplevel()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 Vector<const char> filter = CStrVector(FLAG_ignition_filter);
440 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
441 }
442
443 // Finally respect the filter.
Ben Murdochda12d292016-06-02 14:46:10 +0100444 return info->shared_info()->PassesFilter(FLAG_ignition_filter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445}
446
Ben Murdochda12d292016-06-02 14:46:10 +0100447int CodeAndMetadataSize(CompilationInfo* info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100448 int size = 0;
449 if (info->has_bytecode_array()) {
450 Handle<BytecodeArray> bytecode_array = info->bytecode_array();
451 size += bytecode_array->BytecodeArraySize();
452 size += bytecode_array->constant_pool()->Size();
453 size += bytecode_array->handler_table()->Size();
454 size += bytecode_array->source_position_table()->Size();
455 } else {
456 Handle<Code> code = info->code();
457 size += code->CodeSize();
458 size += code->relocation_info()->Size();
459 size += code->deoptimization_data()->Size();
460 size += code->handler_table()->Size();
461 }
462 return size;
463}
464
Ben Murdochc5610432016-08-08 18:44:38 +0100465bool GenerateUnoptimizedCode(CompilationInfo* info) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100466 bool success;
Ben Murdochda12d292016-06-02 14:46:10 +0100467 EnsureFeedbackVector(info);
Ben Murdochc5610432016-08-08 18:44:38 +0100468 if (FLAG_validate_asm && info->scope()->asm_module()) {
469 AsmTyper typer(info->isolate(), info->zone(), *(info->script()),
470 info->literal());
471 if (FLAG_enable_simd_asmjs) {
472 typer.set_allow_simd(true);
473 }
474 if (!typer.Validate()) {
475 DCHECK(!info->isolate()->has_pending_exception());
476 PrintF("Validation of asm.js module failed: %s", typer.error_message());
477 }
478 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 if (FLAG_ignition && UseIgnition(info)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100480 success = interpreter::Interpreter::MakeBytecode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100482 success = FullCodeGenerator::MakeCode(info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100484 if (success) {
485 Isolate* isolate = info->isolate();
486 Counters* counters = isolate->counters();
Ben Murdochc5610432016-08-08 18:44:38 +0100487 // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100488 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info));
489 counters->total_baseline_compile_count()->Increment(1);
490 }
491 return success;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492}
493
Ben Murdochc5610432016-08-08 18:44:38 +0100494bool CompileUnoptimizedCode(CompilationInfo* info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
Ben Murdochc5610432016-08-08 18:44:38 +0100496 if (!Compiler::Analyze(info->parse_info()) ||
497 !GenerateUnoptimizedCode(info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498 Isolate* isolate = info->isolate();
499 if (!isolate->has_pending_exception()) isolate->StackOverflow();
500 return false;
501 }
502 return true;
503}
504
Ben Murdochc5610432016-08-08 18:44:38 +0100505void InstallSharedScopeInfo(CompilationInfo* info,
506 Handle<SharedFunctionInfo> shared) {
507 Handle<ScopeInfo> scope_info =
508 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
509 shared->set_scope_info(*scope_info);
510}
511
512void InstallSharedCompilationResult(CompilationInfo* info,
513 Handle<SharedFunctionInfo> shared) {
Ben Murdochda12d292016-06-02 14:46:10 +0100514 // Assert that we are not overwriting (possibly patched) debug code.
Ben Murdochc5610432016-08-08 18:44:38 +0100515 DCHECK(!shared->HasDebugInfo());
Ben Murdochda12d292016-06-02 14:46:10 +0100516 DCHECK(!info->code().is_null());
517 shared->ReplaceCode(*info->code());
Ben Murdochda12d292016-06-02 14:46:10 +0100518 if (info->has_bytecode_array()) {
519 DCHECK(!shared->HasBytecodeArray()); // Only compiled once.
520 shared->set_bytecode_array(*info->bytecode_array());
521 }
522}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523
Ben Murdochc5610432016-08-08 18:44:38 +0100524MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000525 VMState<COMPILER> state(info->isolate());
526 PostponeInterruptsScope postpone(info->isolate());
527
528 // Parse and update CompilationInfo with the results.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdochc5610432016-08-08 18:44:38 +0100531 DCHECK_EQ(shared->language_mode(), info->literal()->language_mode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 // Compile either unoptimized code or bytecode for the interpreter.
Ben Murdochc5610432016-08-08 18:44:38 +0100534 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535
Ben Murdochc5610432016-08-08 18:44:38 +0100536 // Update the shared function info with the scope info.
537 InstallSharedScopeInfo(info, shared);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000538
Ben Murdochda12d292016-06-02 14:46:10 +0100539 // Install compilation result on the shared function info
Ben Murdochc5610432016-08-08 18:44:38 +0100540 InstallSharedCompilationResult(info, shared);
541
542 // Record the function compilation event.
543 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000544
545 return info->code();
546}
547
Ben Murdochda12d292016-06-02 14:46:10 +0100548MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549 Handle<JSFunction> function, BailoutId osr_ast_id) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 Handle<SharedFunctionInfo> shared(function->shared());
551 DisallowHeapAllocation no_gc;
552 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
553 function->context()->native_context(), osr_ast_id);
554 if (cached.code != nullptr) {
555 // Caching of optimized code enabled and optimized code found.
556 if (cached.literals != nullptr) function->set_literals(cached.literals);
557 DCHECK(!cached.code->marked_for_deoptimization());
558 DCHECK(function->shared()->is_compiled());
559 return Handle<Code>(cached.code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000560 }
561 return MaybeHandle<Code>();
562}
563
Ben Murdochda12d292016-06-02 14:46:10 +0100564void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000565 Handle<Code> code = info->code();
566 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
567
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 // Function context specialization folds-in the function context,
569 // so no sharing can occur.
570 if (info->is_function_context_specializing()) return;
571 // Frame specialization implies function context specialization.
572 DCHECK(!info->is_frame_specializing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 // Cache optimized context-specific code.
575 Handle<JSFunction> function = info->closure();
576 Handle<SharedFunctionInfo> shared(function->shared());
577 Handle<LiteralsArray> literals(function->literals());
578 Handle<Context> native_context(function->context()->native_context());
579 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
580 literals, info->osr_ast_id());
581
582 // Do not cache (native) context-independent code compiled for OSR.
583 if (code->is_turbofanned() && info->is_osr()) return;
584
585 // Cache optimized (native) context-independent code.
586 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
587 !info->is_native_context_specializing()) {
588 DCHECK(!info->is_function_context_specializing());
589 DCHECK(info->osr_ast_id().IsNone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 }
593}
594
Ben Murdochda12d292016-06-02 14:46:10 +0100595bool Renumber(ParseInfo* parse_info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
597 parse_info->literal())) {
598 return false;
599 }
600 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info();
601 if (!shared_info.is_null()) {
602 FunctionLiteral* lit = parse_info->literal();
603 shared_info->set_ast_node_count(lit->ast_node_count());
Ben Murdochc5610432016-08-08 18:44:38 +0100604 if (lit->dont_optimize_reason() != kNoReason) {
605 shared_info->DisableOptimization(lit->dont_optimize_reason());
606 }
Ben Murdochda12d292016-06-02 14:46:10 +0100607 shared_info->set_dont_crankshaft(
608 shared_info->dont_crankshaft() ||
609 (lit->flags() & AstProperties::kDontCrankshaft));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400610 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 return true;
612}
613
Ben Murdochc5610432016-08-08 18:44:38 +0100614bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
615 bool optimization_disabled = shared->optimization_disabled();
616 bool dont_crankshaft = shared->dont_crankshaft();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617
Ben Murdochc5610432016-08-08 18:44:38 +0100618 // Check the enabling conditions for Turbofan.
619 // 1. "use asm" code.
620 bool is_turbofanable_asm =
621 FLAG_turbo_asm && shared->asm_function() && !optimization_disabled;
622
623 // 2. Fallback for features unsupported by Crankshaft.
624 bool is_unsupported_by_crankshaft_but_turbofanable =
625 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
626 !optimization_disabled;
627
628 // 3. Explicitly enabled by the command-line filter.
629 bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
630
631 return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
632 passes_turbo_filter;
633}
634
635bool GetOptimizedCodeNow(CompilationJob* job) {
636 CompilationInfo* info = job->info();
637 Isolate* isolate = info->isolate();
638
639 // Parsing is not required when optimizing from existing bytecode.
640 if (!info->is_optimizing_from_bytecode()) {
641 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
642 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000643
644 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100645 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646
Ben Murdochc5610432016-08-08 18:44:38 +0100647 if (job->CreateGraph() != CompilationJob::SUCCEEDED ||
648 job->OptimizeGraph() != CompilationJob::SUCCEEDED ||
649 job->GenerateCode() != CompilationJob::SUCCEEDED) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000650 if (FLAG_trace_opt) {
651 PrintF("[aborted optimizing ");
652 info->closure()->ShortPrint();
653 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
654 }
655 return false;
656 }
657
658 // Success!
Ben Murdochc5610432016-08-08 18:44:38 +0100659 job->RecordOptimizationStats();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 InsertCodeIntoOptimizedCodeMap(info);
Ben Murdochc5610432016-08-08 18:44:38 +0100662 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663 return true;
664}
665
Ben Murdochc5610432016-08-08 18:44:38 +0100666bool GetOptimizedCodeLater(CompilationJob* job) {
667 CompilationInfo* info = job->info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 Isolate* isolate = info->isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669
670 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000671 if (FLAG_trace_concurrent_recompilation) {
672 PrintF(" ** Compilation queue full, will retry optimizing ");
673 info->closure()->ShortPrint();
674 PrintF(" later.\n");
675 }
676 return false;
677 }
678
Ben Murdochc5610432016-08-08 18:44:38 +0100679 // All handles below this point will be allocated in a deferred handle scope
680 // that is detached and handed off to the background thread when we return.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000681 CompilationHandleScope handle_scope(info);
Ben Murdochc5610432016-08-08 18:44:38 +0100682
683 // Parsing is not required when optimizing from existing bytecode.
684 if (!info->is_optimizing_from_bytecode()) {
685 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
686 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000687
688 // Reopen handles in the new CompilationHandleScope.
689 info->ReopenHandlesInNewHandleScope();
690 info->parse_info()->ReopenHandlesInNewHandleScope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000691
692 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100693 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694
Ben Murdochc5610432016-08-08 18:44:38 +0100695 if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000696 isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697
698 if (FLAG_trace_concurrent_recompilation) {
699 PrintF(" ** Queued ");
700 info->closure()->ShortPrint();
Ben Murdochc5610432016-08-08 18:44:38 +0100701 PrintF(" for concurrent optimization.\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000702 }
703 return true;
704}
705
Ben Murdochda12d292016-06-02 14:46:10 +0100706MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
707 Compiler::ConcurrencyMode mode,
708 BailoutId osr_ast_id = BailoutId::None(),
709 JavaScriptFrame* osr_frame = nullptr) {
710 Isolate* isolate = function->GetIsolate();
711 Handle<SharedFunctionInfo> shared(function->shared(), isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712
Ben Murdochda12d292016-06-02 14:46:10 +0100713 Handle<Code> cached_code;
714 if (GetCodeFromOptimizedCodeMap(function, osr_ast_id)
715 .ToHandle(&cached_code)) {
716 if (FLAG_trace_opt) {
717 PrintF("[found optimized code for ");
718 function->ShortPrint();
719 if (!osr_ast_id.IsNone()) {
720 PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
721 }
722 PrintF("]\n");
723 }
724 return cached_code;
725 }
726
Ben Murdochc5610432016-08-08 18:44:38 +0100727 // Reset profiler ticks, function is no longer considered hot.
Ben Murdochda12d292016-06-02 14:46:10 +0100728 if (shared->is_compiled()) {
729 shared->code()->set_profiler_ticks(0);
730 }
731
Ben Murdochda12d292016-06-02 14:46:10 +0100732 VMState<COMPILER> state(isolate);
733 DCHECK(!isolate->has_pending_exception());
734 PostponeInterruptsScope postpone(isolate);
Ben Murdochc5610432016-08-08 18:44:38 +0100735 bool use_turbofan = UseTurboFan(shared);
736 base::SmartPointer<CompilationJob> job(
737 use_turbofan ? compiler::Pipeline::NewCompilationJob(function)
738 : new HCompilationJob(function));
739 CompilationInfo* info = job->info();
740 ParseInfo* parse_info = info->parse_info();
Ben Murdochda12d292016-06-02 14:46:10 +0100741
Ben Murdochc5610432016-08-08 18:44:38 +0100742 info->SetOptimizingForOsr(osr_ast_id, osr_frame);
743
744 // Do not use Crankshaft/TurboFan if we need to be able to set break points.
745 if (info->shared_info()->HasDebugInfo()) {
746 info->AbortOptimization(kFunctionBeingDebugged);
747 return MaybeHandle<Code>();
748 }
749
750 // Limit the number of times we try to optimize functions.
751 const int kMaxOptCount =
752 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
753 if (info->shared_info()->opt_count() > kMaxOptCount) {
754 info->AbortOptimization(kOptimizedTooManyTimes);
755 return MaybeHandle<Code>();
756 }
757
758 CanonicalHandleScope canonical(isolate);
759 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
760 TRACE_EVENT0("v8", "V8.OptimizeCode");
761
762 // TurboFan can optimize directly from existing bytecode.
763 if (FLAG_turbo_from_bytecode && use_turbofan &&
764 info->shared_info()->HasBytecodeArray()) {
765 info->MarkAsOptimizeFromBytecode();
766 }
767
768 if (IsEvalToplevel(shared)) {
769 parse_info->set_eval();
770 if (function->context()->IsNativeContext()) parse_info->set_global();
771 parse_info->set_toplevel();
772 parse_info->set_allow_lazy_parsing(false);
773 parse_info->set_lazy(false);
774 }
Ben Murdochda12d292016-06-02 14:46:10 +0100775
776 if (mode == Compiler::CONCURRENT) {
Ben Murdochc5610432016-08-08 18:44:38 +0100777 if (GetOptimizedCodeLater(job.get())) {
778 job.Detach(); // The background recompile job owns this now.
Ben Murdochda12d292016-06-02 14:46:10 +0100779 return isolate->builtins()->InOptimizationQueue();
780 }
781 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100782 if (GetOptimizedCodeNow(job.get())) return info->code();
Ben Murdochda12d292016-06-02 14:46:10 +0100783 }
784
785 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
786 return MaybeHandle<Code>();
787}
788
Ben Murdochc5610432016-08-08 18:44:38 +0100789class InterpreterActivationsFinder : public ThreadVisitor,
790 public OptimizedFunctionVisitor {
791 public:
792 SharedFunctionInfo* shared_;
793 bool has_activations_;
794
795 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared)
796 : shared_(shared), has_activations_(false) {}
797
798 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
799 JavaScriptFrameIterator it(isolate, top);
800 for (; !it.done() && !has_activations_; it.Advance()) {
801 JavaScriptFrame* frame = it.frame();
802 if (!frame->is_interpreted()) continue;
803 if (frame->function()->shared() == shared_) has_activations_ = true;
804 }
805 }
806
807 void VisitFunction(JSFunction* function) {
808 if (function->Inlines(shared_)) has_activations_ = true;
809 }
810
811 void EnterContext(Context* context) {}
812 void LeaveContext(Context* context) {}
813};
814
815bool HasInterpreterActivations(Isolate* isolate, SharedFunctionInfo* shared) {
816 InterpreterActivationsFinder activations_finder(shared);
817 activations_finder.VisitThread(isolate, isolate->thread_local_top());
818 isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
819 if (FLAG_turbo_from_bytecode) {
820 // If we are able to optimize functions directly from bytecode, then there
821 // might be optimized functions that rely on bytecode being around. We need
822 // to prevent switching the given function to baseline code in those cases.
823 Deoptimizer::VisitAllOptimizedFunctions(isolate, &activations_finder);
824 }
825 return activations_finder.has_activations_;
826}
827
828MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
829 Isolate* isolate = function->GetIsolate();
830 VMState<COMPILER> state(isolate);
831 PostponeInterruptsScope postpone(isolate);
832 Zone zone(isolate->allocator());
833 ParseInfo parse_info(&zone, function);
834 CompilationInfo info(&parse_info, function);
835
836 // Reset profiler ticks, function is no longer considered hot.
837 if (function->shared()->HasBytecodeArray()) {
838 function->shared()->set_profiler_ticks(0);
839 }
840
841 // Nothing left to do if the function already has baseline code.
842 if (function->shared()->code()->kind() == Code::FUNCTION) {
843 return Handle<Code>(function->shared()->code());
844 }
845
846 // We do not switch to baseline code when the debugger might have created a
847 // copy of the bytecode with break slots to be able to set break points.
848 if (function->shared()->HasDebugInfo()) {
849 return MaybeHandle<Code>();
850 }
851
852 // TODO(4280): For now we do not switch generators to baseline code because
853 // there might be suspended activations stored in generator objects on the
854 // heap. We could eventually go directly to TurboFan in this case.
855 if (function->shared()->is_generator()) {
856 return MaybeHandle<Code>();
857 }
858
859 // TODO(4280): For now we disable switching to baseline code in the presence
860 // of interpreter activations of the given function. The reasons are:
861 // 1) The debugger assumes each function is either full-code or bytecode.
862 // 2) The underlying bytecode is cleared below, breaking stack unwinding.
863 if (HasInterpreterActivations(isolate, function->shared())) {
864 if (FLAG_trace_opt) {
865 OFStream os(stdout);
866 os << "[unable to switch " << Brief(*function) << " due to activations]"
867 << std::endl;
868 }
869 return MaybeHandle<Code>();
870 }
871
872 if (FLAG_trace_opt) {
873 OFStream os(stdout);
874 os << "[switching method " << Brief(*function) << " to baseline code]"
875 << std::endl;
876 }
877
878 // Parse and update CompilationInfo with the results.
879 if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>();
880 Handle<SharedFunctionInfo> shared = info.shared_info();
881 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode());
882
883 // Compile baseline code using the full code generator.
884 if (!Compiler::Analyze(info.parse_info()) ||
885 !FullCodeGenerator::MakeCode(&info)) {
886 if (!isolate->has_pending_exception()) isolate->StackOverflow();
887 return MaybeHandle<Code>();
888 }
889
890 // TODO(4280): For now we play it safe and remove the bytecode array when we
891 // switch to baseline code. We might consider keeping around the bytecode so
892 // that it can be used as the "source of truth" eventually.
893 shared->ClearBytecodeArray();
894
895 // Update the shared function info with the scope info.
896 InstallSharedScopeInfo(&info, shared);
897
898 // Install compilation result on the shared function info
899 InstallSharedCompilationResult(&info, shared);
900
901 // Record the function compilation event.
902 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &info);
903
904 return info.code();
905}
906
Ben Murdochda12d292016-06-02 14:46:10 +0100907MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400908 Isolate* isolate = function->GetIsolate();
909 DCHECK(!isolate->has_pending_exception());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 DCHECK(!function->is_compiled());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100911 TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
912 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000913 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914
Ben Murdochc5610432016-08-08 18:44:38 +0100915 if (FLAG_turbo_cache_shared_code) {
916 Handle<Code> cached_code;
917 if (GetCodeFromOptimizedCodeMap(function, BailoutId::None())
918 .ToHandle(&cached_code)) {
919 if (FLAG_trace_opt) {
920 PrintF("[found optimized code for ");
921 function->ShortPrint();
922 PrintF(" during unoptimized compile]\n");
923 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400924 DCHECK(function->shared()->is_compiled());
Ben Murdochc5610432016-08-08 18:44:38 +0100925 return cached_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400926 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 }
928
929 if (function->shared()->is_compiled()) {
930 return Handle<Code>(function->shared()->code());
931 }
932
Ben Murdochc5610432016-08-08 18:44:38 +0100933 Zone zone(isolate->allocator());
934 ParseInfo parse_info(&zone, function);
935 CompilationInfo info(&parse_info, function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936 Handle<Code> result;
Ben Murdochc5610432016-08-08 18:44:38 +0100937 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCode(&info), Code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000938
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939 if (FLAG_always_opt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000940 Handle<Code> opt_code;
Ben Murdochda12d292016-06-02 14:46:10 +0100941 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100942 .ToHandle(&opt_code)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000943 result = opt_code;
944 }
945 }
946
947 return result;
948}
949
950
Ben Murdochda12d292016-06-02 14:46:10 +0100951Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
952 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) {
953 Handle<Code> code = isolate->builtins()->CompileLazy();
954 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate));
955 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo(
956 literal->name(), literal->materialized_literal_count(), literal->kind(),
957 code, scope_info);
958 SharedFunctionInfo::InitFromFunctionLiteral(result, literal);
959 SharedFunctionInfo::SetScript(result, script);
960 return result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000961}
962
Ben Murdochda12d292016-06-02 14:46:10 +0100963Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964 Isolate* isolate = info->isolate();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100965 TimerEventScope<TimerEventCompileCode> timer(isolate);
966 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 PostponeInterruptsScope postpone(isolate);
968 DCHECK(!isolate->native_context().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 ParseInfo* parse_info = info->parse_info();
970 Handle<Script> script = parse_info->script();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971
972 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
973 FixedArray* array = isolate->native_context()->embedder_data();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000974 script->set_context_data(array->get(v8::Context::kDebugIdIndex));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975
976 isolate->debug()->OnBeforeCompile(script);
977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000978 DCHECK(parse_info->is_eval() || parse_info->is_global() ||
979 parse_info->is_module());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 parse_info->set_toplevel();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400982
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000983 Handle<SharedFunctionInfo> result;
984
985 { VMState<COMPILER> state(info->isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 if (parse_info->literal() == NULL) {
987 // Parse the script if needed (if it's already parsed, literal() is
988 // non-NULL). If compiling for debugging, we may eagerly compile inner
989 // functions, so do not parse lazily in that case.
990 ScriptCompiler::CompileOptions options = parse_info->compile_options();
991 bool parse_allow_lazy = (options == ScriptCompiler::kConsumeParserCache ||
992 String::cast(script->source())->length() >
993 FLAG_min_preparse_length) &&
994 !info->is_debug();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995
Ben Murdochda12d292016-06-02 14:46:10 +0100996 // Consider parsing eagerly when targeting the code cache.
997 parse_allow_lazy &= !(FLAG_serialize_eager && info->will_serialize());
998
999 // Consider parsing eagerly when targeting Ignition.
1000 parse_allow_lazy &= !(FLAG_ignition && FLAG_ignition_eager &&
1001 !isolate->serializer_enabled());
1002
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003 parse_info->set_allow_lazy_parsing(parse_allow_lazy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 if (!parse_allow_lazy &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 (options == ScriptCompiler::kProduceParserCache ||
1006 options == ScriptCompiler::kConsumeParserCache)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007 // We are going to parse eagerly, but we either 1) have cached data
1008 // produced by lazy parsing or 2) are asked to generate cached data.
1009 // Eager parsing cannot benefit from cached data, and producing cached
1010 // data while parsing eagerly is not implemented.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 parse_info->set_cached_data(nullptr);
1012 parse_info->set_compile_options(ScriptCompiler::kNoCompileOptions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001014 if (!Parser::ParseStatic(parse_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015 return Handle<SharedFunctionInfo>::null();
1016 }
1017 }
1018
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 DCHECK(!info->is_debug() || !parse_info->allow_lazy_parsing());
1020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 FunctionLiteral* lit = parse_info->literal();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022
1023 // Measure how long it takes to do the compilation; only take the
1024 // rest of the function into account to avoid overlap with the
1025 // parsing statistics.
Ben Murdochc5610432016-08-08 18:44:38 +01001026 RuntimeCallTimerScope runtimeTimer(
1027 isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
1028 : &RuntimeCallStats::Compile);
1029 HistogramTimer* rate = parse_info->is_eval()
1030 ? info->isolate()->counters()->compile_eval()
1031 : info->isolate()->counters()->compile();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001032 HistogramTimerScope timer(rate);
Ben Murdochc5610432016-08-08 18:44:38 +01001033 TRACE_EVENT0("v8", parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034
Ben Murdochda12d292016-06-02 14:46:10 +01001035 // Allocate a shared function info object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Ben Murdochda12d292016-06-02 14:46:10 +01001037 result = NewSharedFunctionInfoForLiteral(isolate, lit, script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 result->set_is_toplevel(true);
Ben Murdochc5610432016-08-08 18:44:38 +01001039 if (parse_info->is_eval()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001040 // Eval scripts cannot be (re-)compiled without context.
1041 result->set_allows_lazy_compilation_without_context(false);
1042 }
Ben Murdochda12d292016-06-02 14:46:10 +01001043 parse_info->set_shared_info(result);
1044
1045 // Compile the code.
Ben Murdochc5610432016-08-08 18:44:38 +01001046 if (!CompileUnoptimizedCode(info)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001047 return Handle<SharedFunctionInfo>::null();
1048 }
1049
Ben Murdochc5610432016-08-08 18:44:38 +01001050 // Update the shared function info with the scope info.
1051 InstallSharedScopeInfo(info, result);
1052
Ben Murdochda12d292016-06-02 14:46:10 +01001053 // Install compilation result on the shared function info
Ben Murdochc5610432016-08-08 18:44:38 +01001054 InstallSharedCompilationResult(info, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001056 Handle<String> script_name =
1057 script->name()->IsString()
1058 ? Handle<String>(String::cast(script->name()))
1059 : isolate->factory()->empty_string();
Ben Murdochc5610432016-08-08 18:44:38 +01001060 Logger::LogEventsAndTags log_tag =
1061 parse_info->is_eval()
1062 ? Logger::EVAL_TAG
1063 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001064
Ben Murdochc5610432016-08-08 18:44:38 +01001065 PROFILE(isolate, CodeCreateEvent(log_tag, result->abstract_code(), *result,
1066 *script_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001067
1068 if (!script.is_null())
1069 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001070 }
1071
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001072 return result;
1073}
1074
Ben Murdochda12d292016-06-02 14:46:10 +01001075} // namespace
1076
1077// ----------------------------------------------------------------------------
1078// Implementation of Compiler
1079
1080bool Compiler::Analyze(ParseInfo* info) {
1081 DCHECK_NOT_NULL(info->literal());
1082 if (!Rewriter::Rewrite(info)) return false;
1083 if (!Scope::Analyze(info)) return false;
1084 if (!Renumber(info)) return false;
1085 DCHECK_NOT_NULL(info->scope());
1086 return true;
1087}
1088
1089bool Compiler::ParseAndAnalyze(ParseInfo* info) {
1090 if (!Parser::ParseStatic(info)) return false;
Ben Murdochc5610432016-08-08 18:44:38 +01001091 if (!Compiler::Analyze(info)) return false;
1092 DCHECK_NOT_NULL(info->literal());
1093 DCHECK_NOT_NULL(info->scope());
1094 return true;
Ben Murdochda12d292016-06-02 14:46:10 +01001095}
1096
1097bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
1098 if (function->is_compiled()) return true;
Ben Murdochc5610432016-08-08 18:44:38 +01001099 Isolate* isolate = function->GetIsolate();
1100 DCHECK(AllowCompilation::IsAllowed(isolate));
1101
1102 // Start a compilation.
Ben Murdochda12d292016-06-02 14:46:10 +01001103 Handle<Code> code;
Ben Murdochc5610432016-08-08 18:44:38 +01001104 if (!GetLazyCode(function).ToHandle(&code)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001105 if (flag == CLEAR_EXCEPTION) {
Ben Murdochc5610432016-08-08 18:44:38 +01001106 isolate->clear_pending_exception();
Ben Murdochda12d292016-06-02 14:46:10 +01001107 }
1108 return false;
1109 }
Ben Murdochc5610432016-08-08 18:44:38 +01001110
1111 // Install code on closure.
Ben Murdochda12d292016-06-02 14:46:10 +01001112 function->ReplaceCode(*code);
Ben Murdochc5610432016-08-08 18:44:38 +01001113
1114 // Check postconditions on success.
1115 DCHECK(!isolate->has_pending_exception());
1116 DCHECK(function->shared()->is_compiled());
1117 DCHECK(function->is_compiled());
1118 return true;
1119}
1120
1121bool Compiler::CompileBaseline(Handle<JSFunction> function) {
1122 Isolate* isolate = function->GetIsolate();
1123 DCHECK(AllowCompilation::IsAllowed(isolate));
1124
1125 // Start a compilation.
1126 Handle<Code> code;
1127 if (!GetBaselineCode(function).ToHandle(&code)) {
1128 // Baseline generation failed, get unoptimized code.
1129 DCHECK(function->shared()->is_compiled());
1130 code = handle(function->shared()->code());
1131 isolate->clear_pending_exception();
1132 }
1133
1134 // Install code on closure.
1135 function->ReplaceCode(*code);
1136
1137 // Check postconditions on success.
1138 DCHECK(!isolate->has_pending_exception());
1139 DCHECK(function->shared()->is_compiled());
Ben Murdochda12d292016-06-02 14:46:10 +01001140 DCHECK(function->is_compiled());
1141 return true;
1142}
1143
1144bool Compiler::CompileOptimized(Handle<JSFunction> function,
1145 ConcurrencyMode mode) {
Ben Murdochc5610432016-08-08 18:44:38 +01001146 if (function->IsOptimized()) return true;
1147 Isolate* isolate = function->GetIsolate();
1148 DCHECK(AllowCompilation::IsAllowed(isolate));
1149
1150 // Start a compilation.
Ben Murdochda12d292016-06-02 14:46:10 +01001151 Handle<Code> code;
Ben Murdochc5610432016-08-08 18:44:38 +01001152 if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001153 // Optimization failed, get unoptimized code.
Ben Murdochc5610432016-08-08 18:44:38 +01001154 DCHECK(!isolate->has_pending_exception());
1155 if (function->shared()->is_compiled()) {
1156 code = handle(function->shared()->code(), isolate);
1157 } else {
1158 Zone zone(isolate->allocator());
1159 ParseInfo parse_info(&zone, function);
1160 CompilationInfo info(&parse_info, function);
1161 if (!GetUnoptimizedCode(&info).ToHandle(&code)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001162 return false;
1163 }
1164 }
Ben Murdochda12d292016-06-02 14:46:10 +01001165 }
1166
Ben Murdochc5610432016-08-08 18:44:38 +01001167 // Install code on closure.
1168 function->ReplaceCode(*code);
1169
1170 // Check postconditions on success.
1171 DCHECK(!isolate->has_pending_exception());
1172 DCHECK(function->shared()->is_compiled());
1173 DCHECK(function->is_compiled());
Ben Murdochda12d292016-06-02 14:46:10 +01001174 return true;
1175}
1176
1177bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
Ben Murdochc5610432016-08-08 18:44:38 +01001178 Isolate* isolate = function->GetIsolate();
1179 DCHECK(AllowCompilation::IsAllowed(isolate));
1180
1181 // Start a compilation.
1182 Zone zone(isolate->allocator());
1183 ParseInfo parse_info(&zone, function);
1184 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
1185 if (IsEvalToplevel(handle(function->shared()))) {
1186 parse_info.set_eval();
1187 if (function->context()->IsNativeContext()) parse_info.set_global();
1188 parse_info.set_toplevel();
1189 parse_info.set_allow_lazy_parsing(false);
1190 parse_info.set_lazy(false);
Ben Murdochda12d292016-06-02 14:46:10 +01001191 }
Ben Murdochc5610432016-08-08 18:44:38 +01001192 info.MarkAsDebug();
1193 if (GetUnoptimizedCode(&info).is_null()) {
1194 isolate->clear_pending_exception();
1195 return false;
1196 }
1197
1198 // Check postconditions on success.
1199 DCHECK(!isolate->has_pending_exception());
1200 DCHECK(function->shared()->is_compiled());
1201 DCHECK(function->shared()->HasDebugCode());
1202 return true;
Ben Murdochda12d292016-06-02 14:46:10 +01001203}
1204
1205bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
Ben Murdochc5610432016-08-08 18:44:38 +01001206 Isolate* isolate = shared->GetIsolate();
1207 DCHECK(AllowCompilation::IsAllowed(isolate));
1208
1209 // Start a compilation.
1210 Zone zone(isolate->allocator());
1211 ParseInfo parse_info(&zone, shared);
1212 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdochda12d292016-06-02 14:46:10 +01001213 DCHECK(shared->allows_lazy_compilation_without_context());
1214 DCHECK(!IsEvalToplevel(shared));
Ben Murdochc5610432016-08-08 18:44:38 +01001215 info.MarkAsDebug();
1216 if (GetUnoptimizedCode(&info).is_null()) {
1217 isolate->clear_pending_exception();
1218 return false;
1219 }
1220
1221 // Check postconditions on success.
1222 DCHECK(!isolate->has_pending_exception());
1223 DCHECK(shared->is_compiled());
1224 DCHECK(shared->HasDebugCode());
1225 return true;
1226}
1227
1228MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
1229 Isolate* isolate = script->GetIsolate();
1230 DCHECK(AllowCompilation::IsAllowed(isolate));
1231
1232 // In order to ensure that live edit function info collection finds the newly
1233 // generated shared function infos, clear the script's list temporarily
1234 // and restore it at the end of this method.
1235 Handle<Object> old_function_infos(script->shared_function_infos(), isolate);
1236 script->set_shared_function_infos(Smi::FromInt(0));
1237
1238 // Start a compilation.
1239 Zone zone(isolate->allocator());
1240 ParseInfo parse_info(&zone, script);
1241 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
1242 parse_info.set_global();
1243 info.MarkAsDebug();
1244
1245 // TODO(635): support extensions.
1246 const bool compilation_succeeded = !CompileToplevel(&info).is_null();
1247 Handle<JSArray> infos;
1248 if (compilation_succeeded) {
1249 // Check postconditions on success.
1250 DCHECK(!isolate->has_pending_exception());
1251 infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1252 &zone, isolate);
1253 }
1254
1255 // Restore the original function info list in order to remain side-effect
1256 // free as much as possible, since some code expects the old shared function
1257 // infos to stick around.
1258 script->set_shared_function_infos(*old_function_infos);
1259
1260 return infos;
Ben Murdochda12d292016-06-02 14:46:10 +01001261}
1262
1263// TODO(turbofan): In the future, unoptimized code with deopt support could
1264// be generated lazily once deopt is triggered.
1265bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
1266 DCHECK_NOT_NULL(info->literal());
Ben Murdochc5610432016-08-08 18:44:38 +01001267 DCHECK_NOT_NULL(info->scope());
Ben Murdochda12d292016-06-02 14:46:10 +01001268 Handle<SharedFunctionInfo> shared = info->shared_info();
1269 if (!shared->has_deoptimization_support()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001270 Zone zone(info->isolate()->allocator());
1271 CompilationInfo unoptimized(info->parse_info(), info->closure());
Ben Murdochda12d292016-06-02 14:46:10 +01001272 unoptimized.EnableDeoptimizationSupport();
Ben Murdochc5610432016-08-08 18:44:38 +01001273
1274 // TODO(4280): For now we do not switch generators to baseline code because
1275 // there might be suspended activations stored in generator objects on the
1276 // heap. We could eventually go directly to TurboFan in this case.
1277 if (shared->is_generator()) return false;
1278
1279 // TODO(4280): For now we disable switching to baseline code in the presence
1280 // of interpreter activations of the given function. The reasons are:
1281 // 1) The debugger assumes each function is either full-code or bytecode.
1282 // 2) The underlying bytecode is cleared below, breaking stack unwinding.
1283 // The expensive check for activations only needs to be done when the given
1284 // function has bytecode, otherwise we can be sure there are no activations.
1285 if (shared->HasBytecodeArray() &&
1286 HasInterpreterActivations(info->isolate(), *shared)) {
1287 return false;
1288 }
1289
Ben Murdochda12d292016-06-02 14:46:10 +01001290 // If the current code has reloc info for serialization, also include
1291 // reloc info for serialization for the new code, so that deopt support
1292 // can be added without losing IC state.
1293 if (shared->code()->kind() == Code::FUNCTION &&
1294 shared->code()->has_reloc_info_for_serialization()) {
1295 unoptimized.PrepareForSerializing();
1296 }
1297 EnsureFeedbackVector(&unoptimized);
1298 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1299
Ben Murdochc5610432016-08-08 18:44:38 +01001300 // TODO(4280): For now we play it safe and remove the bytecode array when we
1301 // switch to baseline code. We might consider keeping around the bytecode so
1302 // that it can be used as the "source of truth" eventually.
1303 shared->ClearBytecodeArray();
Ben Murdochda12d292016-06-02 14:46:10 +01001304
1305 // The scope info might not have been set if a lazily compiled
1306 // function is inlined before being called for the first time.
1307 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
Ben Murdochc5610432016-08-08 18:44:38 +01001308 InstallSharedScopeInfo(info, shared);
Ben Murdochda12d292016-06-02 14:46:10 +01001309 }
1310
Ben Murdochc5610432016-08-08 18:44:38 +01001311 // Install compilation result on the shared function info
1312 shared->EnableDeoptimizationSupport(*unoptimized.code());
1313
Ben Murdochda12d292016-06-02 14:46:10 +01001314 // The existing unoptimized code was replaced with the new one.
Ben Murdochc5610432016-08-08 18:44:38 +01001315 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized);
Ben Murdochda12d292016-06-02 14:46:10 +01001316 }
1317 return true;
1318}
1319
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1321 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001322 Handle<Context> context, LanguageMode language_mode,
Ben Murdochc5610432016-08-08 18:44:38 +01001323 ParseRestriction restriction, int eval_scope_position, int eval_position,
1324 int line_offset, int column_offset, Handle<Object> script_name,
1325 ScriptOriginOptions options) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326 Isolate* isolate = source->GetIsolate();
1327 int source_length = source->length();
1328 isolate->counters()->total_eval_size()->Increment(source_length);
1329 isolate->counters()->total_compile_size()->Increment(source_length);
1330
1331 CompilationCache* compilation_cache = isolate->compilation_cache();
1332 MaybeHandle<SharedFunctionInfo> maybe_shared_info =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001333 compilation_cache->LookupEval(source, outer_info, context, language_mode,
Ben Murdochc5610432016-08-08 18:44:38 +01001334 eval_scope_position);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 Handle<SharedFunctionInfo> shared_info;
1336
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001337 Handle<Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 if (!maybe_shared_info.ToHandle(&shared_info)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 script = isolate->factory()->NewScript(source);
1340 if (!script_name.is_null()) {
1341 script->set_name(*script_name);
1342 script->set_line_offset(line_offset);
1343 script->set_column_offset(column_offset);
1344 }
1345 script->set_origin_options(options);
Ben Murdochc5610432016-08-08 18:44:38 +01001346 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1347 Script::SetEvalOrigin(script, outer_info, eval_position);
1348
Ben Murdochda12d292016-06-02 14:46:10 +01001349 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001350 ParseInfo parse_info(&zone, script);
Ben Murdochc5610432016-08-08 18:44:38 +01001351 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001352 parse_info.set_eval();
1353 if (context->IsNativeContext()) parse_info.set_global();
1354 parse_info.set_language_mode(language_mode);
1355 parse_info.set_parse_restriction(restriction);
1356 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001357
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001358 shared_info = CompileToplevel(&info);
1359
1360 if (shared_info.is_null()) {
1361 return MaybeHandle<JSFunction>();
1362 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001363 // If caller is strict mode, the result must be in strict mode as well.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001364 DCHECK(is_sloppy(language_mode) ||
1365 is_strict(shared_info->language_mode()));
1366 compilation_cache->PutEval(source, outer_info, context, shared_info,
Ben Murdochc5610432016-08-08 18:44:38 +01001367 eval_scope_position);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001369 }
1370
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001371 Handle<JSFunction> result =
1372 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1373 shared_info, context, NOT_TENURED);
1374
1375 // OnAfterCompile has to be called after we create the JSFunction, which we
1376 // may require to recompile the eval for debugging, if we find a function
1377 // that contains break points in the eval script.
1378 isolate->debug()->OnAfterCompile(script);
1379
1380 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001381}
1382
Ben Murdochda12d292016-06-02 14:46:10 +01001383Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384 Handle<String> source, Handle<Object> script_name, int line_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 int column_offset, ScriptOriginOptions resource_options,
1386 Handle<Object> source_map_url, Handle<Context> context,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 v8::Extension* extension, ScriptData** cached_data,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
1389 bool is_module) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001390 Isolate* isolate = source->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001391 if (compile_options == ScriptCompiler::kNoCompileOptions) {
1392 cached_data = NULL;
1393 } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1394 compile_options == ScriptCompiler::kProduceCodeCache) {
1395 DCHECK(cached_data && !*cached_data);
1396 DCHECK(extension == NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001397 DCHECK(!isolate->debug()->is_loaded());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398 } else {
1399 DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1400 compile_options == ScriptCompiler::kConsumeCodeCache);
1401 DCHECK(cached_data && *cached_data);
1402 DCHECK(extension == NULL);
1403 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001404 int source_length = source->length();
1405 isolate->counters()->total_load_size()->Increment(source_length);
1406 isolate->counters()->total_compile_size()->Increment(source_length);
1407
Ben Murdochda12d292016-06-02 14:46:10 +01001408 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409 CompilationCache* compilation_cache = isolate->compilation_cache();
1410
1411 // Do a lookup in the compilation cache but not for extensions.
1412 MaybeHandle<SharedFunctionInfo> maybe_result;
1413 Handle<SharedFunctionInfo> result;
1414 if (extension == NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001415 // First check per-isolate compilation cache.
1416 maybe_result = compilation_cache->LookupScript(
1417 source, script_name, line_offset, column_offset, resource_options,
1418 context, language_mode);
1419 if (maybe_result.is_null() && FLAG_serialize_toplevel &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420 compile_options == ScriptCompiler::kConsumeCodeCache &&
1421 !isolate->debug()->is_loaded()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 // Then check cached code provided by embedder.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423 HistogramTimerScope timer(isolate->counters()->compile_deserialize());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001424 TRACE_EVENT0("v8", "V8.CompileDeserialize");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001425 Handle<SharedFunctionInfo> result;
1426 if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1427 .ToHandle(&result)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001428 // Promote to per-isolate compilation cache.
1429 compilation_cache->PutScript(source, context, language_mode, result);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001430 return result;
1431 }
1432 // Deserializer failed. Fall through to compile.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001433 }
1434 }
1435
1436 base::ElapsedTimer timer;
1437 if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
1438 compile_options == ScriptCompiler::kProduceCodeCache) {
1439 timer.Start();
1440 }
1441
Ben Murdochc5610432016-08-08 18:44:38 +01001442 if (!maybe_result.ToHandle(&result) ||
1443 (FLAG_serialize_toplevel &&
1444 compile_options == ScriptCompiler::kProduceCodeCache)) {
1445 // No cache entry found, or embedder wants a code cache. Compile the script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446
1447 // Create a script object describing the script to be compiled.
1448 Handle<Script> script = isolate->factory()->NewScript(source);
1449 if (natives == NATIVES_CODE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001450 script->set_type(Script::TYPE_NATIVE);
1451 script->set_hide_source(true);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001452 } else if (natives == EXTENSION_CODE) {
1453 script->set_type(Script::TYPE_EXTENSION);
1454 script->set_hide_source(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455 }
1456 if (!script_name.is_null()) {
1457 script->set_name(*script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001458 script->set_line_offset(line_offset);
1459 script->set_column_offset(column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001460 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461 script->set_origin_options(resource_options);
1462 if (!source_map_url.is_null()) {
1463 script->set_source_mapping_url(*source_map_url);
1464 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465
1466 // Compile the function and add it to the cache.
Ben Murdochda12d292016-06-02 14:46:10 +01001467 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001468 ParseInfo parse_info(&zone, script);
Ben Murdochc5610432016-08-08 18:44:38 +01001469 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdochda12d292016-06-02 14:46:10 +01001470 if (is_module) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001471 parse_info.set_module();
1472 } else {
1473 parse_info.set_global();
1474 }
1475 if (compile_options != ScriptCompiler::kNoCompileOptions) {
1476 parse_info.set_cached_data(cached_data);
1477 }
1478 parse_info.set_compile_options(compile_options);
1479 parse_info.set_extension(extension);
1480 parse_info.set_context(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001481 if (FLAG_serialize_toplevel &&
1482 compile_options == ScriptCompiler::kProduceCodeCache) {
1483 info.PrepareForSerializing();
1484 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001485
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001486 parse_info.set_language_mode(
Ben Murdochc5610432016-08-08 18:44:38 +01001487 static_cast<LanguageMode>(parse_info.language_mode() | language_mode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001488 result = CompileToplevel(&info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001489 if (extension == NULL && !result.is_null()) {
1490 compilation_cache->PutScript(source, context, language_mode, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491 if (FLAG_serialize_toplevel &&
1492 compile_options == ScriptCompiler::kProduceCodeCache) {
1493 HistogramTimerScope histogram_timer(
1494 isolate->counters()->compile_serialize());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001495 TRACE_EVENT0("v8", "V8.CompileSerialize");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496 *cached_data = CodeSerializer::Serialize(isolate, result, source);
1497 if (FLAG_profile_deserialization) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001498 PrintF("[Compiling and serializing took %0.3f ms]\n",
1499 timer.Elapsed().InMillisecondsF());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001500 }
1501 }
1502 }
1503
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504 if (result.is_null()) {
1505 isolate->ReportPendingMessages();
1506 } else {
1507 isolate->debug()->OnAfterCompile(script);
1508 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001509 } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1510 result->ResetForNewContext(isolate->heap()->global_ic_age());
1511 }
1512 return result;
1513}
1514
Ben Murdochda12d292016-06-02 14:46:10 +01001515Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001516 Handle<Script> script, ParseInfo* parse_info, int source_length) {
1517 Isolate* isolate = script->GetIsolate();
1518 // TODO(titzer): increment the counters in caller.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519 isolate->counters()->total_load_size()->Increment(source_length);
1520 isolate->counters()->total_compile_size()->Increment(source_length);
1521
Ben Murdochda12d292016-06-02 14:46:10 +01001522 LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001523 parse_info->set_language_mode(
1524 static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1525
Ben Murdochc5610432016-08-08 18:44:38 +01001526 CompilationInfo compile_info(parse_info, Handle<JSFunction>::null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527
1528 // The source was parsed lazily, so compiling for debugging is not possible.
1529 DCHECK(!compile_info.is_debug());
1530
1531 Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
1532 if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
1533 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534}
1535
1536
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001537Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001538 FunctionLiteral* literal, Handle<Script> script,
1539 CompilationInfo* outer_info) {
1540 // Precondition: code has been parsed and scopes have been analyzed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001541 Isolate* isolate = outer_info->isolate();
1542 MaybeHandle<SharedFunctionInfo> maybe_existing;
Ben Murdochc5610432016-08-08 18:44:38 +01001543
1544 // Find any previously allocated shared function info for the given literal.
1545 if (outer_info->shared_info()->never_compiled()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 // On the first compile, there are no existing shared function info for
1547 // inner functions yet, so do not try to find them. All bets are off for
1548 // live edit though.
Ben Murdochda12d292016-06-02 14:46:10 +01001549 SLOW_DCHECK(script->FindSharedFunctionInfo(literal).is_null() ||
1550 isolate->debug()->live_edit_enabled());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 } else {
1552 maybe_existing = script->FindSharedFunctionInfo(literal);
1553 }
Ben Murdochc5610432016-08-08 18:44:38 +01001554
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001555 // We found an existing shared function info. If it's already compiled,
1556 // don't worry about compiling it, and simply return it. If it's not yet
1557 // compiled, continue to decide whether to eagerly compile.
1558 // Carry on if we are compiling eager to obtain code for debugging,
1559 // unless we already have code with debut break slots.
1560 Handle<SharedFunctionInfo> existing;
1561 if (maybe_existing.ToHandle(&existing) && existing->is_compiled()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001562 DCHECK(!existing->is_toplevel());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001563 if (!outer_info->is_debug() || existing->HasDebugCode()) {
1564 return existing;
1565 }
1566 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001567
Ben Murdochda12d292016-06-02 14:46:10 +01001568 // Allocate a shared function info object.
1569 Handle<SharedFunctionInfo> result;
1570 if (!maybe_existing.ToHandle(&result)) {
1571 result = NewSharedFunctionInfoForLiteral(isolate, literal, script);
1572 result->set_is_toplevel(false);
Ben Murdochc5610432016-08-08 18:44:38 +01001573
1574 // If the outer function has been compiled before, we cannot be sure that
1575 // shared function info for this function literal has been created for the
1576 // first time. It may have already been compiled previously.
1577 result->set_never_compiled(outer_info->shared_info()->never_compiled());
Ben Murdochda12d292016-06-02 14:46:10 +01001578 }
1579
1580 Zone zone(isolate->allocator());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001581 ParseInfo parse_info(&zone, script);
Ben Murdochc5610432016-08-08 18:44:38 +01001582 CompilationInfo info(&parse_info, Handle<JSFunction>::null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 parse_info.set_literal(literal);
Ben Murdochda12d292016-06-02 14:46:10 +01001584 parse_info.set_shared_info(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001585 parse_info.set_scope(literal->scope());
1586 parse_info.set_language_mode(literal->scope()->language_mode());
1587 if (outer_info->will_serialize()) info.PrepareForSerializing();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 if (outer_info->is_debug()) info.MarkAsDebug();
1589
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001590 // Determine if the function can be lazily compiled. This is necessary to
1591 // allow some of our builtin JS files to be lazily compiled. These
1592 // builtins cannot be handled lazily by the parser, since we have to know
1593 // if a function uses the special natives syntax, which is something the
1594 // parser records.
1595 // If the debugger requests compilation for break points, we cannot be
1596 // aggressive about lazy compilation, because it might trigger compilation
1597 // of functions without an outer context when setting a breakpoint through
1598 // Debug::FindSharedFunctionInfoInScript.
Ben Murdochc5610432016-08-08 18:44:38 +01001599 bool allow_lazy = literal->AllowsLazyCompilation() && !info.is_debug();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001600 bool lazy = FLAG_lazy && allow_lazy && !literal->should_eager_compile();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001601
Ben Murdochda12d292016-06-02 14:46:10 +01001602 // Consider compiling eagerly when targeting the code cache.
1603 lazy &= !(FLAG_serialize_eager && info.will_serialize());
1604
1605 // Consider compiling eagerly when compiling bytecode for Ignition.
1606 lazy &=
1607 !(FLAG_ignition && FLAG_ignition_eager && !isolate->serializer_enabled());
1608
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001609 // Generate code
Ben Murdoch097c5b22016-05-18 11:27:45 +01001610 TimerEventScope<TimerEventCompileCode> timer(isolate);
1611 TRACE_EVENT0("v8", "V8.CompileCode");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612 if (lazy) {
Ben Murdochda12d292016-06-02 14:46:10 +01001613 info.SetCode(isolate->builtins()->CompileLazy());
Ben Murdochc5610432016-08-08 18:44:38 +01001614 } else if (Renumber(info.parse_info()) && GenerateUnoptimizedCode(&info)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001615 // Code generation will ensure that the feedback vector is present and
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001616 // appropriately sized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617 DCHECK(!info.code().is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618 if (literal->should_eager_compile() &&
1619 literal->should_be_used_once_hint()) {
1620 info.code()->MarkToBeExecutedOnce(isolate);
1621 }
Ben Murdochc5610432016-08-08 18:44:38 +01001622 // Update the shared function info with the scope info.
1623 InstallSharedScopeInfo(&info, result);
Ben Murdochda12d292016-06-02 14:46:10 +01001624 // Install compilation result on the shared function info.
Ben Murdochc5610432016-08-08 18:44:38 +01001625 InstallSharedCompilationResult(&info, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001626 } else {
1627 return Handle<SharedFunctionInfo>::null();
1628 }
1629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001630 if (maybe_existing.is_null()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001631 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001632 }
Ben Murdochda12d292016-06-02 14:46:10 +01001633
1634 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001635}
1636
Ben Murdoch097c5b22016-05-18 11:27:45 +01001637Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
1638 v8::Extension* extension, Handle<String> name) {
1639 Isolate* isolate = name->GetIsolate();
1640 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1641
1642 // Compute the function template for the native function.
1643 v8::Local<v8::FunctionTemplate> fun_template =
1644 extension->GetNativeFunctionTemplate(v8_isolate,
1645 v8::Utils::ToLocal(name));
1646 DCHECK(!fun_template.IsEmpty());
1647
1648 // Instantiate the function and create a shared function info from it.
1649 Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
1650 *fun_template->GetFunction(v8_isolate->GetCurrentContext())
1651 .ToLocalChecked()));
1652 const int literals = fun->NumberOfLiterals();
1653 Handle<Code> code = Handle<Code>(fun->shared()->code());
1654 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1655 Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
1656 name, literals, FunctionKind::kNormalFunction, code,
Ben Murdochda12d292016-06-02 14:46:10 +01001657 Handle<ScopeInfo>(fun->shared()->scope_info()));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001658 shared->set_construct_stub(*construct_stub);
Ben Murdochda12d292016-06-02 14:46:10 +01001659 shared->set_feedback_vector(fun->shared()->feedback_vector());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001660
1661 // Copy the function data to the shared function info.
1662 shared->set_function_data(fun->shared()->function_data());
1663 int parameters = fun->shared()->internal_formal_parameter_count();
1664 shared->set_internal_formal_parameter_count(parameters);
1665
1666 return shared;
1667}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001668
Ben Murdochda12d292016-06-02 14:46:10 +01001669MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1670 BailoutId osr_ast_id,
1671 JavaScriptFrame* osr_frame) {
1672 DCHECK(!osr_ast_id.IsNone());
1673 DCHECK_NOT_NULL(osr_frame);
1674 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001675}
1676
Ben Murdochc5610432016-08-08 18:44:38 +01001677void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
1678 // Take ownership of compilation job. Deleting job also tears down the zone.
1679 base::SmartPointer<CompilationJob> job(raw_job);
1680 CompilationInfo* info = job->info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001681 Isolate* isolate = info->isolate();
1682
1683 VMState<COMPILER> state(isolate);
1684 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001685 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001686
1687 Handle<SharedFunctionInfo> shared = info->shared_info();
1688 shared->code()->set_profiler_ticks(0);
1689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001690 DCHECK(!shared->HasDebugInfo());
1691
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001692 // 1) Optimization on the concurrent thread may have failed.
1693 // 2) The function may have already been optimized by OSR. Simply continue.
1694 // Except when OSR already disabled optimization for some reason.
1695 // 3) The code may have already been invalidated due to dependency change.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001696 // 4) Code generation may have failed.
Ben Murdochc5610432016-08-08 18:44:38 +01001697 if (job->last_status() == CompilationJob::SUCCEEDED) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001698 if (shared->optimization_disabled()) {
1699 job->RetryOptimization(kOptimizationDisabled);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001700 } else if (info->dependencies()->HasAborted()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001701 job->RetryOptimization(kBailedOutDueToDependencyChange);
Ben Murdochc5610432016-08-08 18:44:38 +01001702 } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) {
1703 job->RecordOptimizationStats();
1704 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001705 if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
1706 info->osr_ast_id()).code == nullptr) {
Ben Murdochc5610432016-08-08 18:44:38 +01001707 InsertCodeIntoOptimizedCodeMap(info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001708 }
1709 if (FLAG_trace_opt) {
1710 PrintF("[completed optimizing ");
1711 info->closure()->ShortPrint();
1712 PrintF("]\n");
1713 }
Ben Murdochda12d292016-06-02 14:46:10 +01001714 info->closure()->ReplaceCode(*info->code());
1715 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001716 }
1717 }
1718
Ben Murdochc5610432016-08-08 18:44:38 +01001719 DCHECK(job->last_status() != CompilationJob::SUCCEEDED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001720 if (FLAG_trace_opt) {
1721 PrintF("[aborted optimizing ");
1722 info->closure()->ShortPrint();
1723 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
1724 }
Ben Murdochda12d292016-06-02 14:46:10 +01001725 info->closure()->ReplaceCode(shared->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001726}
1727
Ben Murdochda12d292016-06-02 14:46:10 +01001728void Compiler::PostInstantiation(Handle<JSFunction> function,
1729 PretenureFlag pretenure) {
1730 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001731
Ben Murdochda12d292016-06-02 14:46:10 +01001732 if (FLAG_always_opt && shared->allows_lazy_compilation()) {
1733 function->MarkForOptimization();
1734 }
1735
1736 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
1737 function->context()->native_context(), BailoutId::None());
1738 if (cached.code != nullptr) {
1739 // Caching of optimized code enabled and optimized code found.
1740 DCHECK(!cached.code->marked_for_deoptimization());
1741 DCHECK(function->shared()->is_compiled());
1742 function->ReplaceCode(cached.code);
1743 }
1744
1745 if (cached.literals != nullptr) {
1746 function->set_literals(cached.literals);
1747 } else {
1748 Isolate* isolate = function->GetIsolate();
1749 int number_of_literals = shared->num_literals();
1750 Handle<LiteralsArray> literals =
1751 LiteralsArray::New(isolate, handle(shared->feedback_vector()),
1752 number_of_literals, pretenure);
1753 function->set_literals(*literals);
1754
1755 // Cache context-specific literals.
1756 MaybeHandle<Code> code;
1757 if (cached.code != nullptr) code = handle(cached.code);
1758 Handle<Context> native_context(function->context()->native_context());
1759 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
1760 literals, BailoutId::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001761 }
1762}
1763
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001764} // namespace internal
1765} // namespace v8