blob: a381c3aab17db9f1723fdad0a4356ebf57f7c5ef [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"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035#include "debug.h"
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000036#include "full-codegen.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000037#include "gdb-jit.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038#include "hydrogen.h"
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000039#include "isolate-inl.h"
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000040#include "lithium.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000041#include "liveedit.h"
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000042#include "parser.h"
ager@chromium.org71daaf62009-04-01 07:22:49 +000043#include "rewriter.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000044#include "runtime-profiler.h"
ricow@chromium.org55ee8072011-09-08 16:33:10 +000045#include "scanner-character-streams.h"
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000046#include "scopeinfo.h"
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000047#include "scopes.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000048#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049
kasperl@chromium.org71affb52009-05-26 05:44:31 +000050namespace v8 {
51namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000053
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000054CompilationInfo::CompilationInfo(Handle<Script> script, Zone* zone)
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000055 : flags_(LanguageModeField::encode(CLASSIC_MODE)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000056 script_(script),
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000057 osr_ast_id_(BailoutId::None()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000058 Initialize(script->GetIsolate(), BASE, zone);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000059}
60
61
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000062CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
63 Zone* zone)
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000064 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000065 shared_info_(shared_info),
66 script_(Handle<Script>(Script::cast(shared_info->script()))),
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000067 osr_ast_id_(BailoutId::None()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000068 Initialize(script_->GetIsolate(), BASE, zone);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000069}
70
71
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000072CompilationInfo::CompilationInfo(Handle<JSFunction> closure, Zone* zone)
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000073 : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000074 closure_(closure),
75 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
76 script_(Handle<Script>(Script::cast(shared_info_->script()))),
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000077 context_(closure->context()),
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000078 osr_ast_id_(BailoutId::None()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000079 Initialize(script_->GetIsolate(), BASE, zone);
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000080}
81
82
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000083CompilationInfo::CompilationInfo(HydrogenCodeStub* stub,
84 Isolate* isolate, Zone* zone)
85 : flags_(LanguageModeField::encode(CLASSIC_MODE) |
86 IsLazy::encode(true)),
87 osr_ast_id_(BailoutId::None()) {
88 Initialize(isolate, STUB, zone);
89 code_stub_ = stub;
90}
91
92
93void CompilationInfo::Initialize(Isolate* isolate, Mode mode, Zone* zone) {
94 isolate_ = isolate;
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +000095 function_ = NULL;
96 scope_ = NULL;
97 global_scope_ = NULL;
98 extension_ = NULL;
99 pre_parse_data_ = NULL;
100 zone_ = zone;
101 deferred_handles_ = NULL;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000102 code_stub_ = NULL;
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000103 prologue_offset_ = kPrologueOffsetNotSet;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000104 opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000105 if (mode == STUB) {
106 mode_ = STUB;
107 return;
108 }
109 mode_ = V8::UseCrankshaft() ? mode : NONOPT;
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000110 if (script_->type()->value() == Script::TYPE_NATIVE) {
111 MarkAsNative();
112 }
113 if (!shared_info_.is_null()) {
114 ASSERT(language_mode() == CLASSIC_MODE);
115 SetLanguageMode(shared_info_->language_mode());
116 }
117 set_bailout_reason("unknown");
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000118}
119
120
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000121CompilationInfo::~CompilationInfo() {
122 delete deferred_handles_;
123}
124
125
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000126int CompilationInfo::num_parameters() const {
127 if (IsStub()) {
128 return 0;
129 } else {
130 return scope()->num_parameters();
131 }
132}
133
134
135int CompilationInfo::num_heap_slots() const {
136 if (IsStub()) {
137 return 0;
138 } else {
139 return scope()->num_heap_slots();
140 }
141}
142
143
144Code::Flags CompilationInfo::flags() const {
145 if (IsStub()) {
146 return Code::ComputeFlags(Code::COMPILED_STUB);
147 } else {
148 return Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
149 }
150}
151
152
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000153// Disable optimization for the rest of the compilation pipeline.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000154void CompilationInfo::DisableOptimization() {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000155 bool is_optimizable_closure =
156 FLAG_optimize_closures &&
157 closure_.is_null() &&
158 !scope_->HasTrivialOuterContext() &&
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000159 !scope_->outer_scope_calls_non_strict_eval() &&
lrn@chromium.org1c092762011-05-09 09:42:16 +0000160 !scope_->inside_with();
161 SetMode(is_optimizable_closure ? BASE : NONOPT);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000162}
163
164
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000165// Primitive functions are unlikely to be picked up by the stack-walking
166// profiler, so they trigger their own optimization when they're called
167// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
168bool CompilationInfo::ShouldSelfOptimize() {
169 return FLAG_self_optimization &&
170 FLAG_crankshaft &&
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000171 !function()->flags()->Contains(kDontSelfOptimize) &&
yangguo@chromium.orga7d3df92012-02-27 11:46:55 +0000172 !function()->flags()->Contains(kDontOptimize) &&
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000173 function()->scope()->AllowsLazyCompilation() &&
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000174 (shared_info().is_null() || !shared_info()->optimization_disabled());
175}
176
177
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000178void CompilationInfo::AbortOptimization() {
179 Handle<Code> code(shared_info()->code());
180 SetCode(code);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000181}
182
183
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000184// Determine whether to use the full compiler for all code. If the flag
185// --always-full-compiler is specified this is the case. For the virtual frame
186// based compiler the full compiler is also used if a debugger is connected, as
187// the code from the full compiler supports mode precise break points. For the
188// crankshaft adaptive compiler debugging the optimized code is not possible at
189// all. However crankshaft support recompilation of functions, so in this case
190// the full compiler need not be be used if a debugger is attached, but only if
191// break points has actually been set.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000192static bool IsDebuggerActive(Isolate* isolate) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000193#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org1c092762011-05-09 09:42:16 +0000194 return V8::UseCrankshaft() ?
195 isolate->debug()->has_break_points() :
196 isolate->debugger()->IsDebuggerActive();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000197#else
lrn@chromium.org1c092762011-05-09 09:42:16 +0000198 return false;
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000199#endif
200}
201
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000202
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000203static bool AlwaysFullCompiler(Isolate* isolate) {
204 return FLAG_always_full_compiler || IsDebuggerActive(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000205}
206
207
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000208void OptimizingCompiler::RecordOptimizationStats() {
209 Handle<JSFunction> function = info()->closure();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000210 int opt_count = function->shared()->opt_count();
211 function->shared()->set_opt_count(opt_count + 1);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000212 double ms_creategraph =
213 static_cast<double>(time_taken_to_create_graph_) / 1000;
214 double ms_optimize = static_cast<double>(time_taken_to_optimize_) / 1000;
215 double ms_codegen = static_cast<double>(time_taken_to_codegen_) / 1000;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000216 if (FLAG_trace_opt) {
217 PrintF("[optimizing: ");
218 function->PrintName();
219 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000220 PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
221 ms_codegen);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000222 }
223 if (FLAG_trace_opt_stats) {
224 static double compilation_time = 0.0;
225 static int compiled_functions = 0;
226 static int code_size = 0;
227
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000228 compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000229 compiled_functions++;
230 code_size += function->shared()->SourceSize();
231 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
232 compiled_functions,
233 code_size,
234 compilation_time);
235 }
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000236 if (FLAG_hydrogen_stats) {
237 HStatistics::Instance()->IncrementSubtotals(time_taken_to_create_graph_,
238 time_taken_to_optimize_,
239 time_taken_to_codegen_);
240 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000241}
242
243
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000244// A return value of true indicates the compilation pipeline is still
245// going, not necessarily that we optimized the code.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000246static bool MakeCrankshaftCode(CompilationInfo* info) {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000247 OptimizingCompiler compiler(info);
248 OptimizingCompiler::Status status = compiler.CreateGraph();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000249
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000250 if (status != OptimizingCompiler::SUCCEEDED) {
251 return status != OptimizingCompiler::FAILED;
252 }
253 status = compiler.OptimizeGraph();
254 if (status != OptimizingCompiler::SUCCEEDED) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000255 status = compiler.AbortOptimization();
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000256 return status != OptimizingCompiler::FAILED;
257 }
258 status = compiler.GenerateAndInstallCode();
259 return status != OptimizingCompiler::FAILED;
260}
261
262
263OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
264 ASSERT(V8::UseCrankshaft());
265 ASSERT(info()->IsOptimizing());
266 ASSERT(!info()->IsCompilingForDebugging());
267
268 // We should never arrive here if there is no code object on the
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000269 // shared function object.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000270 Handle<Code> code(info()->shared_info()->code());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000271 ASSERT(code->kind() == Code::FUNCTION);
272
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000273 // We should never arrive here if optimization has been disabled on the
274 // shared function info.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000275 ASSERT(!info()->shared_info()->optimization_disabled());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000276
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000277 // Fall back to using the full code generator if it's not possible
278 // to use the Hydrogen-based optimizing compiler. We already have
279 // generated code for this from the shared function object.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000280 if (AlwaysFullCompiler(info()->isolate())) {
281 info()->SetCode(code);
282 return SetLastStatus(BAILED_OUT);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000283 }
284
285 // Limit the number of times we re-compile a functions with
286 // the optimizing compiler.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000287 const int kMaxOptCount =
verwaest@chromium.orgde64f722012-08-16 15:44:54 +0000288 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000289 if (info()->opt_count() > kMaxOptCount) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000290 info()->set_bailout_reason("optimized too many times");
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000291 return AbortOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000292 }
293
294 // Due to an encoding limit on LUnallocated operands in the Lithium
295 // language, we cannot optimize functions with too many formal parameters
296 // or perform on-stack replacement for function with too many
297 // stack-allocated local variables.
298 //
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000299 // The encoding is as a signed value, with parameters and receiver using
300 // the negative indices and locals the non-negative ones.
ager@chromium.org04921a82011-06-27 13:21:41 +0000301 const int parameter_limit = -LUnallocated::kMinFixedIndex;
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000302 Scope* scope = info()->scope();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000303 if ((scope->num_parameters() + 1) > parameter_limit) {
304 info()->set_bailout_reason("too many parameters");
305 return AbortOptimization();
306 }
307
308 const int locals_limit = LUnallocated::kMaxFixedIndex;
309 if (!info()->osr_ast_id().IsNone() &&
310 scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit) {
311 info()->set_bailout_reason("too many parameters/locals");
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000312 return AbortOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000313 }
314
315 // Take --hydrogen-filter into account.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000316 Handle<String> name = info()->function()->debug_name();
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000317 if (*FLAG_hydrogen_filter != '\0') {
318 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
319 if ((filter[0] == '-'
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000320 && name->IsUtf8EqualTo(filter.SubVector(1, filter.length())))
321 || (filter[0] != '-' && !name->IsUtf8EqualTo(filter))) {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000322 info()->SetCode(code);
323 return SetLastStatus(BAILED_OUT);
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000324 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000325 }
326
327 // Recompile the unoptimized version of the code if the current version
328 // doesn't have deoptimization support. Alternatively, we may decide to
329 // run the full code generator to get a baseline for the compile-time
330 // performance of the hydrogen-based compiler.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000331 bool should_recompile = !info()->shared_info()->has_deoptimization_support();
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000332 if (should_recompile || FLAG_hydrogen_stats) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000333 HPhase phase(HPhase::kFullCodeGen);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000334 CompilationInfoWithZone unoptimized(info()->shared_info());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000335 // Note that we use the same AST that we will use for generating the
336 // optimized code.
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000337 unoptimized.SetFunction(info()->function());
338 unoptimized.SetScope(info()->scope());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000339 unoptimized.SetContext(info()->context());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000340 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
341 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
342 if (should_recompile) {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000343 if (!succeeded) return SetLastStatus(FAILED);
344 Handle<SharedFunctionInfo> shared = info()->shared_info();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000345 shared->EnableDeoptimizationSupport(*unoptimized.code());
346 // The existing unoptimized code was replaced with the new one.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000347 Compiler::RecordFunctionCompilation(
348 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000349 }
350 }
351
352 // Check that the unoptimized, shared code is ready for
353 // optimizations. When using the always_opt flag we disregard the
354 // optimizable marker in the code object and optimize anyway. This
355 // is safe as long as the unoptimized code has deoptimization
356 // support.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000357 ASSERT(FLAG_always_opt || code->optimizable());
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000358 ASSERT(info()->shared_info()->has_deoptimization_support());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000359
360 if (FLAG_trace_hydrogen) {
361 PrintF("-----------------------------------------------------------\n");
362 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000363 HTracer::Instance()->TraceCompilation(info());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000364 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000365 Handle<Context> native_context(
366 info()->closure()->context()->native_context());
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000367 oracle_ = new(info()->zone()) TypeFeedbackOracle(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000368 code, native_context, info()->isolate(), info()->zone());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000369 graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info(), oracle_);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000370
371 Timer t(this, &time_taken_to_create_graph_);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000372 graph_ = graph_builder_->CreateGraph();
373
374 if (info()->isolate()->has_pending_exception()) {
375 info()->SetCode(Handle<Code>::null());
376 return SetLastStatus(FAILED);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000377 }
378
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000379 // The function being compiled may have bailed out due to an inline
380 // candidate bailing out. In such a case, we don't disable
381 // optimization on the shared_info.
382 ASSERT(!graph_builder_->inline_bailout() || graph_ == NULL);
383 if (graph_ == NULL) {
384 if (graph_builder_->inline_bailout()) {
385 info_->AbortOptimization();
386 return SetLastStatus(BAILED_OUT);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000387 } else {
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000388 return AbortOptimization();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000389 }
390 }
391
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000392 return SetLastStatus(SUCCEEDED);
393}
394
395OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000396 AssertNoAllocation no_gc;
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000397 NoHandleAllocation no_handles(isolate());
398 NoHandleDereference no_deref(isolate());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000399
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000400 ASSERT(last_status() == SUCCEEDED);
401 Timer t(this, &time_taken_to_optimize_);
402 ASSERT(graph_ != NULL);
403 SmartArrayPointer<char> bailout_reason;
404 if (!graph_->Optimize(&bailout_reason)) {
405 if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000406 return SetLastStatus(BAILED_OUT);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000407 } else {
408 chunk_ = LChunk::NewChunk(graph_);
409 if (chunk_ == NULL) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000410 return SetLastStatus(BAILED_OUT);
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000411 }
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000412 }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000413 return SetLastStatus(SUCCEEDED);
414}
415
416
417OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
418 ASSERT(last_status() == SUCCEEDED);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000419 { // Scope for timer.
420 Timer timer(this, &time_taken_to_codegen_);
421 ASSERT(chunk_ != NULL);
422 ASSERT(graph_ != NULL);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000423 Handle<Code> optimized_code = chunk_->Codegen(Code::OPTIMIZED_FUNCTION);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000424 if (optimized_code.is_null()) {
425 info()->set_bailout_reason("code generation failed");
426 return AbortOptimization();
427 }
428 info()->SetCode(optimized_code);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000429 }
verwaest@chromium.org178fb152012-07-18 11:21:48 +0000430 RecordOptimizationStats();
431 return SetLastStatus(SUCCEEDED);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000432}
433
434
lrn@chromium.org1c092762011-05-09 09:42:16 +0000435static bool GenerateCode(CompilationInfo* info) {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000436 bool is_optimizing = V8::UseCrankshaft() &&
437 !info->IsCompilingForDebugging() &&
438 info->IsOptimizing();
439 if (is_optimizing) {
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000440 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000441 info->isolate(), Logger::TimerEventScope::v8_recompile_synchronous);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000442 return MakeCrankshaftCode(info);
443 } else {
444 if (info->IsOptimizing()) {
445 // Have the CompilationInfo decide if the compilation should be
446 // BASE or NONOPT.
447 info->DisableOptimization();
448 }
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000449 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000450 info->isolate(), Logger::TimerEventScope::v8_compile_full_code);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000451 return FullCodeGenerator::MakeCode(info);
452 }
lrn@chromium.org1c092762011-05-09 09:42:16 +0000453}
454
455
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000456static bool MakeCode(CompilationInfo* info) {
457 // Precondition: code has been parsed. Postcondition: the code field in
458 // the compilation info is set if compilation succeeded.
459 ASSERT(info->function() != NULL);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000460 return Rewriter::Rewrite(info) && Scope::Analyze(info) && GenerateCode(info);
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000461}
462
463
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000464#ifdef ENABLE_DEBUGGER_SUPPORT
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000465bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
466 // Precondition: code has been parsed. Postcondition: the code field in
467 // the compilation info is set if compilation succeeded.
468 bool succeeded = MakeCode(info);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000469 if (!info->shared_info().is_null()) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000470 Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope(),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000471 info->zone());
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000472 info->shared_info()->set_scope_info(*scope_info);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000473 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000474 return succeeded;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000475}
476#endif
477
478
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000479static bool DebuggerWantsEagerCompilation(CompilationInfo* info,
480 bool allow_lazy_without_ctx = false) {
481 return LiveEditFunctionTracker::IsActive(info->isolate()) ||
482 (info->isolate()->DebuggerHasBreakPoints() && !allow_lazy_without_ctx);
483}
484
485
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000486static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000487 Isolate* isolate = info->isolate();
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000488 ZoneScope zone_scope(info->zone(), DELETE_ON_EXIT);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000489 PostponeInterruptsScope postpone(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000491 ASSERT(!isolate->native_context().is_null());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000492 Handle<Script> script = info->script();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000493 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
494 FixedArray* array = isolate->native_context()->embedder_data();
495 script->set_context_data(array->get(0));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000496
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000497#ifdef ENABLE_DEBUGGER_SUPPORT
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000498 if (info->is_eval()) {
499 Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL;
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000500 script->set_compilation_type(Smi::FromInt(compilation_type));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000501 // For eval scripts add information on the function from which eval was
502 // called.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000503 if (info->is_eval()) {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000504 StackTraceFrameIterator it(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000505 if (!it.done()) {
506 script->set_eval_from_shared(
507 JSFunction::cast(it.frame()->function())->shared());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000508 Code* code = it.frame()->LookupCode();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000509 int offset = static_cast<int>(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000510 it.frame()->pc() - code->instruction_start());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000511 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
512 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000513 }
514 }
515
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000516 // Notify debugger
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000517 isolate->debugger()->OnBeforeCompile(script);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000518#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519
520 // Only allow non-global compiles for eval.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000521 ASSERT(info->is_eval() || info->is_global());
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000522 ParsingFlags flags = kNoParsingFlags;
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000523 if ((info->pre_parse_data() != NULL ||
524 String::cast(script->source())->length() > FLAG_min_preparse_length) &&
525 !DebuggerWantsEagerCompilation(info)) {
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000526 flags = kAllowLazy;
527 }
528 if (!ParserApi::Parse(info, flags)) {
529 return Handle<SharedFunctionInfo>::null();
530 }
kasper.lund212ac232008-07-16 07:07:30 +0000531
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000532 // Measure how long it takes to do the compilation; only take the
533 // rest of the function into account to avoid overlap with the
534 // parsing statistics.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000535 HistogramTimer* rate = info->is_eval()
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000536 ? info->isolate()->counters()->compile_eval()
537 : info->isolate()->counters()->compile();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000538 HistogramTimerScope timer(rate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000539
540 // Compile the code.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000541 FunctionLiteral* lit = info->function();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000542 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000543 if (!MakeCode(info)) {
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000544 if (!isolate->has_pending_exception()) isolate->StackOverflow();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000545 return Handle<SharedFunctionInfo>::null();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000546 }
547
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000548 // Allocate function.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000549 ASSERT(!info->code().is_null());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000550 Handle<SharedFunctionInfo> result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000551 isolate->factory()->NewSharedFunctionInfo(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000552 lit->name(),
553 lit->materialized_literal_count(),
554 info->code(),
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000555 ScopeInfo::Create(info->scope(), info->zone()));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000556
557 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
558 Compiler::SetFunctionInfo(result, lit, true, script);
559
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000560 if (script->name()->IsString()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000561 PROFILE(isolate, CodeCreateEvent(
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000562 info->is_eval()
563 ? Logger::EVAL_TAG
564 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
565 *info->code(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000566 *result,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000567 String::cast(script->name())));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000568 GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
569 script,
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000570 info->code(),
571 info));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000572 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000573 PROFILE(isolate, CodeCreateEvent(
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000574 info->is_eval()
575 ? Logger::EVAL_TAG
576 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
577 *info->code(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000578 *result,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000579 isolate->heap()->empty_string()));
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000580 GDBJIT(AddCode(Handle<String>(), script, info->code(), info));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581 }
582
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583 // Hint to the runtime system used when allocating space for initial
584 // property space by setting the expected number of properties for
585 // the instances of the function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000586 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000587
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000588 script->set_compilation_state(
589 Smi::FromInt(Script::COMPILATION_STATE_COMPILED));
590
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000591#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592 // Notify debugger
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000593 isolate->debugger()->OnAfterCompile(
594 script, Debugger::NO_AFTER_COMPILE_FLAGS);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000595#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000597 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000598
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000599 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600}
601
602
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000603Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
604 Handle<Object> script_name,
605 int line_offset,
606 int column_offset,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000607 Handle<Context> context,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000608 v8::Extension* extension,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000609 ScriptDataImpl* pre_data,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000610 Handle<Object> script_data,
611 NativesFlag natives) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000612 Isolate* isolate = source->GetIsolate();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000613 int source_length = source->length();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000614 isolate->counters()->total_load_size()->Increment(source_length);
615 isolate->counters()->total_compile_size()->Increment(source_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616
617 // The VM is in the COMPILER state until exiting this function.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000618 VMState state(isolate, COMPILER);
619
620 CompilationCache* compilation_cache = isolate->compilation_cache();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000622 // Do a lookup in the compilation cache but not for extensions.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000623 Handle<SharedFunctionInfo> result;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000624 if (extension == NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000625 result = compilation_cache->LookupScript(source,
626 script_name,
627 line_offset,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000628 column_offset,
629 context);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630 }
631
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000632 if (result.is_null()) {
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000633 // No cache entry found. Do pre-parsing, if it makes sense, and compile
634 // the script.
635 // Building preparse data that is only used immediately after is only a
636 // saving if we might skip building the AST for lazily compiled functions.
637 // I.e., preparse data isn't relevant when the lazy flag is off, and
638 // for small sources, odds are that there aren't many functions
639 // that would be compiled lazily anyway, so we skip the preparse step
640 // in that case too.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000641
642 // Create a script object describing the script to be compiled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000643 Handle<Script> script = FACTORY->NewScript(source);
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000644 if (natives == NATIVES_CODE) {
645 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
646 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000647 if (!script_name.is_null()) {
648 script->set_name(*script_name);
649 script->set_line_offset(Smi::FromInt(line_offset));
650 script->set_column_offset(Smi::FromInt(column_offset));
651 }
652
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000653 script->set_data(script_data.is_null() ? HEAP->undefined_value()
ager@chromium.org5c838252010-02-19 08:53:10 +0000654 : *script_data);
655
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000656 // Compile the function and add it to the cache.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000657 CompilationInfoWithZone info(script);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000658 info.MarkAsGlobal();
659 info.SetExtension(extension);
660 info.SetPreParseData(pre_data);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000661 info.SetContext(context);
rossberg@chromium.org2c067b12012-03-19 11:01:52 +0000662 if (FLAG_use_strict) {
663 info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE);
664 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000665 result = MakeFunctionInfo(&info);
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000666 if (extension == NULL && !result.is_null() && !result->dont_cache()) {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000667 compilation_cache->PutScript(source, context, result);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000668 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000669 } else {
670 if (result->ic_age() != HEAP->global_ic_age()) {
671 result->ResetForNewContext(HEAP->global_ic_age());
672 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000673 }
674
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000675 if (result.is_null()) isolate->ReportPendingMessages();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000676 return result;
677}
678
679
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000680Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
681 Handle<Context> context,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000682 bool is_global,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000683 LanguageMode language_mode,
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000684 int scope_position) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000685 Isolate* isolate = source->GetIsolate();
ager@chromium.orgc3e50d82008-11-05 11:53:10 +0000686 int source_length = source->length();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000687 isolate->counters()->total_eval_size()->Increment(source_length);
688 isolate->counters()->total_compile_size()->Increment(source_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000689
690 // The VM is in the COMPILER state until exiting this function.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000691 VMState state(isolate, COMPILER);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000692
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000693 // Do a lookup in the compilation cache; if the entry is not there, invoke
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000694 // the compiler and add the result to the cache.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000695 Handle<SharedFunctionInfo> result;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000696 CompilationCache* compilation_cache = isolate->compilation_cache();
697 result = compilation_cache->LookupEval(source,
698 context,
699 is_global,
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000700 language_mode,
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000701 scope_position);
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000702
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000703 if (result.is_null()) {
704 // Create a script object describing the script to be compiled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000705 Handle<Script> script = isolate->factory()->NewScript(source);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000706 CompilationInfoWithZone info(script);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000707 info.MarkAsEval();
708 if (is_global) info.MarkAsGlobal();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000709 info.SetLanguageMode(language_mode);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000710 info.SetContext(context);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000711 result = MakeFunctionInfo(&info);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000712 if (!result.is_null()) {
yangguo@chromium.org56454712012-02-16 15:33:53 +0000713 // Explicitly disable optimization for eval code. We're not yet prepared
714 // to handle eval-code in the optimizing compiler.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000715 result->DisableOptimization("eval");
yangguo@chromium.org56454712012-02-16 15:33:53 +0000716
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000717 // If caller is strict mode, the result must be in strict mode or
718 // extended mode as well, but not the other way around. Consider:
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000719 // eval("'use strict'; ...");
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000720 ASSERT(language_mode != STRICT_MODE || !result->is_classic_mode());
721 // If caller is in extended mode, the result must also be in
722 // extended mode.
723 ASSERT(language_mode != EXTENDED_MODE ||
724 result->is_extended_mode());
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000725 if (!result->dont_cache()) {
726 compilation_cache->PutEval(
727 source, context, is_global, result, scope_position);
728 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000729 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000730 } else {
731 if (result->ic_age() != HEAP->global_ic_age()) {
732 result->ResetForNewContext(HEAP->global_ic_age());
733 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000734 }
ager@chromium.org8bb60582008-12-11 12:02:20 +0000735
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000736 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737}
738
739
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000740static bool InstallFullCode(CompilationInfo* info) {
741 // Update the shared function info with the compiled code and the
742 // scope info. Please note, that the order of the shared function
743 // info initialization is important since set_scope_info might
744 // trigger a GC, causing the ASSERT below to be invalid if the code
745 // was flushed. By setting the code object last we avoid this.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000746 Handle<SharedFunctionInfo> shared = info->shared_info();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000747 Handle<Code> code = info->code();
748 Handle<JSFunction> function = info->closure();
749 Handle<ScopeInfo> scope_info =
750 ScopeInfo::Create(info->scope(), info->zone());
751 shared->set_scope_info(*scope_info);
yangguo@chromium.org9768bf12013-01-11 14:51:07 +0000752 shared->ReplaceCode(*code);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000753 if (!function.is_null()) {
754 function->ReplaceCode(*code);
755 ASSERT(!function->IsOptimized());
756 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000758 // Set the expected number of properties for instances.
759 FunctionLiteral* lit = info->function();
760 int expected = lit->expected_property_count();
761 SetExpectedNofPropertiesFromEstimate(shared, expected);
762
763 // Set the optimization hints after performing lazy compilation, as
764 // these are not set when the function is set up as a lazily
765 // compiled function.
766 shared->SetThisPropertyAssignmentsInfo(
767 lit->has_only_simple_this_property_assignments(),
768 *lit->this_property_assignments());
769
770 // Check the function has compiled code.
771 ASSERT(shared->is_compiled());
772 shared->set_code_age(0);
773 shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
774 shared->set_dont_inline(lit->flags()->Contains(kDontInline));
775 shared->set_ast_node_count(lit->ast_node_count());
776
jkummerow@chromium.org000f7fb2012-08-01 11:14:42 +0000777 if (V8::UseCrankshaft() &&
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000778 !function.is_null() &&
779 !shared->optimization_disabled()) {
780 // If we're asked to always optimize, we compile the optimized
781 // version of the function right away - unless the debugger is
782 // active as it makes no sense to compile optimized code then.
783 if (FLAG_always_opt &&
784 !Isolate::Current()->DebuggerHasBreakPoints()) {
785 CompilationInfoWithZone optimized(function);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000786 optimized.SetOptimizing(BailoutId::None());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000787 return Compiler::CompileLazy(&optimized);
788 }
789 }
790 return true;
791}
792
793
794static void InstallCodeCommon(CompilationInfo* info) {
795 Handle<SharedFunctionInfo> shared = info->shared_info();
796 Handle<Code> code = info->code();
797 ASSERT(!code.is_null());
798
799 // Set optimizable to false if this is disallowed by the shared
800 // function info, e.g., we might have flushed the code and must
801 // reset this bit when lazy compiling the code again.
802 if (shared->optimization_disabled()) code->set_optimizable(false);
803
804 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
805}
806
807
808static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
809 Handle<Code> code = info->code();
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000810 if (FLAG_cache_optimized_code &&
811 info->osr_ast_id().IsNone() &&
812 code->kind() == Code::OPTIMIZED_FUNCTION) {
813 Handle<JSFunction> function = info->closure();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000814 Handle<SharedFunctionInfo> shared(function->shared());
815 Handle<FixedArray> literals(function->literals());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000816 Handle<Context> native_context(function->context()->native_context());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000817 SharedFunctionInfo::AddToOptimizedCodeMap(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000818 shared, native_context, code, literals);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000819 }
820}
821
822
823static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000824 if (FLAG_cache_optimized_code &&
825 info->osr_ast_id().IsNone() &&
826 info->IsOptimizing()) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000827 Handle<SharedFunctionInfo> shared = info->shared_info();
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000828 Handle<JSFunction> function = info->closure();
829 ASSERT(!function.is_null());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000830 Handle<Context> native_context(function->context()->native_context());
831 int index = shared->SearchOptimizedCodeMap(*native_context);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000832 if (index > 0) {
833 if (FLAG_trace_opt) {
ulan@chromium.orgd9e468a2012-06-25 09:47:40 +0000834 PrintF("[found optimized code for: ");
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000835 function->PrintName();
ulan@chromium.orgd9e468a2012-06-25 09:47:40 +0000836 PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(*function));
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000837 }
ulan@chromium.orgd9e468a2012-06-25 09:47:40 +0000838 // Caching of optimized code enabled and optimized code found.
839 shared->InstallFromOptimizedCodeMap(*function, index);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000840 return true;
841 }
842 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000843 return false;
844}
845
846
847bool Compiler::CompileLazy(CompilationInfo* info) {
848 Isolate* isolate = info->isolate();
849
850 ZoneScope zone_scope(info->zone(), DELETE_ON_EXIT);
851
852 // The VM is in the COMPILER state until exiting this function.
853 VMState state(isolate, COMPILER);
854
855 PostponeInterruptsScope postpone(isolate);
856
857 Handle<SharedFunctionInfo> shared = info->shared_info();
858 int compiled_size = shared->end_position() - shared->start_position();
859 isolate->counters()->total_compile_size()->Increment(compiled_size);
860
861 if (InstallCodeFromOptimizedCodeMap(info)) return true;
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000862
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000863 // Generate the AST for the lazily compiled function.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000864 if (ParserApi::Parse(info, kNoParsingFlags)) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000865 // Measure how long it takes to do the lazy compilation; only take the
866 // rest of the function into account to avoid overlap with the lazy
867 // parsing statistics.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000868 HistogramTimerScope timer(isolate->counters()->compile_lazy());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000869
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000870 // After parsing we know the function's language mode. Remember it.
871 LanguageMode language_mode = info->function()->language_mode();
872 info->SetLanguageMode(language_mode);
873 shared->set_language_mode(language_mode);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000874
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000875 // Compile the code.
876 if (!MakeCode(info)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000877 if (!isolate->has_pending_exception()) {
878 isolate->StackOverflow();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000879 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000880 } else {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000881 InstallCodeCommon(info);
kasper.lund212ac232008-07-16 07:07:30 +0000882
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000883 if (info->IsOptimizing()) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000884 Handle<Code> code = info->code();
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000885 ASSERT(shared->scope_info() != ScopeInfo::Empty(isolate));
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000886 info->closure()->ReplaceCode(*code);
887 InsertCodeIntoOptimizedCodeMap(info);
888 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000889 } else {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000890 return InstallFullCode(info);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000891 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000892 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893 }
894
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000895 ASSERT(info->code().is_null());
896 return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000897}
898
899
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000900void Compiler::RecompileParallel(Handle<JSFunction> closure) {
901 if (closure->IsInRecompileQueue()) return;
902 ASSERT(closure->IsMarkedForParallelRecompilation());
903
904 Isolate* isolate = closure->GetIsolate();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000905 // Here we prepare compile data for the parallel recompilation thread, but
906 // this still happens synchronously and interrupts execution.
907 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000908 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000909
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000910 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
911 if (FLAG_trace_parallel_recompilation) {
912 PrintF(" ** Compilation queue, will retry opting on next run.\n");
913 }
914 return;
915 }
916
917 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure));
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000918 VMState state(isolate, PARALLEL_COMPILER);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000919 PostponeInterruptsScope postpone(isolate);
920
921 Handle<SharedFunctionInfo> shared = info->shared_info();
922 int compiled_size = shared->end_position() - shared->start_position();
923 isolate->counters()->total_compile_size()->Increment(compiled_size);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000924 info->SetOptimizing(BailoutId::None());
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000925
926 {
927 CompilationHandleScope handle_scope(*info);
928
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000929 if (!FLAG_manual_parallel_recompilation &&
930 InstallCodeFromOptimizedCodeMap(*info)) {
931 return;
932 }
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000933
934 if (ParserApi::Parse(*info, kNoParsingFlags)) {
935 LanguageMode language_mode = info->function()->language_mode();
936 info->SetLanguageMode(language_mode);
937 shared->set_language_mode(language_mode);
938 info->SaveHandles();
939
940 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) {
941 OptimizingCompiler* compiler =
942 new(info->zone()) OptimizingCompiler(*info);
943 OptimizingCompiler::Status status = compiler->CreateGraph();
944 if (status == OptimizingCompiler::SUCCEEDED) {
945 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
946 shared->code()->set_profiler_ticks(0);
947 closure->ReplaceCode(isolate->builtins()->builtin(
948 Builtins::kInRecompileQueue));
949 info.Detach();
950 } else if (status == OptimizingCompiler::BAILED_OUT) {
951 isolate->clear_pending_exception();
952 InstallFullCode(*info);
953 }
954 }
955 }
956 }
957
958 if (isolate->has_pending_exception()) {
959 isolate->clear_pending_exception();
960 }
961}
962
963
964void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
965 SmartPointer<CompilationInfo> info(optimizing_compiler->info());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000966 Isolate* isolate = info->isolate();
967 VMState state(isolate, PARALLEL_COMPILER);
968 Logger::TimerEventScope timer(
danno@chromium.org1f34ad32012-11-26 14:53:56 +0000969 isolate, Logger::TimerEventScope::v8_recompile_synchronous);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000970 // If crankshaft succeeded, install the optimized code else install
971 // the unoptimized code.
972 OptimizingCompiler::Status status = optimizing_compiler->last_status();
973 if (status != OptimizingCompiler::SUCCEEDED) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000974 optimizing_compiler->info()->set_bailout_reason(
975 "failed/bailed out last time");
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000976 status = optimizing_compiler->AbortOptimization();
977 } else {
978 status = optimizing_compiler->GenerateAndInstallCode();
979 ASSERT(status == OptimizingCompiler::SUCCEEDED ||
980 status == OptimizingCompiler::BAILED_OUT);
981 }
982
983 InstallCodeCommon(*info);
984 if (status == OptimizingCompiler::SUCCEEDED) {
985 Handle<Code> code = info->code();
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000986 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate));
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000987 info->closure()->ReplaceCode(*code);
988 if (info->shared_info()->SearchOptimizedCodeMap(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000989 info->closure()->context()->native_context()) == -1) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000990 InsertCodeIntoOptimizedCodeMap(*info);
991 }
992 } else {
993 info->SetCode(Handle<Code>(info->shared_info()->code()));
994 InstallFullCode(*info);
995 }
996}
997
998
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000999Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001000 Handle<Script> script) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001001 // Precondition: code has been parsed and scopes have been analyzed.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001002 CompilationInfoWithZone info(script);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001003 info.SetFunction(literal);
1004 info.SetScope(literal->scope());
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001005 info.SetLanguageMode(literal->scope()->language_mode());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001006
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001007 Isolate* isolate = info.isolate();
1008 LiveEditFunctionTracker live_edit_tracker(isolate, literal);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001009 // Determine if the function can be lazily compiled. This is necessary to
1010 // allow some of our builtin JS files to be lazily compiled. These
1011 // builtins cannot be handled lazily by the parser, since we have to know
1012 // if a function uses the special natives syntax, which is something the
1013 // parser records.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001014 // If the debugger requests compilation for break points, we cannot be
1015 // aggressive about lazy compilation, because it might trigger compilation
1016 // of functions without an outer context when setting a breakpoint through
jkummerow@chromium.org78502a92012-09-06 13:50:42 +00001017 // Debug::FindSharedFunctionInfoInScript.
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001018 bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext();
ager@chromium.org5c838252010-02-19 08:53:10 +00001019 bool allow_lazy = literal->AllowsLazyCompilation() &&
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001020 !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001021
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001022 Handle<ScopeInfo> scope_info(ScopeInfo::Empty(isolate));
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001023
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001024 // Generate code
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001025 if (FLAG_lazy && allow_lazy && !literal->is_parenthesized()) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001026 Handle<Code> code = isolate->builtins()->LazyCompile();
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001027 info.SetCode(code);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001028 } else if (GenerateCode(&info)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001029 ASSERT(!info.code().is_null());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001030 scope_info = ScopeInfo::Create(info.scope(), info.zone());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001031 } else {
1032 return Handle<SharedFunctionInfo>::null();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001033 }
1034
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00001035 // Create a shared function info object.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001036 Handle<SharedFunctionInfo> result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001037 FACTORY->NewSharedFunctionInfo(literal->name(),
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001038 literal->materialized_literal_count(),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001039 info.code(),
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001040 scope_info);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001041 SetFunctionInfo(result, literal, false, script);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001042 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001043 result->set_allows_lazy_compilation(allow_lazy);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001044 result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001045
1046 // Set the expected number of properties for instances and return
1047 // the resulting function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001048 SetExpectedNofPropertiesFromEstimate(result,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001049 literal->expected_property_count());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001050 live_edit_tracker.RecordFunctionInfo(result, literal, info.zone());
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001051 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001052}
1053
1054
1055// Sets the function info on a function.
1056// The start_position points to the first '(' character after the function name
1057// in the full script source. When counting characters in the script source the
1058// the first character is number 0 (not 1).
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001059void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001060 FunctionLiteral* lit,
1061 bool is_toplevel,
1062 Handle<Script> script) {
danno@chromium.orgc612e022011-11-10 11:38:15 +00001063 function_info->set_length(lit->parameter_count());
1064 function_info->set_formal_parameter_count(lit->parameter_count());
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001065 function_info->set_script(*script);
1066 function_info->set_function_token_position(lit->function_token_position());
1067 function_info->set_start_position(lit->start_position());
1068 function_info->set_end_position(lit->end_position());
1069 function_info->set_is_expression(lit->is_expression());
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00001070 function_info->set_is_anonymous(lit->is_anonymous());
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001071 function_info->set_is_toplevel(is_toplevel);
1072 function_info->set_inferred_name(*lit->inferred_name());
1073 function_info->SetThisPropertyAssignmentsInfo(
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001074 lit->has_only_simple_this_property_assignments(),
1075 *lit->this_property_assignments());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001076 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001077 function_info->set_allows_lazy_compilation_without_context(
1078 lit->AllowsLazyCompilationWithoutContext());
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001079 function_info->set_language_mode(lit->language_mode());
whesse@chromium.org7b260152011-06-20 15:33:18 +00001080 function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
1081 function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001082 function_info->set_ast_node_count(lit->ast_node_count());
yangguo@chromium.org56454712012-02-16 15:33:53 +00001083 function_info->set_is_function(lit->is_function());
1084 function_info->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001085 function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001086 function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001087}
1088
1089
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001090void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001091 CompilationInfo* info,
1092 Handle<SharedFunctionInfo> shared) {
1093 // SharedFunctionInfo is passed separately, because if CompilationInfo
1094 // was created using Script object, it will not have it.
1095
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001096 // Log the code generation. If source information is available include
1097 // script name and line number. Check explicitly whether logging is
1098 // enabled as finding the line number is not free.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001099 if (info->isolate()->logger()->is_logging_code_events() ||
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001100 CpuProfiler::is_profiling(info->isolate())) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001101 Handle<Script> script = info->script();
1102 Handle<Code> code = info->code();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001103 if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001104 return;
ager@chromium.org5c838252010-02-19 08:53:10 +00001105 if (script->name()->IsString()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001106 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001107 USE(line_num);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001108 PROFILE(info->isolate(),
1109 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001110 *code,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001111 *shared,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001112 String::cast(script->name()),
1113 line_num));
ager@chromium.org5c838252010-02-19 08:53:10 +00001114 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001115 PROFILE(info->isolate(),
1116 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001117 *code,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001118 *shared,
1119 shared->DebugName()));
ager@chromium.org5c838252010-02-19 08:53:10 +00001120 }
1121 }
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001122
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001123 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001124 Handle<Script>(info->script()),
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001125 Handle<Code>(info->code()),
1126 info));
ager@chromium.org5c838252010-02-19 08:53:10 +00001127}
ager@chromium.org5c838252010-02-19 08:53:10 +00001128
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001129} } // namespace v8::internal