blob: 6c2bdce26f9a2540adf5a66484d51103afc91628 [file] [log] [blame]
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000030#include "compiler.h"
31
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032#include "bootstrapper.h"
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000033#include "codegen.h"
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000034#include "compilation-cache.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000035#include "cpu-profiler.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036#include "debug.h"
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000037#include "deoptimizer.h"
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000038#include "full-codegen.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000039#include "gdb-jit.h"
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000040#include "typing.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000041#include "hydrogen.h"
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000042#include "isolate-inl.h"
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000043#include "lithium.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000044#include "liveedit.h"
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000045#include "parser.h"
ager@chromium.org71daaf62009-04-01 07:22:49 +000046#include "rewriter.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000047#include "runtime-profiler.h"
ricow@chromium.org55ee8072011-09-08 16:33:10 +000048#include "scanner-character-streams.h"
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000049#include "scopeinfo.h"
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000050#include "scopes.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000051#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052
kasperl@chromium.org71affb52009-05-26 05:44:31 +000053namespace v8 {
54namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000056
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000057CompilationInfo::CompilationInfo(Handle<Script> script,
58 Zone* zone)
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000059 : flags_(LanguageModeField::encode(CLASSIC_MODE)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000060 script_(script),
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000061 osr_ast_id_(BailoutId::None()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000062 Initialize(script->GetIsolate(), BASE, zone);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000063}
64
65
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000066CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
67 Zone* zone)
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000068 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000069 shared_info_(shared_info),
70 script_(Handle<Script>(Script::cast(shared_info->script()))),
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000071 osr_ast_id_(BailoutId::None()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000072 Initialize(script_->GetIsolate(), BASE, zone);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000073}
74
75
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000076CompilationInfo::CompilationInfo(Handle<JSFunction> closure,
77 Zone* zone)
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000078 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000079 closure_(closure),
80 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
81 script_(Handle<Script>(Script::cast(shared_info_->script()))),
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000082 context_(closure->context()),
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000083 osr_ast_id_(BailoutId::None()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000084 Initialize(script_->GetIsolate(), BASE, zone);
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000085}
86
87
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000088CompilationInfo::CompilationInfo(HydrogenCodeStub* stub,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000089 Isolate* isolate,
90 Zone* zone)
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000091 : flags_(LanguageModeField::encode(CLASSIC_MODE) |
92 IsLazy::encode(true)),
93 osr_ast_id_(BailoutId::None()) {
94 Initialize(isolate, STUB, zone);
95 code_stub_ = stub;
96}
97
98
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000099void CompilationInfo::Initialize(Isolate* isolate,
100 Mode mode,
101 Zone* zone) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000102 isolate_ = isolate;
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000103 function_ = NULL;
104 scope_ = NULL;
105 global_scope_ = NULL;
106 extension_ = NULL;
107 pre_parse_data_ = NULL;
108 zone_ = zone;
109 deferred_handles_ = NULL;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000110 code_stub_ = NULL;
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000111 prologue_offset_ = kPrologueOffsetNotSet;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000112 opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000113 no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
114 ? new List<OffsetRange>(2) : NULL;
danno@chromium.org41728482013-06-12 22:31:22 +0000115 for (int i = 0; i < DependentCode::kGroupCount; i++) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000116 dependencies_[i] = NULL;
danno@chromium.org41728482013-06-12 22:31:22 +0000117 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000118 if (mode == STUB) {
119 mode_ = STUB;
120 return;
121 }
122 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
danno@chromium.org59400602013-08-13 17:09:37 +0000123 abort_due_to_dependency_ = false;
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000124 if (script_->type()->value() == Script::TYPE_NATIVE) {
125 MarkAsNative();
126 }
127 if (!shared_info_.is_null()) {
128 ASSERT(language_mode() == CLASSIC_MODE);
129 SetLanguageMode(shared_info_->language_mode());
130 }
danno@chromium.org59400602013-08-13 17:09:37 +0000131 set_bailout_reason(kUnknown);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000132}
133
134
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000135CompilationInfo::~CompilationInfo() {
136 delete deferred_handles_;
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000137 delete no_frame_ranges_;
danno@chromium.org41728482013-06-12 22:31:22 +0000138#ifdef DEBUG
139 // Check that no dependent maps have been added or added dependent maps have
140 // been rolled back or committed.
141 for (int i = 0; i < DependentCode::kGroupCount; i++) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000142 ASSERT_EQ(NULL, dependencies_[i]);
danno@chromium.org41728482013-06-12 22:31:22 +0000143 }
144#endif // DEBUG
145}
146
147
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000148void CompilationInfo::CommitDependencies(Handle<Code> code) {
danno@chromium.org41728482013-06-12 22:31:22 +0000149 for (int i = 0; i < DependentCode::kGroupCount; i++) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000150 ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
151 if (group_objects == NULL) continue;
danno@chromium.org41728482013-06-12 22:31:22 +0000152 ASSERT(!object_wrapper_.is_null());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000153 for (int j = 0; j < group_objects->length(); j++) {
154 DependentCode::DependencyGroup group =
155 static_cast<DependentCode::DependencyGroup>(i);
156 DependentCode* dependent_code =
157 DependentCode::ForObject(group_objects->at(j), group);
158 dependent_code->UpdateToFinishedCode(group, this, *code);
danno@chromium.org41728482013-06-12 22:31:22 +0000159 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000160 dependencies_[i] = NULL; // Zone-allocated, no need to delete.
danno@chromium.org41728482013-06-12 22:31:22 +0000161 }
162}
163
164
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000165void CompilationInfo::RollbackDependencies() {
danno@chromium.org41728482013-06-12 22:31:22 +0000166 // Unregister from all dependent maps if not yet committed.
167 for (int i = 0; i < DependentCode::kGroupCount; i++) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000168 ZoneList<Handle<HeapObject> >* group_objects = dependencies_[i];
169 if (group_objects == NULL) continue;
170 for (int j = 0; j < group_objects->length(); j++) {
171 DependentCode::DependencyGroup group =
172 static_cast<DependentCode::DependencyGroup>(i);
173 DependentCode* dependent_code =
174 DependentCode::ForObject(group_objects->at(j), group);
175 dependent_code->RemoveCompilationInfo(group, this);
danno@chromium.org41728482013-06-12 22:31:22 +0000176 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000177 dependencies_[i] = NULL; // Zone-allocated, no need to delete.
danno@chromium.org41728482013-06-12 22:31:22 +0000178 }
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000179}
180
181
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000182int CompilationInfo::num_parameters() const {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000183 ASSERT(!IsStub());
184 return scope()->num_parameters();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000185}
186
187
188int CompilationInfo::num_heap_slots() const {
189 if (IsStub()) {
190 return 0;
191 } else {
192 return scope()->num_heap_slots();
193 }
194}
195
196
197Code::Flags CompilationInfo::flags() const {
198 if (IsStub()) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000199 return Code::ComputeFlags(code_stub()->GetCodeKind(),
200 code_stub()->GetICState(),
201 code_stub()->GetExtraICState(),
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000202 code_stub()->GetStubType(),
203 code_stub()->GetStubFlags());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000204 } else {
205 return Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
206 }
207}
208
209
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000210// Disable optimization for the rest of the compilation pipeline.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000211void CompilationInfo::DisableOptimization() {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000212 bool is_optimizable_closure =
213 FLAG_optimize_closures &&
214 closure_.is_null() &&
215 !scope_->HasTrivialOuterContext() &&
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000216 !scope_->outer_scope_calls_non_strict_eval() &&
lrn@chromium.org1c092762011-05-09 09:42:16 +0000217 !scope_->inside_with();
218 SetMode(is_optimizable_closure ? BASE : NONOPT);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000219}
220
221
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000222// Primitive functions are unlikely to be picked up by the stack-walking
223// profiler, so they trigger their own optimization when they're called
224// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
225bool CompilationInfo::ShouldSelfOptimize() {
226 return FLAG_self_optimization &&
227 FLAG_crankshaft &&
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000228 !function()->flags()->Contains(kDontSelfOptimize) &&
yangguo@chromium.orga7d3df92012-02-27 11:46:55 +0000229 !function()->flags()->Contains(kDontOptimize) &&
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000230 function()->scope()->AllowsLazyCompilation() &&
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000231 (shared_info().is_null() || !shared_info()->optimization_disabled());
232}
233
234
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000235// Determine whether to use the full compiler for all code. If the flag
236// --always-full-compiler is specified this is the case. For the virtual frame
237// based compiler the full compiler is also used if a debugger is connected, as
238// the code from the full compiler supports mode precise break points. For the
239// crankshaft adaptive compiler debugging the optimized code is not possible at
240// all. However crankshaft support recompilation of functions, so in this case
241// the full compiler need not be be used if a debugger is attached, but only if
242// break points has actually been set.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000243static bool IsDebuggerActive(Isolate* isolate) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000244#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org1c092762011-05-09 09:42:16 +0000245 return V8::UseCrankshaft() ?
246 isolate->debug()->has_break_points() :
247 isolate->debugger()->IsDebuggerActive();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000248#else
lrn@chromium.org1c092762011-05-09 09:42:16 +0000249 return false;
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000250#endif
251}
252
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000253
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000254static bool AlwaysFullCompiler(Isolate* isolate) {
255 return FLAG_always_full_compiler || IsDebuggerActive(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000256}
257
258
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000259void OptimizingCompiler::RecordOptimizationStats() {
260 Handle<JSFunction> function = info()->closure();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000261 int opt_count = function->shared()->opt_count();
262 function->shared()->set_opt_count(opt_count + 1);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000263 double ms_creategraph =
264 static_cast<double>(time_taken_to_create_graph_) / 1000;
265 double ms_optimize = static_cast<double>(time_taken_to_optimize_) / 1000;
266 double ms_codegen = static_cast<double>(time_taken_to_codegen_) / 1000;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000267 if (FLAG_trace_opt) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000268 PrintF("[optimizing ");
269 function->ShortPrint();
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000270 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
271 ms_codegen);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000272 }
273 if (FLAG_trace_opt_stats) {
274 static double compilation_time = 0.0;
275 static int compiled_functions = 0;
276 static int code_size = 0;
277
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000278 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000279 compiled_functions++;
280 code_size += function->shared()->SourceSize();
281 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
282 compiled_functions,
283 code_size,
284 compilation_time);
285 }
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000286 if (FLAG_hydrogen_stats) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000287 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
288 time_taken_to_optimize_,
289 time_taken_to_codegen_);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000290 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000291}
292
293
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000294// A return value of true indicates the compilation pipeline is still
295// going, not necessarily that we optimized the code.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000296static bool MakeCrankshaftCode(CompilationInfo* info) {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000297 OptimizingCompiler compiler(info);
298 OptimizingCompiler::Status status = compiler.CreateGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000299
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000300 if (status != OptimizingCompiler::SUCCEEDED) {
301 return status != OptimizingCompiler::FAILED;
302 }
303 status = compiler.OptimizeGraph();
304 if (status != OptimizingCompiler::SUCCEEDED) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000305 status = compiler.AbortOptimization();
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000306 return status != OptimizingCompiler::FAILED;
307 }
308 status = compiler.GenerateAndInstallCode();
309 return status != OptimizingCompiler::FAILED;
310}
311
312
313OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
314 ASSERT(V8::UseCrankshaft());
315 ASSERT(info()->IsOptimizing());
316 ASSERT(!info()->IsCompilingForDebugging());
317
318 // We should never arrive here if there is no code object on the
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000319 // shared function object.
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000320 ASSERT(info()->shared_info()->code()->kind() == Code::FUNCTION);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000321
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000322 // We should never arrive here if optimization has been disabled on the
323 // shared function info.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000324 ASSERT(!info()->shared_info()->optimization_disabled());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000325
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000326 // Fall back to using the full code generator if it's not possible
327 // to use the Hydrogen-based optimizing compiler. We already have
328 // generated code for this from the shared function object.
ulan@chromium.org750145a2013-03-07 15:14:13 +0000329 if (AlwaysFullCompiler(isolate())) {
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000330 info()->AbortOptimization();
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000331 return SetLastStatus(BAILED_OUT);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000332 }
333
334 // Limit the number of times we re-compile a functions with
335 // the optimizing compiler.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000336 const int kMaxOptCount =
verwaest@chromium.orgde64f722012-08-16 15:44:54 +0000337 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000338 if (info()->opt_count() > kMaxOptCount) {
danno@chromium.org59400602013-08-13 17:09:37 +0000339 info()->set_bailout_reason(kOptimizedTooManyTimes);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000340 return AbortOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000341 }
342
343 // Due to an encoding limit on LUnallocated operands in the Lithium
344 // language, we cannot optimize functions with too many formal parameters
345 // or perform on-stack replacement for function with too many
346 // stack-allocated local variables.
347 //
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000348 // The encoding is as a signed value, with parameters and receiver using
349 // the negative indices and locals the non-negative ones.
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000350 const int parameter_limit = -LUnallocated::kMinFixedSlotIndex;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000351 Scope* scope = info()->scope();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000352 if ((scope->num_parameters() + 1) > parameter_limit) {
danno@chromium.org59400602013-08-13 17:09:37 +0000353 info()->set_bailout_reason(kTooManyParameters);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000354 return AbortOptimization();
355 }
356
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000357 const int locals_limit = LUnallocated::kMaxFixedSlotIndex;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000358 if (!info()->osr_ast_id().IsNone() &&
359 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
danno@chromium.org59400602013-08-13 17:09:37 +0000360 info()->set_bailout_reason(kTooManyParametersLocals);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000361 return AbortOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000362 }
363
364 // Take --hydrogen-filter into account.
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +0000365 if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) {
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000366 info()->AbortOptimization();
367 return SetLastStatus(BAILED_OUT);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000368 }
369
370 // Recompile the unoptimized version of the code if the current version
371 // doesn't have deoptimization support. Alternatively, we may decide to
372 // run the full code generator to get a baseline for the compile-time
373 // performance of the hydrogen-based compiler.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000374 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000375 if (should_recompile || FLAG_hydrogen_stats) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000376 int64_t start_ticks = 0;
377 if (FLAG_hydrogen_stats) {
378 start_ticks = OS::Ticks();
379 }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000380 CompilationInfoWithZone unoptimized(info()->shared_info());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000381 // Note that we use the same AST that we will use for generating the
382 // optimized code.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000383 unoptimized.SetFunction(info()->function());
384 unoptimized.SetScope(info()->scope());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000385 unoptimized.SetContext(info()->context());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000386 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
387 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
388 if (should_recompile) {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000389 if (!succeeded) return SetLastStatus(FAILED);
390 Handle<SharedFunctionInfo> shared = info()->shared_info();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000391 shared->EnableDeoptimizationSupport(*unoptimized.code());
392 // The existing unoptimized code was replaced with the new one.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000393 Compiler::RecordFunctionCompilation(
394 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000395 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000396 if (FLAG_hydrogen_stats) {
397 int64_t ticks = OS::Ticks() - start_ticks;
398 isolate()->GetHStatistics()->IncrementFullCodeGen(ticks);
399 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000400 }
401
402 // Check that the unoptimized, shared code is ready for
403 // optimizations. When using the always_opt flag we disregard the
404 // optimizable marker in the code object and optimize anyway. This
405 // is safe as long as the unoptimized code has deoptimization
406 // support.
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000407 ASSERT(FLAG_always_opt || info()->shared_info()->code()->optimizable());
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000408 ASSERT(info()->shared_info()->has_deoptimization_support());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000409
410 if (FLAG_trace_hydrogen) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000411 Handle<String> name = info()->function()->debug_name();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000412 PrintF("-----------------------------------------------------------\n");
413 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
ulan@chromium.org750145a2013-03-07 15:14:13 +0000414 isolate()->GetHTracer()->TraceCompilation(info());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000415 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000416
417 // Type-check the function.
danno@chromium.org41728482013-06-12 22:31:22 +0000418 AstTyper::Run(info());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000419
420 graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000421
422 Timer t(this, &time_taken_to_create_graph_);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000423 graph_ = graph_builder_->CreateGraph();
424
ulan@chromium.org750145a2013-03-07 15:14:13 +0000425 if (isolate()->has_pending_exception()) {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000426 info()->SetCode(Handle<Code>::null());
427 return SetLastStatus(FAILED);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000428 }
429
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000430 // The function being compiled may have bailed out due to an inline
431 // candidate bailing out. In such a case, we don't disable
432 // optimization on the shared_info.
433 ASSERT(!graph_builder_->inline_bailout() || graph_ == NULL);
434 if (graph_ == NULL) {
435 if (graph_builder_->inline_bailout()) {
436 info_->AbortOptimization();
437 return SetLastStatus(BAILED_OUT);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000438 } else {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000439 return AbortOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000440 }
441 }
442
danno@chromium.org59400602013-08-13 17:09:37 +0000443 if (info()->HasAbortedDueToDependencyChange()) {
444 info_->set_bailout_reason(kBailedOutDueToDependencyChange);
445 info_->AbortOptimization();
446 return SetLastStatus(BAILED_OUT);
447 }
448
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000449 return SetLastStatus(SUCCEEDED);
450}
451
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000452
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000453OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000454 DisallowHeapAllocation no_allocation;
455 DisallowHandleAllocation no_handles;
456 DisallowHandleDereference no_deref;
danno@chromium.org59400602013-08-13 17:09:37 +0000457 DisallowCodeDependencyChange no_dependency_change;
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000458
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000459 ASSERT(last_status() == SUCCEEDED);
460 Timer t(this, &time_taken_to_optimize_);
461 ASSERT(graph_ != NULL);
danno@chromium.org59400602013-08-13 17:09:37 +0000462 BailoutReason bailout_reason = kNoReason;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000463 if (!graph_->Optimize(&bailout_reason)) {
danno@chromium.org59400602013-08-13 17:09:37 +0000464 if (bailout_reason == kNoReason) graph_builder_->Bailout(bailout_reason);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000465 return SetLastStatus(BAILED_OUT);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000466 } else {
467 chunk_ = LChunk::NewChunk(graph_);
468 if (chunk_ == NULL) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000469 return SetLastStatus(BAILED_OUT);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000470 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000471 }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000472 return SetLastStatus(SUCCEEDED);
473}
474
475
476OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
477 ASSERT(last_status() == SUCCEEDED);
danno@chromium.org59400602013-08-13 17:09:37 +0000478 ASSERT(!info()->HasAbortedDueToDependencyChange());
479 DisallowCodeDependencyChange no_dependency_change;
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000480 { // Scope for timer.
481 Timer timer(this, &time_taken_to_codegen_);
482 ASSERT(chunk_ != NULL);
483 ASSERT(graph_ != NULL);
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000484 // Deferred handles reference objects that were accessible during
485 // graph creation. To make sure that we don't encounter inconsistencies
486 // between graph creation and code generation, we disallow accessing
487 // objects through deferred handles during the latter, with exceptions.
yangguo@chromium.org20301242013-06-03 16:06:25 +0000488 DisallowDeferredHandleDereference no_deferred_handle_deref;
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000489 Handle<Code> optimized_code = chunk_->Codegen();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000490 if (optimized_code.is_null()) {
danno@chromium.org59400602013-08-13 17:09:37 +0000491 if (info()->bailout_reason() == kNoReason) {
492 info()->set_bailout_reason(kCodeGenerationFailed);
493 }
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000494 return AbortOptimization();
495 }
496 info()->SetCode(optimized_code);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000497 }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000498 RecordOptimizationStats();
499 return SetLastStatus(SUCCEEDED);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000500}
501
502
lrn@chromium.org1c092762011-05-09 09:42:16 +0000503static bool GenerateCode(CompilationInfo* info) {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000504 bool is_optimizing = V8::UseCrankshaft() &&
505 !info->IsCompilingForDebugging() &&
506 info->IsOptimizing();
507 if (is_optimizing) {
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000508 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000509 info->isolate(), Logger::TimerEventScope::v8_recompile_synchronous);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000510 return MakeCrankshaftCode(info);
511 } else {
512 if (info->IsOptimizing()) {
513 // Have the CompilationInfo decide if the compilation should be
514 // BASE or NONOPT.
515 info->DisableOptimization();
516 }
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000517 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000518 info->isolate(), Logger::TimerEventScope::v8_compile_full_code);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000519 return FullCodeGenerator::MakeCode(info);
520 }
lrn@chromium.org1c092762011-05-09 09:42:16 +0000521}
522
523
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000524static bool MakeCode(CompilationInfo* info) {
525 // Precondition: code has been parsed. Postcondition: the code field in
526 // the compilation info is set if compilation succeeded.
527 ASSERT(info->function() != NULL);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000528 return Rewriter::Rewrite(info) && Scope::Analyze(info) && GenerateCode(info);
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000529}
530
531
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000532#ifdef ENABLE_DEBUGGER_SUPPORT
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000533bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
534 // Precondition: code has been parsed. Postcondition: the code field in
535 // the compilation info is set if compilation succeeded.
536 bool succeeded = MakeCode(info);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000537 if (!info->shared_info().is_null()) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000538 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000539 info->zone());
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000540 info->shared_info()->set_scope_info(*scope_info);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000541 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000542 return succeeded;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000543}
544#endif
545
546
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000547static bool DebuggerWantsEagerCompilation(CompilationInfo* info,
548 bool allow_lazy_without_ctx = false) {
549 return LiveEditFunctionTracker::IsActive(info->isolate()) ||
550 (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx);
551}
552
553
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000554static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000555 Isolate* isolate = info->isolate();
556 PostponeInterruptsScope postpone(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000557
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000558 ASSERT(!isolate->native_context().is_null());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000559 Handle<Script> script = info->script();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000560 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
561 FixedArray* array = isolate->native_context()->embedder_data();
562 script->set_context_data(array->get(0));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000563
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000564#ifdef ENABLE_DEBUGGER_SUPPORT
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000565 if (info->is_eval()) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000566 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000567 // For eval scripts add information on the function from which eval was
568 // called.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000569 if (info->is_eval()) {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000570 StackTraceFrameIterator it(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000571 if (!it.done()) {
danno@chromium.org169691d2013-07-15 08:01:13 +0000572 script->set_eval_from_shared(it.frame()->function()->shared());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000573 Code* code = it.frame()->LookupCode();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000574 int offset = static_cast<int>(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000575 it.frame()->pc() - code->instruction_start());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000576 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
577 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000578 }
579 }
580
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581 // Notify debugger
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000582 isolate->debugger()->OnBeforeCompile(script);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000583#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584
585 // Only allow non-global compiles for eval.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000586 ASSERT(info->is_eval() || info->is_global());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000587 {
588 Parser parser(info);
589 if ((info->pre_parse_data() != NULL ||
590 String::cast(script->source())->length() > FLAG_min_preparse_length) &&
591 !DebuggerWantsEagerCompilation(info))
592 parser.set_allow_lazy(true);
593 if (!parser.Parse()) {
594 return Handle<SharedFunctionInfo>::null();
595 }
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000596 }
kasper.lund212ac232008-07-16 07:07:30 +0000597
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000598 // Measure how long it takes to do the compilation; only take the
599 // rest of the function into account to avoid overlap with the
600 // parsing statistics.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000601 HistogramTimer* rate = info->is_eval()
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000602 ? info->isolate()->counters()->compile_eval()
603 : info->isolate()->counters()->compile();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000604 HistogramTimerScope timer(rate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605
606 // Compile the code.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000607 FunctionLiteral* lit = info->function();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000608 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000609 if (!MakeCode(info)) {
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000610 if (!isolate->has_pending_exception()) isolate->StackOverflow();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000611 return Handle<SharedFunctionInfo>::null();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612 }
613
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000614 // Allocate function.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000615 ASSERT(!info->code().is_null());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000616 Handle<SharedFunctionInfo> result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000617 isolate->factory()->NewSharedFunctionInfo(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000618 lit->name(),
619 lit->materialized_literal_count(),
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000620 lit->is_generator(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000621 info->code(),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000622 ScopeInfo::Create(info->scope(), info->zone()));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000623
624 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
625 Compiler::SetFunctionInfo(result, lit, true, script);
626
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000627 if (script->name()->IsString()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000628 PROFILE(isolate, CodeCreateEvent(
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000629 info->is_eval()
630 ? Logger::EVAL_TAG
631 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
632 *info->code(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000633 *result,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000634 info,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000635 String::cast(script->name())));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000636 GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
637 script,
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000638 info->code(),
639 info));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000640 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000641 PROFILE(isolate, CodeCreateEvent(
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000642 info->is_eval()
643 ? Logger::EVAL_TAG
644 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
645 *info->code(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000646 *result,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000647 info,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000648 isolate->heap()->empty_string()));
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000649 GDBJIT(AddCode(Handle<String>(), script, info->code(), info));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000650 }
651
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652 // Hint to the runtime system used when allocating space for initial
653 // property space by setting the expected number of properties for
654 // the instances of the function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000655 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000656
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000657 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000658
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000659#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660 // Notify debugger
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000661 isolate->debugger()->OnAfterCompile(
662 script, Debugger::NO_AFTER_COMPILE_FLAGS);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000663#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000664
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000665 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000666
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000667 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668}
669
670
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000671Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
672 Handle<Object> script_name,
673 int line_offset,
674 int column_offset,
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000675 bool is_shared_cross_origin,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000676 Handle<Context> context,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000677 v8::Extension* extension,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000678 ScriptDataImpl* pre_data,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000679 Handle<Object> script_data,
680 NativesFlag natives) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000681 Isolate* isolate = source->GetIsolate();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000682 int source_length = source->length();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000683 isolate->counters()->total_load_size()->Increment(source_length);
684 isolate->counters()->total_compile_size()->Increment(source_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000685
686 // The VM is in the COMPILER state until exiting this function.
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000687 VMState<COMPILER> state(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000688
689 CompilationCache* compilation_cache = isolate->compilation_cache();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000690
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000691 // Do a lookup in the compilation cache but not for extensions.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000692 Handle<SharedFunctionInfo> result;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000693 if (extension == NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000694 result = compilation_cache->LookupScript(source,
695 script_name,
696 line_offset,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000697 column_offset,
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000698 is_shared_cross_origin,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000699 context);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000700 }
701
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000702 if (result.is_null()) {
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000703 // No cache entry found. Do pre-parsing, if it makes sense, and compile
704 // the script.
705 // Building preparse data that is only used immediately after is only a
706 // saving if we might skip building the AST for lazily compiled functions.
707 // I.e., preparse data isn't relevant when the lazy flag is off, and
708 // for small sources, odds are that there aren't many functions
709 // that would be compiled lazily anyway, so we skip the preparse step
710 // in that case too.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000711
712 // Create a script object describing the script to be compiled.
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000713 Handle<Script> script = isolate->factory()->NewScript(source);
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000714 if (natives == NATIVES_CODE) {
715 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
716 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000717 if (!script_name.is_null()) {
718 script->set_name(*script_name);
719 script->set_line_offset(Smi::FromInt(line_offset));
720 script->set_column_offset(Smi::FromInt(column_offset));
721 }
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000722 script->set_is_shared_cross_origin(is_shared_cross_origin);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000723
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000724 script->set_data(script_data.is_null() ? HEAP->undefined_value()
ager@chromium.org5c838252010-02-19 08:53:10 +0000725 : *script_data);
726
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000727 // Compile the function and add it to the cache.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000728 CompilationInfoWithZone info(script);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000729 info.MarkAsGlobal();
730 info.SetExtension(extension);
731 info.SetPreParseData(pre_data);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000732 info.SetContext(context);
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000733 if (FLAG_use_strict) {
734 info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE);
735 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000736 result = MakeFunctionInfo(&info);
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000737 if (extension == NULL && !result.is_null() && !result->dont_cache()) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000738 compilation_cache->PutScript(source, context, result);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000739 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000740 } else {
741 if (result->ic_age() != HEAP->global_ic_age()) {
742 result->ResetForNewContext(HEAP->global_ic_age());
743 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000744 }
745
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000746 if (result.is_null()) isolate->ReportPendingMessages();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000747 return result;
748}
749
750
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000751Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
752 Handle<Context> context,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000753 bool is_global,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000754 LanguageMode language_mode,
svenpanne@chromium.org9faefa42013-03-08 13:13:16 +0000755 ParseRestriction restriction,
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000756 int scope_position) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000757 Isolate* isolate = source->GetIsolate();
ager@chromium.orgc3e50d82008-11-05 11:53:10 +0000758 int source_length = source->length();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000759 isolate->counters()->total_eval_size()->Increment(source_length);
760 isolate->counters()->total_compile_size()->Increment(source_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000761
762 // The VM is in the COMPILER state until exiting this function.
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000763 VMState<COMPILER> state(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000764
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000765 // Do a lookup in the compilation cache; if the entry is not there, invoke
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000766 // the compiler and add the result to the cache.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000767 Handle<SharedFunctionInfo> result;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000768 CompilationCache* compilation_cache = isolate->compilation_cache();
769 result = compilation_cache->LookupEval(source,
770 context,
771 is_global,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000772 language_mode,
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000773 scope_position);
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000774
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000775 if (result.is_null()) {
776 // Create a script object describing the script to be compiled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000777 Handle<Script> script = isolate->factory()->NewScript(source);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000778 CompilationInfoWithZone info(script);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000779 info.MarkAsEval();
780 if (is_global) info.MarkAsGlobal();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000781 info.SetLanguageMode(language_mode);
svenpanne@chromium.org9faefa42013-03-08 13:13:16 +0000782 info.SetParseRestriction(restriction);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000783 info.SetContext(context);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000784 result = MakeFunctionInfo(&info);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000785 if (!result.is_null()) {
yangguo@chromium.org56454712012-02-16 15:33:53 +0000786 // Explicitly disable optimization for eval code. We're not yet prepared
787 // to handle eval-code in the optimizing compiler.
danno@chromium.org59400602013-08-13 17:09:37 +0000788 result->DisableOptimization(kEval);
yangguo@chromium.org56454712012-02-16 15:33:53 +0000789
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000790 // If caller is strict mode, the result must be in strict mode or
791 // extended mode as well, but not the other way around. Consider:
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000792 // eval("'use strict'; ...");
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000793 ASSERT(language_mode != STRICT_MODE || !result->is_classic_mode());
794 // If caller is in extended mode, the result must also be in
795 // extended mode.
796 ASSERT(language_mode != EXTENDED_MODE ||
797 result->is_extended_mode());
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000798 if (!result->dont_cache()) {
799 compilation_cache->PutEval(
800 source, context, is_global, result, scope_position);
801 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000802 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000803 } else {
804 if (result->ic_age() != HEAP->global_ic_age()) {
805 result->ResetForNewContext(HEAP->global_ic_age());
806 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000807 }
ager@chromium.org8bb60582008-12-11 12:02:20 +0000808
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000809 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000810}
811
812
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000813static bool InstallFullCode(CompilationInfo* info) {
814 // Update the shared function info with the compiled code and the
815 // scope info. Please note, that the order of the shared function
816 // info initialization is important since set_scope_info might
817 // trigger a GC, causing the ASSERT below to be invalid if the code
818 // was flushed. By setting the code object last we avoid this.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000819 Handle<SharedFunctionInfo> shared = info->shared_info();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000820 Handle<Code> code = info->code();
danno@chromium.org59400602013-08-13 17:09:37 +0000821 CHECK(code->kind() == Code::FUNCTION);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000822 Handle<JSFunction> function = info->closure();
823 Handle<ScopeInfo> scope_info =
824 ScopeInfo::Create(info->scope(), info->zone());
825 shared->set_scope_info(*scope_info);
yangguo@chromium.org9768bf12013-01-11 14:51:07 +0000826 shared->ReplaceCode(*code);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000827 if (!function.is_null()) {
828 function->ReplaceCode(*code);
829 ASSERT(!function->IsOptimized());
830 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000831
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000832 // Set the expected number of properties for instances.
833 FunctionLiteral* lit = info->function();
834 int expected = lit->expected_property_count();
835 SetExpectedNofPropertiesFromEstimate(shared, expected);
836
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000837 // Check the function has compiled code.
838 ASSERT(shared->is_compiled());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000839 shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
840 shared->set_dont_inline(lit->flags()->Contains(kDontInline));
841 shared->set_ast_node_count(lit->ast_node_count());
842
jkummerow@chromium.org000f7fb2012-08-01 11:14:42 +0000843 if (V8::UseCrankshaft() &&
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000844 !function.is_null() &&
845 !shared->optimization_disabled()) {
846 // If we're asked to always optimize, we compile the optimized
847 // version of the function right away - unless the debugger is
848 // active as it makes no sense to compile optimized code then.
849 if (FLAG_always_opt &&
850 !Isolate::Current()->DebuggerHasBreakPoints()) {
851 CompilationInfoWithZone optimized(function);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000852 optimized.SetOptimizing(BailoutId::None());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000853 return Compiler::CompileLazy(&optimized);
854 }
855 }
856 return true;
857}
858
859
860static void InstallCodeCommon(CompilationInfo* info) {
861 Handle<SharedFunctionInfo> shared = info->shared_info();
862 Handle<Code> code = info->code();
863 ASSERT(!code.is_null());
864
865 // Set optimizable to false if this is disallowed by the shared
866 // function info, e.g., we might have flushed the code and must
867 // reset this bit when lazy compiling the code again.
868 if (shared->optimization_disabled()) code->set_optimizable(false);
869
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000870 if (shared->code() == *code) {
871 // Do not send compilation event for the same code twice.
872 return;
873 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000874 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
875}
876
877
878static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
879 Handle<Code> code = info->code();
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000880 if (FLAG_cache_optimized_code &&
881 info->osr_ast_id().IsNone() &&
882 code->kind() == Code::OPTIMIZED_FUNCTION) {
883 Handle<JSFunction> function = info->closure();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000884 Handle<SharedFunctionInfo> shared(function->shared());
885 Handle<FixedArray> literals(function->literals());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000886 Handle<Context> native_context(function->context()->native_context());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000887 SharedFunctionInfo::AddToOptimizedCodeMap(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000888 shared, native_context, code, literals);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000889 }
890}
891
892
893static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000894 if (FLAG_cache_optimized_code &&
895 info->osr_ast_id().IsNone() &&
896 info->IsOptimizing()) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000897 Handle<SharedFunctionInfo> shared = info->shared_info();
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000898 Handle<JSFunction> function = info->closure();
899 ASSERT(!function.is_null());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000900 Handle<Context> native_context(function->context()->native_context());
901 int index = shared->SearchOptimizedCodeMap(*native_context);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000902 if (index > 0) {
903 if (FLAG_trace_opt) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000904 PrintF("[found optimized code for ");
905 function->ShortPrint();
906 PrintF("]\n");
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000907 }
ulan@chromium.orgd9e468a2012-06-25 09:47:40 +0000908 // Caching of optimized code enabled and optimized code found.
909 shared->InstallFromOptimizedCodeMap(*function, index);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000910 return true;
911 }
912 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000913 return false;
914}
915
916
917bool Compiler::CompileLazy(CompilationInfo* info) {
918 Isolate* isolate = info->isolate();
919
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000920 // The VM is in the COMPILER state until exiting this function.
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000921 VMState<COMPILER> state(isolate);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000922
923 PostponeInterruptsScope postpone(isolate);
924
925 Handle<SharedFunctionInfo> shared = info->shared_info();
926 int compiled_size = shared->end_position() - shared->start_position();
927 isolate->counters()->total_compile_size()->Increment(compiled_size);
928
929 if (InstallCodeFromOptimizedCodeMap(info)) return true;
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000930
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000931 // Generate the AST for the lazily compiled function.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000932 if (Parser::Parse(info)) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000933 // Measure how long it takes to do the lazy compilation; only take the
934 // rest of the function into account to avoid overlap with the lazy
935 // parsing statistics.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000936 HistogramTimerScope timer(isolate->counters()->compile_lazy());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000937
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000938 // After parsing we know the function's language mode. Remember it.
939 LanguageMode language_mode = info->function()->language_mode();
940 info->SetLanguageMode(language_mode);
941 shared->set_language_mode(language_mode);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000942
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000943 // Compile the code.
944 if (!MakeCode(info)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000945 if (!isolate->has_pending_exception()) {
946 isolate->StackOverflow();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000947 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000948 } else {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000949 InstallCodeCommon(info);
kasper.lund212ac232008-07-16 07:07:30 +0000950
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000951 if (info->IsOptimizing()) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000952 Handle<Code> code = info->code();
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000953 ASSERT(shared->scope_info() != ScopeInfo::Empty(isolate));
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000954 info->closure()->ReplaceCode(*code);
955 InsertCodeIntoOptimizedCodeMap(info);
956 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000957 } else {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000958 return InstallFullCode(info);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000959 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000960 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000961 }
962
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000963 ASSERT(info->code().is_null());
964 return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000965}
966
967
rossberg@chromium.org92597162013-08-23 13:28:00 +0000968void Compiler::RecompileConcurrent(Handle<JSFunction> closure) {
969 ASSERT(closure->IsMarkedForConcurrentRecompilation());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000970
971 Isolate* isolate = closure->GetIsolate();
rossberg@chromium.org92597162013-08-23 13:28:00 +0000972 // Here we prepare compile data for the concurrent recompilation thread, but
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000973 // this still happens synchronously and interrupts execution.
974 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000975 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000976
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000977 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
rossberg@chromium.org92597162013-08-23 13:28:00 +0000978 if (FLAG_trace_concurrent_recompilation) {
danno@chromium.org59400602013-08-13 17:09:37 +0000979 PrintF(" ** Compilation queue full, will retry optimizing ");
980 closure->PrintName();
981 PrintF(" on next run.\n");
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000982 }
983 return;
984 }
985
986 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure));
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000987 VMState<COMPILER> state(isolate);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000988 PostponeInterruptsScope postpone(isolate);
989
990 Handle<SharedFunctionInfo> shared = info->shared_info();
991 int compiled_size = shared->end_position() - shared->start_position();
992 isolate->counters()->total_compile_size()->Increment(compiled_size);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000993 info->SetOptimizing(BailoutId::None());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000994
995 {
996 CompilationHandleScope handle_scope(*info);
997
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000998 if (InstallCodeFromOptimizedCodeMap(*info)) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000999 return;
1000 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001001
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001002 if (Parser::Parse(*info)) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001003 LanguageMode language_mode = info->function()->language_mode();
1004 info->SetLanguageMode(language_mode);
1005 shared->set_language_mode(language_mode);
1006 info->SaveHandles();
1007
1008 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) {
1009 OptimizingCompiler* compiler =
1010 new(info->zone()) OptimizingCompiler(*info);
1011 OptimizingCompiler::Status status = compiler->CreateGraph();
1012 if (status == OptimizingCompiler::SUCCEEDED) {
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001013 info.Detach();
1014 shared->code()->set_profiler_ticks(0);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001015 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001016 } else if (status == OptimizingCompiler::BAILED_OUT) {
1017 isolate->clear_pending_exception();
1018 InstallFullCode(*info);
1019 }
1020 }
1021 }
1022 }
1023
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001024 if (shared->code()->back_edges_patched_for_osr()) {
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001025 // At this point we either put the function on recompilation queue or
1026 // aborted optimization. In either case we want to continue executing
1027 // the unoptimized code without running into OSR. If the unoptimized
1028 // code has been patched for OSR, unpatch it.
1029 InterruptStub interrupt_stub;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001030 Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001031 Handle<Code> replacement_code =
1032 isolate->builtins()->OnStackReplacement();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001033 Deoptimizer::RevertInterruptCode(shared->code(),
1034 *interrupt_code,
1035 *replacement_code);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001036 }
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001037
1038 if (isolate->has_pending_exception()) isolate->clear_pending_exception();
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001039}
1040
1041
1042void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
1043 SmartPointer<CompilationInfo> info(optimizing_compiler->info());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001044 // The function may have already been optimized by OSR. Simply continue.
1045 // Except when OSR already disabled optimization for some reason.
1046 if (info->shared_info()->optimization_disabled()) {
danno@chromium.org41728482013-06-12 22:31:22 +00001047 info->AbortOptimization();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001048 InstallFullCode(*info);
rossberg@chromium.org92597162013-08-23 13:28:00 +00001049 if (FLAG_trace_concurrent_recompilation) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001050 PrintF(" ** aborting optimization for ");
1051 info->closure()->PrintName();
1052 PrintF(" as it has been disabled.\n");
1053 }
1054 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
1055 return;
1056 }
ulan@chromium.org750145a2013-03-07 15:14:13 +00001057
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001058 Isolate* isolate = info->isolate();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001059 VMState<COMPILER> state(isolate);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001060 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +00001061 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001062 // If crankshaft succeeded, install the optimized code else install
1063 // the unoptimized code.
1064 OptimizingCompiler::Status status = optimizing_compiler->last_status();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001065 if (info->HasAbortedDueToDependencyChange()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001066 info->set_bailout_reason(kBailedOutDueToDependencyChange);
danno@chromium.org41728482013-06-12 22:31:22 +00001067 status = optimizing_compiler->AbortOptimization();
1068 } else if (status != OptimizingCompiler::SUCCEEDED) {
danno@chromium.org59400602013-08-13 17:09:37 +00001069 info->set_bailout_reason(kFailedBailedOutLastTime);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001070 status = optimizing_compiler->AbortOptimization();
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00001071 } else if (isolate->DebuggerHasBreakPoints()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001072 info->set_bailout_reason(kDebuggerIsActive);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001073 status = optimizing_compiler->AbortOptimization();
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001074 } else {
1075 status = optimizing_compiler->GenerateAndInstallCode();
1076 ASSERT(status == OptimizingCompiler::SUCCEEDED ||
1077 status == OptimizingCompiler::BAILED_OUT);
1078 }
1079
1080 InstallCodeCommon(*info);
1081 if (status == OptimizingCompiler::SUCCEEDED) {
1082 Handle<Code> code = info->code();
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001083 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001084 info->closure()->ReplaceCode(*code);
1085 if (info->shared_info()->SearchOptimizedCodeMap(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001086 info->closure()->context()->native_context()) == -1) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001087 InsertCodeIntoOptimizedCodeMap(*info);
1088 }
rossberg@chromium.org92597162013-08-23 13:28:00 +00001089 if (FLAG_trace_concurrent_recompilation) {
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001090 PrintF(" ** Optimized code for ");
1091 info->closure()->PrintName();
1092 PrintF(" installed.\n");
1093 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001094 } else {
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001095 info->AbortOptimization();
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001096 InstallFullCode(*info);
1097 }
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001098 // Optimized code is finally replacing unoptimized code. Reset the latter's
1099 // profiler ticks to prevent too soon re-opt after a deopt.
1100 info->shared_info()->code()->set_profiler_ticks(0);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001101 ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
yangguo@chromium.org304cc332012-07-24 07:59:48 +00001102}
1103
1104
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001105Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001106 Handle<Script> script) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001107 // Precondition: code has been parsed and scopes have been analyzed.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001108 CompilationInfoWithZone info(script);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001109 info.SetFunction(literal);
1110 info.SetScope(literal->scope());
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001111 info.SetLanguageMode(literal->scope()->language_mode());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001112
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001113 Isolate* isolate = info.isolate();
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001114 Factory* factory = isolate->factory();
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001115 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001116 // Determine if the function can be lazily compiled. This is necessary to
1117 // allow some of our builtin JS files to be lazily compiled. These
1118 // builtins cannot be handled lazily by the parser, since we have to know
1119 // if a function uses the special natives syntax, which is something the
1120 // parser records.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001121 // If the debugger requests compilation for break points, we cannot be
1122 // aggressive about lazy compilation, because it might trigger compilation
1123 // of functions without an outer context when setting a breakpoint through
jkummerow@chromium.org78502a92012-09-06 13:50:42 +00001124 // Debug::FindSharedFunctionInfoInScript.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001125 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
ager@chromium.org5c838252010-02-19 08:53:10 +00001126 bool allow_lazy = literal->AllowsLazyCompilation() &&
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001127 !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001128
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001129 Handle<ScopeInfo> scope_info(ScopeInfo::Empty(isolate));
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001130
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001131 // Generate code
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001132 if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001133 Handle<Code> code = isolate->builtins()->LazyCompile();
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001134 info.SetCode(code);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001135 } else if (GenerateCode(&info)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001136 ASSERT(!info.code().is_null());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001137 scope_info = ScopeInfo::Create(info.scope(), info.zone());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001138 } else {
1139 return Handle<SharedFunctionInfo>::null();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001140 }
1141
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00001142 // Create a shared function info object.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001143 Handle<SharedFunctionInfo> result =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001144 factory->NewSharedFunctionInfo(literal->name(),
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001145 literal->materialized_literal_count(),
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001146 literal->is_generator(),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001147 info.code(),
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001148 scope_info);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001149 SetFunctionInfo(result, literal, false, script);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001150 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001151 result->set_allows_lazy_compilation(allow_lazy);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001152 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001153
1154 // Set the expected number of properties for instances and return
1155 // the resulting function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001156 SetExpectedNofPropertiesFromEstimate(result,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001157 literal->expected_property_count());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001158 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001159 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001160}
1161
1162
1163// Sets the function info on a function.
1164// The start_position points to the first '(' character after the function name
1165// in the full script source. When counting characters in the script source the
1166// the first character is number 0 (not 1).
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001167void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001168 FunctionLiteral* lit,
1169 bool is_toplevel,
1170 Handle<Script> script) {
danno@chromium.orgc612e022011-11-10 11:38:15 +00001171 function_info->set_length(lit->parameter_count());
1172 function_info->set_formal_parameter_count(lit->parameter_count());
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001173 function_info->set_script(*script);
1174 function_info->set_function_token_position(lit->function_token_position());
1175 function_info->set_start_position(lit->start_position());
1176 function_info->set_end_position(lit->end_position());
1177 function_info->set_is_expression(lit->is_expression());
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00001178 function_info->set_is_anonymous(lit->is_anonymous());
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001179 function_info->set_is_toplevel(is_toplevel);
1180 function_info->set_inferred_name(*lit->inferred_name());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001181 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001182 function_info->set_allows_lazy_compilation_without_context(
1183 lit->AllowsLazyCompilationWithoutContext());
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001184 function_info->set_language_mode(lit->language_mode());
whesse@chromium.org7b260152011-06-20 15:33:18 +00001185 function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
1186 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001187 function_info->set_ast_node_count(lit->ast_node_count());
yangguo@chromium.org56454712012-02-16 15:33:53 +00001188 function_info->set_is_function(lit->is_function());
1189 function_info->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001190 function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001191 function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001192 function_info->set_is_generator(lit->is_generator());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001193}
1194
1195
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001196void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001197 CompilationInfo* info,
1198 Handle<SharedFunctionInfo> shared) {
1199 // SharedFunctionInfo is passed separately, because if CompilationInfo
1200 // was created using Script object, it will not have it.
1201
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001202 // Log the code generation. If source information is available include
1203 // script name and line number. Check explicitly whether logging is
1204 // enabled as finding the line number is not free.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001205 if (info->isolate()->logger()->is_logging_code_events() ||
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001206 info->isolate()->cpu_profiler()->is_profiling()) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001207 Handle<Script> script = info->script();
1208 Handle<Code> code = info->code();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001209 if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001210 return;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001211 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001212 int column_num =
1213 GetScriptColumnNumber(script, shared->start_position()) + 1;
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001214 USE(line_num);
ager@chromium.org5c838252010-02-19 08:53:10 +00001215 if (script->name()->IsString()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001216 PROFILE(info->isolate(),
1217 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001218 *code,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001219 *shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001220 info,
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00001221 String::cast(script->name()),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001222 line_num,
1223 column_num));
ager@chromium.org5c838252010-02-19 08:53:10 +00001224 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001225 PROFILE(info->isolate(),
1226 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001227 *code,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001228 *shared,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001229 info,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001230 info->isolate()->heap()->empty_string(),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001231 line_num,
1232 column_num));
ager@chromium.org5c838252010-02-19 08:53:10 +00001233 }
1234 }
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001235
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001236 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001237 Handle<Script>(info->script()),
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001238 Handle<Code>(info->code()),
1239 info));
ager@chromium.org5c838252010-02-19 08:53:10 +00001240}
ager@chromium.org5c838252010-02-19 08:53:10 +00001241
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001242
1243CompilationPhase::CompilationPhase(const char* name, CompilationInfo* info)
1244 : name_(name), info_(info), zone_(info->isolate()) {
1245 if (FLAG_hydrogen_stats) {
1246 info_zone_start_allocation_size_ = info->zone()->allocation_size();
1247 start_ticks_ = OS::Ticks();
1248 }
1249}
1250
1251
1252CompilationPhase::~CompilationPhase() {
1253 if (FLAG_hydrogen_stats) {
1254 unsigned size = zone()->allocation_size();
1255 size += info_->zone()->allocation_size() - info_zone_start_allocation_size_;
1256 int64_t ticks = OS::Ticks() - start_ticks_;
1257 isolate()->GetHStatistics()->SaveTiming(name_, ticks, size);
1258 }
1259}
1260
1261
1262bool CompilationPhase::ShouldProduceTraceOutput() const {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001263 // Trace if the appropriate trace flag is set and the phase name's first
1264 // character is in the FLAG_trace_phase command line parameter.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001265 AllowHandleDereference allow_deref;
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00001266 bool tracing_on = info()->IsStub()
1267 ? FLAG_trace_hydrogen_stubs
1268 : (FLAG_trace_hydrogen &&
1269 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001270 return (tracing_on &&
1271 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001272}
1273
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001274} } // namespace v8::internal