blob: 62402e18fa9ddf501dfe5ec973c3b846f3d9e7f0 [file] [log] [blame]
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001// Copyright 2011 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"
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000039#include "lithium.h"
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000040#include "liveedit.h"
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000041#include "parser.h"
ager@chromium.org71daaf62009-04-01 07:22:49 +000042#include "rewriter.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000043#include "runtime-profiler.h"
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000044#include "scopeinfo.h"
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000045#include "scopes.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000046#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000047
kasperl@chromium.org71affb52009-05-26 05:44:31 +000048namespace v8 {
49namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000051
52CompilationInfo::CompilationInfo(Handle<Script> script)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000053 : isolate_(script->GetIsolate()),
54 flags_(0),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000055 function_(NULL),
56 scope_(NULL),
57 script_(script),
58 extension_(NULL),
kasperl@chromium.orga5551262010-12-07 12:49:48 +000059 pre_parse_data_(NULL),
60 supports_deoptimization_(false),
61 osr_ast_id_(AstNode::kNoNumber) {
62 Initialize(NONOPT);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000063}
64
65
66CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000067 : isolate_(shared_info->GetIsolate()),
68 flags_(IsLazy::encode(true)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000069 function_(NULL),
70 scope_(NULL),
71 shared_info_(shared_info),
72 script_(Handle<Script>(Script::cast(shared_info->script()))),
73 extension_(NULL),
kasperl@chromium.orga5551262010-12-07 12:49:48 +000074 pre_parse_data_(NULL),
75 supports_deoptimization_(false),
76 osr_ast_id_(AstNode::kNoNumber) {
77 Initialize(BASE);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000078}
79
80
81CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000082 : isolate_(closure->GetIsolate()),
83 flags_(IsLazy::encode(true)),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000084 function_(NULL),
85 scope_(NULL),
86 closure_(closure),
87 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
88 script_(Handle<Script>(Script::cast(shared_info_->script()))),
89 extension_(NULL),
kasperl@chromium.orga5551262010-12-07 12:49:48 +000090 pre_parse_data_(NULL),
91 supports_deoptimization_(false),
92 osr_ast_id_(AstNode::kNoNumber) {
93 Initialize(BASE);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000094}
95
96
ager@chromium.orgea91cc52011-05-23 06:06:11 +000097// Disable optimization for the rest of the compilation pipeline.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000098void CompilationInfo::DisableOptimization() {
lrn@chromium.org1c092762011-05-09 09:42:16 +000099 bool is_optimizable_closure =
100 FLAG_optimize_closures &&
101 closure_.is_null() &&
102 !scope_->HasTrivialOuterContext() &&
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000103 !scope_->outer_scope_calls_non_strict_eval() &&
lrn@chromium.org1c092762011-05-09 09:42:16 +0000104 !scope_->inside_with();
105 SetMode(is_optimizable_closure ? BASE : NONOPT);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000106}
107
108
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000109void CompilationInfo::AbortOptimization() {
110 Handle<Code> code(shared_info()->code());
111 SetCode(code);
112 Isolate* isolate = code->GetIsolate();
113 isolate->compilation_cache()->MarkForLazyOptimizing(closure());
114}
115
116
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117// Determine whether to use the full compiler for all code. If the flag
118// --always-full-compiler is specified this is the case. For the virtual frame
119// based compiler the full compiler is also used if a debugger is connected, as
120// the code from the full compiler supports mode precise break points. For the
121// crankshaft adaptive compiler debugging the optimized code is not possible at
122// all. However crankshaft support recompilation of functions, so in this case
123// the full compiler need not be be used if a debugger is attached, but only if
124// break points has actually been set.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000125static bool is_debugging_active() {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000126#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000127 Isolate* isolate = Isolate::Current();
lrn@chromium.org1c092762011-05-09 09:42:16 +0000128 return V8::UseCrankshaft() ?
129 isolate->debug()->has_break_points() :
130 isolate->debugger()->IsDebuggerActive();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000131#else
lrn@chromium.org1c092762011-05-09 09:42:16 +0000132 return false;
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000133#endif
134}
135
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000136
lrn@chromium.org1c092762011-05-09 09:42:16 +0000137static bool AlwaysFullCompiler() {
138 return FLAG_always_full_compiler || is_debugging_active();
139}
140
141
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000142static void FinishOptimization(Handle<JSFunction> function, int64_t start) {
143 int opt_count = function->shared()->opt_count();
144 function->shared()->set_opt_count(opt_count + 1);
lrn@chromium.org8541d772010-12-15 12:05:09 +0000145 double ms = static_cast<double>(OS::Ticks() - start) / 1000;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000146 if (FLAG_trace_opt) {
147 PrintF("[optimizing: ");
148 function->PrintName();
149 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
150 PrintF(" - took %0.3f ms]\n", ms);
151 }
152 if (FLAG_trace_opt_stats) {
153 static double compilation_time = 0.0;
154 static int compiled_functions = 0;
155 static int code_size = 0;
156
157 compilation_time += ms;
158 compiled_functions++;
159 code_size += function->shared()->SourceSize();
160 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
161 compiled_functions,
162 code_size,
163 compilation_time);
164 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000165}
166
167
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000168static bool MakeCrankshaftCode(CompilationInfo* info) {
169 // Test if we can optimize this function when asked to. We can only
170 // do this after the scopes are computed.
171 if (!info->AllowOptimize()) info->DisableOptimization();
172
173 // In case we are not optimizing simply return the code from
174 // the full code generator.
175 if (!info->IsOptimizing()) {
176 return FullCodeGenerator::MakeCode(info);
177 }
178
179 // We should never arrive here if there is not code object on the
180 // shared function object.
181 Handle<Code> code(info->shared_info()->code());
182 ASSERT(code->kind() == Code::FUNCTION);
183
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000184 // We should never arrive here if optimization has been disabled on the
185 // shared function info.
186 ASSERT(!info->shared_info()->optimization_disabled());
187
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000188 // Fall back to using the full code generator if it's not possible
189 // to use the Hydrogen-based optimizing compiler. We already have
190 // generated code for this from the shared function object.
191 if (AlwaysFullCompiler() || !FLAG_use_hydrogen) {
192 info->SetCode(code);
193 return true;
194 }
195
196 // Limit the number of times we re-compile a functions with
197 // the optimizing compiler.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000198 const int kMaxOptCount =
199 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000200 if (info->shared_info()->opt_count() > kMaxOptCount) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000201 info->AbortOptimization();
202 Handle<JSFunction> closure = info->closure();
203 info->shared_info()->DisableOptimization(*closure);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000204 // True indicates the compilation pipeline is still going, not
205 // necessarily that we optimized the code.
206 return true;
207 }
208
209 // Due to an encoding limit on LUnallocated operands in the Lithium
210 // language, we cannot optimize functions with too many formal parameters
211 // or perform on-stack replacement for function with too many
212 // stack-allocated local variables.
213 //
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000214 // The encoding is as a signed value, with parameters and receiver using
215 // the negative indices and locals the non-negative ones.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000216 const int parameter_limit = (LUnallocated::kMaxFixedIndices / 2);
217 const int locals_limit = parameter_limit - 1;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000218 Scope* scope = info->scope();
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000219 if ((scope->num_parameters() + 1) > parameter_limit ||
220 scope->num_stack_slots() > locals_limit) {
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000221 info->AbortOptimization();
222 Handle<JSFunction> closure = info->closure();
223 info->shared_info()->DisableOptimization(*closure);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000224 // True indicates the compilation pipeline is still going, not
225 // necessarily that we optimized the code.
226 return true;
227 }
228
229 // Take --hydrogen-filter into account.
230 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
231 Handle<String> name = info->function()->debug_name();
232 bool match = filter.is_empty() || name->IsEqualTo(filter);
233 if (!match) {
234 info->SetCode(code);
235 return true;
236 }
237
238 // Recompile the unoptimized version of the code if the current version
239 // doesn't have deoptimization support. Alternatively, we may decide to
240 // run the full code generator to get a baseline for the compile-time
241 // performance of the hydrogen-based compiler.
242 int64_t start = OS::Ticks();
243 bool should_recompile = !info->shared_info()->has_deoptimization_support();
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000244 if (should_recompile || FLAG_hydrogen_stats) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000245 HPhase phase(HPhase::kFullCodeGen);
246 CompilationInfo unoptimized(info->shared_info());
247 // Note that we use the same AST that we will use for generating the
248 // optimized code.
249 unoptimized.SetFunction(info->function());
250 unoptimized.SetScope(info->scope());
251 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
252 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
253 if (should_recompile) {
254 if (!succeeded) return false;
255 Handle<SharedFunctionInfo> shared = info->shared_info();
256 shared->EnableDeoptimizationSupport(*unoptimized.code());
257 // The existing unoptimized code was replaced with the new one.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000258 Compiler::RecordFunctionCompilation(
259 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000260 }
261 }
262
263 // Check that the unoptimized, shared code is ready for
264 // optimizations. When using the always_opt flag we disregard the
265 // optimizable marker in the code object and optimize anyway. This
266 // is safe as long as the unoptimized code has deoptimization
267 // support.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000268 ASSERT(FLAG_always_opt || code->optimizable());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000269 ASSERT(info->shared_info()->has_deoptimization_support());
270
271 if (FLAG_trace_hydrogen) {
272 PrintF("-----------------------------------------------------------\n");
273 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
274 HTracer::Instance()->TraceCompilation(info->function());
275 }
276
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000277 Handle<Context> global_context(info->closure()->context()->global_context());
278 TypeFeedbackOracle oracle(code, global_context);
279 HGraphBuilder builder(info, &oracle);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000280 HPhase phase(HPhase::kTotal);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000281 HGraph* graph = builder.CreateGraph();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000282 if (info->isolate()->has_pending_exception()) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000283 info->SetCode(Handle<Code>::null());
284 return false;
285 }
286
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000287 if (graph != NULL && FLAG_build_lithium) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000288 Handle<Code> optimized_code = graph->Compile(info);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000289 if (!optimized_code.is_null()) {
290 info->SetCode(optimized_code);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000291 FinishOptimization(info->closure(), start);
292 return true;
293 }
294 }
295
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000296 // Keep using the shared code.
297 info->AbortOptimization();
298 if (!builder.inline_bailout()) {
299 // Mark the shared code as unoptimizable unless it was an inlined
300 // function that bailed out.
301 Handle<JSFunction> closure = info->closure();
302 info->shared_info()->DisableOptimization(*closure);
303 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000304 // True indicates the compilation pipeline is still going, not necessarily
305 // that we optimized the code.
306 return true;
307}
308
309
lrn@chromium.org1c092762011-05-09 09:42:16 +0000310static bool GenerateCode(CompilationInfo* info) {
311 return V8::UseCrankshaft() ?
312 MakeCrankshaftCode(info) :
313 FullCodeGenerator::MakeCode(info);
314}
315
316
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000317static bool MakeCode(CompilationInfo* info) {
318 // Precondition: code has been parsed. Postcondition: the code field in
319 // the compilation info is set if compilation succeeded.
320 ASSERT(info->function() != NULL);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000321 return Rewriter::Rewrite(info) && Scope::Analyze(info) && GenerateCode(info);
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000322}
323
324
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000325#ifdef ENABLE_DEBUGGER_SUPPORT
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000326bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
327 // Precondition: code has been parsed. Postcondition: the code field in
328 // the compilation info is set if compilation succeeded.
329 bool succeeded = MakeCode(info);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000330 if (!info->shared_info().is_null()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000331 Handle<SerializedScopeInfo> scope_info =
332 SerializedScopeInfo::Create(info->scope());
333 info->shared_info()->set_scope_info(*scope_info);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000334 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000335 return succeeded;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000336}
337#endif
338
339
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000340static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000341 Isolate* isolate = info->isolate();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000342 ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000343 PostponeInterruptsScope postpone(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000345 ASSERT(!isolate->global_context().is_null());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000346 Handle<Script> script = info->script();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000347 script->set_context_data((*isolate->global_context())->data());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000348
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000349#ifdef ENABLE_DEBUGGER_SUPPORT
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000350 if (info->is_eval()) {
351 Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL;
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000352 script->set_compilation_type(Smi::FromInt(compilation_type));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000353 // For eval scripts add information on the function from which eval was
354 // called.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000355 if (info->is_eval()) {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000356 StackTraceFrameIterator it(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000357 if (!it.done()) {
358 script->set_eval_from_shared(
359 JSFunction::cast(it.frame()->function())->shared());
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000360 Code* code = it.frame()->LookupCode();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000361 int offset = static_cast<int>(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000362 it.frame()->pc() - code->instruction_start());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000363 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
364 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000365 }
366 }
367
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 // Notify debugger
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000369 isolate->debugger()->OnBeforeCompile(script);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000370#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371
372 // Only allow non-global compiles for eval.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000373 ASSERT(info->is_eval() || info->is_global());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000374
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000375 if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
kasper.lund212ac232008-07-16 07:07:30 +0000376
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000377 // Measure how long it takes to do the compilation; only take the
378 // rest of the function into account to avoid overlap with the
379 // parsing statistics.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000380 HistogramTimer* rate = info->is_eval()
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000381 ? info->isolate()->counters()->compile_eval()
382 : info->isolate()->counters()->compile();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000383 HistogramTimerScope timer(rate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384
385 // Compile the code.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000386 FunctionLiteral* lit = info->function();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000387 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000388 if (!MakeCode(info)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000389 isolate->StackOverflow();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000390 return Handle<SharedFunctionInfo>::null();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000391 }
392
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000393 // Allocate function.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000394 ASSERT(!info->code().is_null());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000395 Handle<SharedFunctionInfo> result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000396 isolate->factory()->NewSharedFunctionInfo(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000397 lit->name(),
398 lit->materialized_literal_count(),
399 info->code(),
400 SerializedScopeInfo::Create(info->scope()));
401
402 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
403 Compiler::SetFunctionInfo(result, lit, true, script);
404
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000405 if (script->name()->IsString()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000406 PROFILE(isolate, CodeCreateEvent(
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000407 info->is_eval()
408 ? Logger::EVAL_TAG
409 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
410 *info->code(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000411 *result,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000412 String::cast(script->name())));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000413 GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
414 script,
415 info->code()));
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000416 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000417 PROFILE(isolate, CodeCreateEvent(
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000418 info->is_eval()
419 ? Logger::EVAL_TAG
420 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
421 *info->code(),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000422 *result,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000423 isolate->heap()->empty_string()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000424 GDBJIT(AddCode(Handle<String>(), script, info->code()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000425 }
426
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427 // Hint to the runtime system used when allocating space for initial
428 // property space by setting the expected number of properties for
429 // the instances of the function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000430 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000432#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000433 // Notify debugger
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000434 isolate->debugger()->OnAfterCompile(
435 script, Debugger::NO_AFTER_COMPILE_FLAGS);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000436#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000437
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000438 live_edit_tracker.RecordFunctionInfo(result, lit);
439
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000440 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000441}
442
443
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000444Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
445 Handle<Object> script_name,
446 int line_offset,
447 int column_offset,
448 v8::Extension* extension,
449 ScriptDataImpl* input_pre_data,
450 Handle<Object> script_data,
451 NativesFlag natives) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000452 Isolate* isolate = source->GetIsolate();
ager@chromium.org870a0b62008-11-04 11:43:05 +0000453 int source_length = source->length();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000454 isolate->counters()->total_load_size()->Increment(source_length);
455 isolate->counters()->total_compile_size()->Increment(source_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456
457 // The VM is in the COMPILER state until exiting this function.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000458 VMState state(isolate, COMPILER);
459
460 CompilationCache* compilation_cache = isolate->compilation_cache();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000462 // Do a lookup in the compilation cache but not for extensions.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000463 Handle<SharedFunctionInfo> result;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000464 if (extension == NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000465 result = compilation_cache->LookupScript(source,
466 script_name,
467 line_offset,
468 column_offset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000469 }
470
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000471 if (result.is_null()) {
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000472 // No cache entry found. Do pre-parsing, if it makes sense, and compile
473 // the script.
474 // Building preparse data that is only used immediately after is only a
475 // saving if we might skip building the AST for lazily compiled functions.
476 // I.e., preparse data isn't relevant when the lazy flag is off, and
477 // for small sources, odds are that there aren't many functions
478 // that would be compiled lazily anyway, so we skip the preparse step
479 // in that case too.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000480 ScriptDataImpl* pre_data = input_pre_data;
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000481 if (pre_data == NULL
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000482 && source_length >= FLAG_min_preparse_length) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000483 if (source->IsExternalTwoByteString()) {
484 ExternalTwoByteStringUC16CharacterStream stream(
485 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
486 pre_data = ParserApi::PartialPreParse(&stream, extension);
487 } else {
488 GenericStringUC16CharacterStream stream(source, 0, source->length());
489 pre_data = ParserApi::PartialPreParse(&stream, extension);
490 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000491 }
492
493 // Create a script object describing the script to be compiled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000494 Handle<Script> script = FACTORY->NewScript(source);
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000495 if (natives == NATIVES_CODE) {
496 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
497 }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000498 if (!script_name.is_null()) {
499 script->set_name(*script_name);
500 script->set_line_offset(Smi::FromInt(line_offset));
501 script->set_column_offset(Smi::FromInt(column_offset));
502 }
503
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000504 script->set_data(script_data.is_null() ? HEAP->undefined_value()
ager@chromium.org5c838252010-02-19 08:53:10 +0000505 : *script_data);
506
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000507 // Compile the function and add it to the cache.
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000508 CompilationInfo info(script);
509 info.MarkAsGlobal();
510 info.SetExtension(extension);
511 info.SetPreParseData(pre_data);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000512 if (natives == NATIVES_CODE) {
513 info.MarkAsAllowingNativesSyntax();
514 info.MarkAsNative();
515 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000516 result = MakeFunctionInfo(&info);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000517 if (extension == NULL && !result.is_null()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000518 compilation_cache->PutScript(source, result);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000519 }
520
521 // Get rid of the pre-parsing data (if necessary).
522 if (input_pre_data == NULL && pre_data != NULL) {
523 delete pre_data;
524 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 }
526
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000527 if (result.is_null()) isolate->ReportPendingMessages();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 return result;
529}
530
531
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000532Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
533 Handle<Context> context,
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000534 bool is_global,
535 StrictModeFlag strict_mode) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000536 Isolate* isolate = source->GetIsolate();
ager@chromium.orgc3e50d82008-11-05 11:53:10 +0000537 int source_length = source->length();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000538 isolate->counters()->total_eval_size()->Increment(source_length);
539 isolate->counters()->total_compile_size()->Increment(source_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000540
541 // The VM is in the COMPILER state until exiting this function.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000542 VMState state(isolate, COMPILER);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000544 // Do a lookup in the compilation cache; if the entry is not there, invoke
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000545 // the compiler and add the result to the cache.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000546 Handle<SharedFunctionInfo> result;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000547 CompilationCache* compilation_cache = isolate->compilation_cache();
548 result = compilation_cache->LookupEval(source,
549 context,
550 is_global,
551 strict_mode);
ager@chromium.orgadd848f2009-08-13 12:44:13 +0000552
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000553 if (result.is_null()) {
554 // Create a script object describing the script to be compiled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000555 Handle<Script> script = isolate->factory()->NewScript(source);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000556 CompilationInfo info(script);
557 info.MarkAsEval();
558 if (is_global) info.MarkAsGlobal();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000559 if (strict_mode == kStrictMode) info.MarkAsStrictMode();
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000560 info.SetCallingContext(context);
561 result = MakeFunctionInfo(&info);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000562 if (!result.is_null()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000563 CompilationCache* compilation_cache = isolate->compilation_cache();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000564 // If caller is strict mode, the result must be strict as well,
565 // but not the other way around. Consider:
566 // eval("'use strict'; ...");
567 ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000568 compilation_cache->PutEval(source, context, is_global, result);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000569 }
570 }
ager@chromium.org8bb60582008-12-11 12:02:20 +0000571
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000572 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573}
574
575
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000576bool Compiler::CompileLazy(CompilationInfo* info) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000577 Isolate* isolate = info->isolate();
578
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000579 ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580
581 // The VM is in the COMPILER state until exiting this function.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000582 VMState state(isolate, COMPILER);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000584 PostponeInterruptsScope postpone(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000585
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000586 Handle<SharedFunctionInfo> shared = info->shared_info();
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +0000587 int compiled_size = shared->end_position() - shared->start_position();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000588 isolate->counters()->total_compile_size()->Increment(compiled_size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000589
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000590 // Generate the AST for the lazily compiled function.
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000591 if (ParserApi::Parse(info)) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000592 // Measure how long it takes to do the lazy compilation; only take the
593 // rest of the function into account to avoid overlap with the lazy
594 // parsing statistics.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000595 HistogramTimerScope timer(isolate->counters()->compile_lazy());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000597 // After parsing we know function's strict mode. Remember it.
598 if (info->function()->strict_mode()) {
599 shared->set_strict_mode(true);
600 info->MarkAsStrictMode();
601 }
602
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000603 // Compile the code.
604 if (!MakeCode(info)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000605 if (!isolate->has_pending_exception()) {
606 isolate->StackOverflow();
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000607 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000608 } else {
609 ASSERT(!info->code().is_null());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000610 Handle<Code> code = info->code();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000611 // Set optimizable to false if this is disallowed by the shared
612 // function info, e.g., we might have flushed the code and must
613 // reset this bit when lazy compiling the code again.
614 if (shared->optimization_disabled()) code->set_optimizable(false);
615
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000616 Handle<JSFunction> function = info->closure();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000617 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
kasper.lund212ac232008-07-16 07:07:30 +0000618
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000619 if (info->IsOptimizing()) {
620 function->ReplaceCode(*code);
621 } else {
622 // Update the shared function info with the compiled code and the
623 // scope info. Please note, that the order of the shared function
624 // info initialization is important since set_scope_info might
625 // trigger a GC, causing the ASSERT below to be invalid if the code
626 // was flushed. By settting the code object last we avoid this.
627 Handle<SerializedScopeInfo> scope_info =
628 SerializedScopeInfo::Create(info->scope());
629 shared->set_scope_info(*scope_info);
630 shared->set_code(*code);
631 if (!function.is_null()) {
632 function->ReplaceCode(*code);
633 ASSERT(!function->IsOptimized());
634 }
635
636 // Set the expected number of properties for instances.
637 FunctionLiteral* lit = info->function();
638 int expected = lit->expected_property_count();
639 SetExpectedNofPropertiesFromEstimate(shared, expected);
640
641 // Set the optimization hints after performing lazy compilation, as
642 // these are not set when the function is set up as a lazily
643 // compiled function.
644 shared->SetThisPropertyAssignmentsInfo(
645 lit->has_only_simple_this_property_assignments(),
646 *lit->this_property_assignments());
647
648 // Check the function has compiled code.
649 ASSERT(shared->is_compiled());
650 shared->set_code_age(0);
651
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000652 if (info->AllowOptimize() && !shared->optimization_disabled()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000653 // If we're asked to always optimize, we compile the optimized
654 // version of the function right away - unless the debugger is
655 // active as it makes no sense to compile optimized code then.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000656 if (FLAG_always_opt &&
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000657 !Isolate::Current()->DebuggerHasBreakPoints()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000658 CompilationInfo optimized(function);
659 optimized.SetOptimizing(AstNode::kNoNumber);
660 return CompileLazy(&optimized);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000661 } else if (isolate->compilation_cache()->ShouldOptimizeEagerly(
662 function)) {
663 isolate->runtime_profiler()->OptimizeSoon(*function);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000664 }
665 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000666 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000668 return true;
669 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670 }
671
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000672 ASSERT(info->code().is_null());
673 return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674}
675
676
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000677Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000678 Handle<Script> script) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000679 // Precondition: code has been parsed and scopes have been analyzed.
680 CompilationInfo info(script);
681 info.SetFunction(literal);
682 info.SetScope(literal->scope());
danno@chromium.org40cb8782011-05-25 07:58:50 +0000683 if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000684 if (script->type()->value() == Script::TYPE_NATIVE) info.MarkAsNative();
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000685
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000686 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000687 // Determine if the function can be lazily compiled. This is necessary to
688 // allow some of our builtin JS files to be lazily compiled. These
689 // builtins cannot be handled lazily by the parser, since we have to know
690 // if a function uses the special natives syntax, which is something the
691 // parser records.
ager@chromium.org5c838252010-02-19 08:53:10 +0000692 bool allow_lazy = literal->AllowsLazyCompilation() &&
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000693 !LiveEditFunctionTracker::IsActive(info.isolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000694
ager@chromium.orgb5737492010-07-15 09:29:43 +0000695 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000696
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000697 // Generate code
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000698 if (FLAG_lazy && allow_lazy) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000699 Handle<Code> code = info.isolate()->builtins()->LazyCompile();
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000700 info.SetCode(code);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000701 } else if ((V8::UseCrankshaft() && MakeCrankshaftCode(&info)) ||
702 (!V8::UseCrankshaft() && FullCodeGenerator::MakeCode(&info))) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000703 ASSERT(!info.code().is_null());
ager@chromium.orgb5737492010-07-15 09:29:43 +0000704 scope_info = SerializedScopeInfo::Create(info.scope());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000705 } else {
706 return Handle<SharedFunctionInfo>::null();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000707 }
708
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000709 // Create a shared function info object.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000710 Handle<SharedFunctionInfo> result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000711 FACTORY->NewSharedFunctionInfo(literal->name(),
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000712 literal->materialized_literal_count(),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000713 info.code(),
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000714 scope_info);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000715 SetFunctionInfo(result, literal, false, script);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000716 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000717 result->set_allows_lazy_compilation(allow_lazy);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000718
719 // Set the expected number of properties for instances and return
720 // the resulting function.
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000721 SetExpectedNofPropertiesFromEstimate(result,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000722 literal->expected_property_count());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000723 live_edit_tracker.RecordFunctionInfo(result, literal);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000724 return result;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000725}
726
727
728// Sets the function info on a function.
729// The start_position points to the first '(' character after the function name
730// in the full script source. When counting characters in the script source the
731// the first character is number 0 (not 1).
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000732void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000733 FunctionLiteral* lit,
734 bool is_toplevel,
735 Handle<Script> script) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000736 function_info->set_length(lit->num_parameters());
737 function_info->set_formal_parameter_count(lit->num_parameters());
738 function_info->set_script(*script);
739 function_info->set_function_token_position(lit->function_token_position());
740 function_info->set_start_position(lit->start_position());
741 function_info->set_end_position(lit->end_position());
742 function_info->set_is_expression(lit->is_expression());
743 function_info->set_is_toplevel(is_toplevel);
744 function_info->set_inferred_name(*lit->inferred_name());
745 function_info->SetThisPropertyAssignmentsInfo(
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000746 lit->has_only_simple_this_property_assignments(),
747 *lit->this_property_assignments());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000748 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000749 function_info->set_strict_mode(lit->strict_mode());
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000750}
751
752
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000753void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000754 CompilationInfo* info,
755 Handle<SharedFunctionInfo> shared) {
756 // SharedFunctionInfo is passed separately, because if CompilationInfo
757 // was created using Script object, it will not have it.
758
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000759 // Log the code generation. If source information is available include
760 // script name and line number. Check explicitly whether logging is
761 // enabled as finding the line number is not free.
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000762 if (info->isolate()->logger()->is_logging() ||
763 CpuProfiler::is_profiling(info->isolate())) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000764 Handle<Script> script = info->script();
765 Handle<Code> code = info->code();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000766 if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000767 return;
ager@chromium.org5c838252010-02-19 08:53:10 +0000768 if (script->name()->IsString()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000769 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000770 USE(line_num);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000771 PROFILE(info->isolate(),
772 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000773 *code,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000774 *shared,
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000775 String::cast(script->name()),
776 line_num));
ager@chromium.org5c838252010-02-19 08:53:10 +0000777 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000778 PROFILE(info->isolate(),
779 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000780 *code,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000781 *shared,
782 shared->DebugName()));
ager@chromium.org5c838252010-02-19 08:53:10 +0000783 }
784 }
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000785
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000786 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000787 Handle<Script>(info->script()),
788 Handle<Code>(info->code())));
ager@chromium.org5c838252010-02-19 08:53:10 +0000789}
ager@chromium.org5c838252010-02-19 08:53:10 +0000790
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791} } // namespace v8::internal