blob: 1ec4414ad3eb0e8517e2f9e19de8a2fe7da0a9a4 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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
Ben Murdochf87a2032010-10-22 12:50:53 +010030#include "compiler.h"
31
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "bootstrapper.h"
33#include "codegen-inl.h"
34#include "compilation-cache.h"
Steve Block6ded16b2010-05-10 14:33:55 +010035#include "data-flow.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036#include "debug.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000037#include "full-codegen.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010038#include "gdb-jit.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010039#include "hydrogen.h"
Steve Block1e0659c2011-05-24 12:43:12 +010040#include "lithium.h"
Steve Block6ded16b2010-05-10 14:33:55 +010041#include "liveedit.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010042#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000043#include "rewriter.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010044#include "runtime-profiler.h"
Ben Murdoch3bec4d22010-07-22 14:51:16 +010045#include "scopeinfo.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010046#include "scopes.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010047#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000048
49namespace v8 {
50namespace internal {
51
Ben Murdochf87a2032010-10-22 12:50:53 +010052
53CompilationInfo::CompilationInfo(Handle<Script> script)
Steve Block44f0eee2011-05-26 01:26:41 +010054 : isolate_(script->GetIsolate()),
55 flags_(0),
Ben Murdochf87a2032010-10-22 12:50:53 +010056 function_(NULL),
57 scope_(NULL),
58 script_(script),
59 extension_(NULL),
Ben Murdochb0fe1622011-05-05 13:52:32 +010060 pre_parse_data_(NULL),
61 supports_deoptimization_(false),
62 osr_ast_id_(AstNode::kNoNumber) {
63 Initialize(NONOPT);
Ben Murdochf87a2032010-10-22 12:50:53 +010064}
65
66
67CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
Steve Block44f0eee2011-05-26 01:26:41 +010068 : isolate_(shared_info->GetIsolate()),
69 flags_(IsLazy::encode(true)),
Ben Murdochf87a2032010-10-22 12:50:53 +010070 function_(NULL),
71 scope_(NULL),
72 shared_info_(shared_info),
73 script_(Handle<Script>(Script::cast(shared_info->script()))),
74 extension_(NULL),
Ben Murdochb0fe1622011-05-05 13:52:32 +010075 pre_parse_data_(NULL),
76 supports_deoptimization_(false),
77 osr_ast_id_(AstNode::kNoNumber) {
78 Initialize(BASE);
Ben Murdochf87a2032010-10-22 12:50:53 +010079}
80
81
82CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
Steve Block44f0eee2011-05-26 01:26:41 +010083 : isolate_(closure->GetIsolate()),
84 flags_(IsLazy::encode(true)),
Ben Murdochf87a2032010-10-22 12:50:53 +010085 function_(NULL),
86 scope_(NULL),
87 closure_(closure),
88 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
89 script_(Handle<Script>(Script::cast(shared_info_->script()))),
90 extension_(NULL),
Ben Murdochb0fe1622011-05-05 13:52:32 +010091 pre_parse_data_(NULL),
92 supports_deoptimization_(false),
93 osr_ast_id_(AstNode::kNoNumber) {
94 Initialize(BASE);
Ben Murdochf87a2032010-10-22 12:50:53 +010095}
96
97
Ben Murdochb8e0da22011-05-16 14:20:40 +010098void CompilationInfo::DisableOptimization() {
99 if (FLAG_optimize_closures) {
100 // If we allow closures optimizations and it's an optimizable closure
101 // mark it correspondingly.
102 bool is_closure = closure_.is_null() && !scope_->HasTrivialOuterContext();
103 if (is_closure) {
104 bool is_optimizable_closure =
105 !scope_->outer_scope_calls_eval() && !scope_->inside_with();
106 if (is_optimizable_closure) {
107 SetMode(BASE);
108 return;
109 }
110 }
111 }
112
113 SetMode(NONOPT);
114}
115
116
Ben Murdochb0fe1622011-05-05 13:52:32 +0100117// 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.
Leon Clarkef7060e22010-06-03 12:02:55 +0100125static bool AlwaysFullCompiler() {
126#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100127 Isolate* isolate = Isolate::Current();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100128 if (V8::UseCrankshaft()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100129 return FLAG_always_full_compiler || isolate->debug()->has_break_points();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100130 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100131 return FLAG_always_full_compiler || isolate->debugger()->IsDebuggerActive();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100132 }
Leon Clarkef7060e22010-06-03 12:02:55 +0100133#else
134 return FLAG_always_full_compiler;
135#endif
136}
137
Steve Block3ce2e202009-11-05 08:53:23 +0000138
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139static void FinishOptimization(Handle<JSFunction> function, int64_t start) {
140 int opt_count = function->shared()->opt_count();
141 function->shared()->set_opt_count(opt_count + 1);
142 double ms = static_cast<double>(OS::Ticks() - start) / 1000;
143 if (FLAG_trace_opt) {
144 PrintF("[optimizing: ");
145 function->PrintName();
146 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
147 PrintF(" - took %0.3f ms]\n", ms);
148 }
149 if (FLAG_trace_opt_stats) {
150 static double compilation_time = 0.0;
151 static int compiled_functions = 0;
152 static int code_size = 0;
153
154 compilation_time += ms;
155 compiled_functions++;
156 code_size += function->shared()->SourceSize();
157 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
158 compiled_functions,
159 code_size,
160 compilation_time);
161 }
162}
163
164
165static void AbortAndDisable(CompilationInfo* info) {
166 // Disable optimization for the shared function info and mark the
167 // code as non-optimizable. The marker on the shared function info
168 // is there because we flush non-optimized code thereby loosing the
169 // non-optimizable information for the code. When the code is
170 // regenerated and set on the shared function info it is marked as
171 // non-optimizable if optimization is disabled for the shared
172 // function info.
173 Handle<SharedFunctionInfo> shared = info->shared_info();
174 shared->set_optimization_disabled(true);
175 Handle<Code> code = Handle<Code>(shared->code());
176 ASSERT(code->kind() == Code::FUNCTION);
177 code->set_optimizable(false);
178 info->SetCode(code);
Steve Block44f0eee2011-05-26 01:26:41 +0100179 Isolate* isolate = code->GetIsolate();
180 isolate->compilation_cache()->MarkForLazyOptimizing(info->closure());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100181 if (FLAG_trace_opt) {
182 PrintF("[disabled optimization for: ");
183 info->closure()->PrintName();
184 PrintF(" / %" V8PRIxPTR "]\n",
185 reinterpret_cast<intptr_t>(*info->closure()));
186 }
187}
188
189
190static bool MakeCrankshaftCode(CompilationInfo* info) {
191 // Test if we can optimize this function when asked to. We can only
192 // do this after the scopes are computed.
193 if (!info->AllowOptimize()) info->DisableOptimization();
194
195 // In case we are not optimizing simply return the code from
196 // the full code generator.
197 if (!info->IsOptimizing()) {
198 return FullCodeGenerator::MakeCode(info);
199 }
200
201 // We should never arrive here if there is not code object on the
202 // shared function object.
203 Handle<Code> code(info->shared_info()->code());
204 ASSERT(code->kind() == Code::FUNCTION);
205
Steve Block44f0eee2011-05-26 01:26:41 +0100206 // We should never arrive here if optimization has been disabled on the
207 // shared function info.
208 ASSERT(!info->shared_info()->optimization_disabled());
209
Ben Murdochb0fe1622011-05-05 13:52:32 +0100210 // Fall back to using the full code generator if it's not possible
211 // to use the Hydrogen-based optimizing compiler. We already have
212 // generated code for this from the shared function object.
213 if (AlwaysFullCompiler() || !FLAG_use_hydrogen) {
214 info->SetCode(code);
215 return true;
216 }
217
218 // Limit the number of times we re-compile a functions with
219 // the optimizing compiler.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100220 const int kMaxOptCount =
221 FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100222 if (info->shared_info()->opt_count() > kMaxOptCount) {
223 AbortAndDisable(info);
224 // True indicates the compilation pipeline is still going, not
225 // necessarily that we optimized the code.
226 return true;
227 }
228
229 // Due to an encoding limit on LUnallocated operands in the Lithium
230 // language, we cannot optimize functions with too many formal parameters
231 // or perform on-stack replacement for function with too many
232 // stack-allocated local variables.
233 //
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100234 // The encoding is as a signed value, with parameters and receiver using
235 // the negative indices and locals the non-negative ones.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100236 const int limit = LUnallocated::kMaxFixedIndices / 2;
237 Scope* scope = info->scope();
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100238 if ((scope->num_parameters() + 1) > limit ||
239 scope->num_stack_slots() > limit) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100240 AbortAndDisable(info);
241 // True indicates the compilation pipeline is still going, not
242 // necessarily that we optimized the code.
243 return true;
244 }
245
246 // Take --hydrogen-filter into account.
247 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
248 Handle<String> name = info->function()->debug_name();
249 bool match = filter.is_empty() || name->IsEqualTo(filter);
250 if (!match) {
251 info->SetCode(code);
252 return true;
253 }
254
255 // Recompile the unoptimized version of the code if the current version
256 // doesn't have deoptimization support. Alternatively, we may decide to
257 // run the full code generator to get a baseline for the compile-time
258 // performance of the hydrogen-based compiler.
259 int64_t start = OS::Ticks();
260 bool should_recompile = !info->shared_info()->has_deoptimization_support();
Steve Block44f0eee2011-05-26 01:26:41 +0100261 if (should_recompile || FLAG_hydrogen_stats) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100262 HPhase phase(HPhase::kFullCodeGen);
263 CompilationInfo unoptimized(info->shared_info());
264 // Note that we use the same AST that we will use for generating the
265 // optimized code.
266 unoptimized.SetFunction(info->function());
267 unoptimized.SetScope(info->scope());
268 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
269 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
270 if (should_recompile) {
271 if (!succeeded) return false;
272 Handle<SharedFunctionInfo> shared = info->shared_info();
273 shared->EnableDeoptimizationSupport(*unoptimized.code());
274 // The existing unoptimized code was replaced with the new one.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100275 Compiler::RecordFunctionCompilation(
276 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100277 }
278 }
279
280 // Check that the unoptimized, shared code is ready for
281 // optimizations. When using the always_opt flag we disregard the
282 // optimizable marker in the code object and optimize anyway. This
283 // is safe as long as the unoptimized code has deoptimization
284 // support.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100285 ASSERT(FLAG_always_opt || code->optimizable());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100286 ASSERT(info->shared_info()->has_deoptimization_support());
287
288 if (FLAG_trace_hydrogen) {
289 PrintF("-----------------------------------------------------------\n");
290 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
291 HTracer::Instance()->TraceCompilation(info->function());
292 }
293
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100294 Handle<Context> global_context(info->closure()->context()->global_context());
295 TypeFeedbackOracle oracle(code, global_context);
296 HGraphBuilder builder(info, &oracle);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100297 HPhase phase(HPhase::kTotal);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100298 HGraph* graph = builder.CreateGraph();
Steve Block44f0eee2011-05-26 01:26:41 +0100299 if (info->isolate()->has_pending_exception()) {
Steve Block1e0659c2011-05-24 12:43:12 +0100300 info->SetCode(Handle<Code>::null());
301 return false;
302 }
303
Ben Murdochb0fe1622011-05-05 13:52:32 +0100304 if (graph != NULL && FLAG_build_lithium) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100305 Handle<Code> optimized_code = graph->Compile(info);
306 if (!optimized_code.is_null()) {
307 info->SetCode(optimized_code);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100308 FinishOptimization(info->closure(), start);
309 return true;
310 }
311 }
312
313 // Compilation with the Hydrogen compiler failed. Keep using the
314 // shared code but mark it as unoptimizable.
315 AbortAndDisable(info);
316 // True indicates the compilation pipeline is still going, not necessarily
317 // that we optimized the code.
318 return true;
319}
320
321
Ben Murdochf87a2032010-10-22 12:50:53 +0100322static bool MakeCode(CompilationInfo* info) {
323 // Precondition: code has been parsed. Postcondition: the code field in
324 // the compilation info is set if compilation succeeded.
325 ASSERT(info->function() != NULL);
326
Ben Murdochb0fe1622011-05-05 13:52:32 +0100327 if (Rewriter::Rewrite(info) && Scope::Analyze(info)) {
328 if (V8::UseCrankshaft()) return MakeCrankshaftCode(info);
329
Ben Murdochf87a2032010-10-22 12:50:53 +0100330 // Generate code and return it. Code generator selection is governed by
331 // which backends are enabled and whether the function is considered
332 // run-once code or not.
333 //
334 // --full-compiler enables the dedicated backend for code we expect to
335 // be run once
336 //
337 // The normal choice of backend can be overridden with the flags
338 // --always-full-compiler.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100339 if (Rewriter::Analyze(info)) {
340 Handle<SharedFunctionInfo> shared = info->shared_info();
341 bool is_run_once = (shared.is_null())
342 ? info->scope()->is_global_scope()
343 : (shared->is_toplevel() || shared->try_full_codegen());
344 bool can_use_full =
345 FLAG_full_compiler && !info->function()->contains_loops();
346 if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
347 return FullCodeGenerator::MakeCode(info);
348 } else {
349 return AssignedVariablesAnalyzer::Analyze(info) &&
350 CodeGenerator::MakeCode(info);
351 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100352 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 }
354
Ben Murdochf87a2032010-10-22 12:50:53 +0100355 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000356}
357
358
Steve Block6ded16b2010-05-10 14:33:55 +0100359#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdochf87a2032010-10-22 12:50:53 +0100360bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
361 // Precondition: code has been parsed. Postcondition: the code field in
362 // the compilation info is set if compilation succeeded.
363 bool succeeded = MakeCode(info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100364 if (!info->shared_info().is_null()) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100365 Handle<SerializedScopeInfo> scope_info =
366 SerializedScopeInfo::Create(info->scope());
367 info->shared_info()->set_scope_info(*scope_info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100368 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100369 return succeeded;
Steve Block6ded16b2010-05-10 14:33:55 +0100370}
371#endif
372
373
Ben Murdochf87a2032010-10-22 12:50:53 +0100374static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000375 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
376
Steve Block44f0eee2011-05-26 01:26:41 +0100377 Isolate* isolate = info->isolate();
378 PostponeInterruptsScope postpone(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000379
Steve Block44f0eee2011-05-26 01:26:41 +0100380 ASSERT(!isolate->global_context().is_null());
Ben Murdochf87a2032010-10-22 12:50:53 +0100381 Handle<Script> script = info->script();
Steve Block44f0eee2011-05-26 01:26:41 +0100382 script->set_context_data((*isolate->global_context())->data());
Steve Blocka7e24c12009-10-30 11:49:00 +0000383
Leon Clarke4515c472010-02-03 11:58:03 +0000384#ifdef ENABLE_DEBUGGER_SUPPORT
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800385 if (info->is_eval()) {
386 Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL;
Ben Murdochf87a2032010-10-22 12:50:53 +0100387 script->set_compilation_type(Smi::FromInt(compilation_type));
Steve Blocka7e24c12009-10-30 11:49:00 +0000388 // For eval scripts add information on the function from which eval was
389 // called.
Ben Murdochf87a2032010-10-22 12:50:53 +0100390 if (info->is_eval()) {
Leon Clarke4515c472010-02-03 11:58:03 +0000391 StackTraceFrameIterator it;
392 if (!it.done()) {
393 script->set_eval_from_shared(
394 JSFunction::cast(it.frame()->function())->shared());
Steve Block44f0eee2011-05-26 01:26:41 +0100395 Code* code = it.frame()->LookupCode(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +0000396 int offset = static_cast<int>(
Steve Block44f0eee2011-05-26 01:26:41 +0100397 it.frame()->pc() - code->instruction_start());
Leon Clarke4515c472010-02-03 11:58:03 +0000398 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
399 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 }
401 }
402
403 // Notify debugger
Steve Block44f0eee2011-05-26 01:26:41 +0100404 isolate->debugger()->OnBeforeCompile(script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000405#endif
406
407 // Only allow non-global compiles for eval.
Ben Murdochf87a2032010-10-22 12:50:53 +0100408 ASSERT(info->is_eval() || info->is_global());
Steve Blocka7e24c12009-10-30 11:49:00 +0000409
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800410 if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000411
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 // Measure how long it takes to do the compilation; only take the
413 // rest of the function into account to avoid overlap with the
414 // parsing statistics.
Ben Murdochf87a2032010-10-22 12:50:53 +0100415 HistogramTimer* rate = info->is_eval()
Steve Block44f0eee2011-05-26 01:26:41 +0100416 ? info->isolate()->counters()->compile_eval()
417 : info->isolate()->counters()->compile();
Steve Blocka7e24c12009-10-30 11:49:00 +0000418 HistogramTimerScope timer(rate);
419
420 // Compile the code.
Ben Murdochf87a2032010-10-22 12:50:53 +0100421 FunctionLiteral* lit = info->function();
Steve Block44f0eee2011-05-26 01:26:41 +0100422 LiveEditFunctionTracker live_edit_tracker(isolate, lit);
Ben Murdochf87a2032010-10-22 12:50:53 +0100423 if (!MakeCode(info)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100424 isolate->StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100425 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 }
427
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100428 // Allocate function.
Ben Murdochf87a2032010-10-22 12:50:53 +0100429 ASSERT(!info->code().is_null());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100430 Handle<SharedFunctionInfo> result =
Steve Block44f0eee2011-05-26 01:26:41 +0100431 isolate->factory()->NewSharedFunctionInfo(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100432 lit->name(),
433 lit->materialized_literal_count(),
434 info->code(),
435 SerializedScopeInfo::Create(info->scope()));
436
437 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
438 Compiler::SetFunctionInfo(result, lit, true, script);
439
Steve Block6ded16b2010-05-10 14:33:55 +0100440 if (script->name()->IsString()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100441 PROFILE(isolate, CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100442 info->is_eval()
443 ? Logger::EVAL_TAG
444 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
445 *info->code(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100446 *result,
Ben Murdochf87a2032010-10-22 12:50:53 +0100447 String::cast(script->name())));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100448 GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
449 script,
450 info->code()));
Steve Block6ded16b2010-05-10 14:33:55 +0100451 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100452 PROFILE(isolate, CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100453 info->is_eval()
454 ? Logger::EVAL_TAG
455 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
456 *info->code(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100457 *result,
Steve Block44f0eee2011-05-26 01:26:41 +0100458 isolate->heap()->empty_string()));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100459 GDBJIT(AddCode(Handle<String>(), script, info->code()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000460 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000461
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 // Hint to the runtime system used when allocating space for initial
463 // property space by setting the expected number of properties for
464 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100465 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000466
467#ifdef ENABLE_DEBUGGER_SUPPORT
468 // Notify debugger
Steve Block44f0eee2011-05-26 01:26:41 +0100469 isolate->debugger()->OnAfterCompile(
470 script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000471#endif
472
Steve Block6ded16b2010-05-10 14:33:55 +0100473 live_edit_tracker.RecordFunctionInfo(result, lit);
474
475 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000476}
477
478
Steve Block6ded16b2010-05-10 14:33:55 +0100479Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
480 Handle<Object> script_name,
481 int line_offset,
482 int column_offset,
483 v8::Extension* extension,
484 ScriptDataImpl* input_pre_data,
485 Handle<Object> script_data,
486 NativesFlag natives) {
Steve Block44f0eee2011-05-26 01:26:41 +0100487 Isolate* isolate = source->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 int source_length = source->length();
Steve Block44f0eee2011-05-26 01:26:41 +0100489 isolate->counters()->total_load_size()->Increment(source_length);
490 isolate->counters()->total_compile_size()->Increment(source_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000491
492 // The VM is in the COMPILER state until exiting this function.
Steve Block44f0eee2011-05-26 01:26:41 +0100493 VMState state(isolate, COMPILER);
494
495 CompilationCache* compilation_cache = isolate->compilation_cache();
Steve Blocka7e24c12009-10-30 11:49:00 +0000496
497 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100498 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000499 if (extension == NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100500 result = compilation_cache->LookupScript(source,
501 script_name,
502 line_offset,
503 column_offset);
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 }
505
506 if (result.is_null()) {
Steve Block59151502010-09-22 15:07:15 +0100507 // No cache entry found. Do pre-parsing, if it makes sense, and compile
508 // the script.
509 // Building preparse data that is only used immediately after is only a
510 // saving if we might skip building the AST for lazily compiled functions.
511 // I.e., preparse data isn't relevant when the lazy flag is off, and
512 // for small sources, odds are that there aren't many functions
513 // that would be compiled lazily anyway, so we skip the preparse step
514 // in that case too.
Steve Blocka7e24c12009-10-30 11:49:00 +0000515 ScriptDataImpl* pre_data = input_pre_data;
Steve Block59151502010-09-22 15:07:15 +0100516 if (pre_data == NULL
Steve Block59151502010-09-22 15:07:15 +0100517 && source_length >= FLAG_min_preparse_length) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100518 if (source->IsExternalTwoByteString()) {
519 ExternalTwoByteStringUC16CharacterStream stream(
520 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
521 pre_data = ParserApi::PartialPreParse(&stream, extension);
522 } else {
523 GenericStringUC16CharacterStream stream(source, 0, source->length());
524 pre_data = ParserApi::PartialPreParse(&stream, extension);
525 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000526 }
527
528 // Create a script object describing the script to be compiled.
Steve Block44f0eee2011-05-26 01:26:41 +0100529 Handle<Script> script = FACTORY->NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000530 if (natives == NATIVES_CODE) {
531 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
532 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 if (!script_name.is_null()) {
534 script->set_name(*script_name);
535 script->set_line_offset(Smi::FromInt(line_offset));
536 script->set_column_offset(Smi::FromInt(column_offset));
537 }
538
Steve Block44f0eee2011-05-26 01:26:41 +0100539 script->set_data(script_data.is_null() ? HEAP->undefined_value()
Andrei Popescu402d9372010-02-26 13:31:12 +0000540 : *script_data);
541
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 // Compile the function and add it to the cache.
Ben Murdochf87a2032010-10-22 12:50:53 +0100543 CompilationInfo info(script);
544 info.MarkAsGlobal();
545 info.SetExtension(extension);
546 info.SetPreParseData(pre_data);
Steve Block44f0eee2011-05-26 01:26:41 +0100547 if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax();
Ben Murdochf87a2032010-10-22 12:50:53 +0100548 result = MakeFunctionInfo(&info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000549 if (extension == NULL && !result.is_null()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100550 compilation_cache->PutScript(source, result);
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 }
552
553 // Get rid of the pre-parsing data (if necessary).
554 if (input_pre_data == NULL && pre_data != NULL) {
555 delete pre_data;
556 }
557 }
558
Steve Block44f0eee2011-05-26 01:26:41 +0100559 if (result.is_null()) isolate->ReportPendingMessages();
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 return result;
561}
562
563
Steve Block6ded16b2010-05-10 14:33:55 +0100564Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
565 Handle<Context> context,
Steve Block1e0659c2011-05-24 12:43:12 +0100566 bool is_global,
567 StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100568 Isolate* isolate = source->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +0000569 int source_length = source->length();
Steve Block44f0eee2011-05-26 01:26:41 +0100570 isolate->counters()->total_eval_size()->Increment(source_length);
571 isolate->counters()->total_compile_size()->Increment(source_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000572
573 // The VM is in the COMPILER state until exiting this function.
Steve Block44f0eee2011-05-26 01:26:41 +0100574 VMState state(isolate, COMPILER);
Steve Blocka7e24c12009-10-30 11:49:00 +0000575
Ben Murdochf87a2032010-10-22 12:50:53 +0100576 // Do a lookup in the compilation cache; if the entry is not there, invoke
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800577 // the compiler and add the result to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100578 Handle<SharedFunctionInfo> result;
Steve Block44f0eee2011-05-26 01:26:41 +0100579 CompilationCache* compilation_cache = isolate->compilation_cache();
580 result = compilation_cache->LookupEval(source,
581 context,
582 is_global,
583 strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000584
585 if (result.is_null()) {
586 // Create a script object describing the script to be compiled.
Steve Block44f0eee2011-05-26 01:26:41 +0100587 Handle<Script> script = isolate->factory()->NewScript(source);
Ben Murdochf87a2032010-10-22 12:50:53 +0100588 CompilationInfo info(script);
589 info.MarkAsEval();
590 if (is_global) info.MarkAsGlobal();
Steve Block1e0659c2011-05-24 12:43:12 +0100591 if (strict_mode == kStrictMode) info.MarkAsStrict();
Ben Murdochf87a2032010-10-22 12:50:53 +0100592 info.SetCallingContext(context);
593 result = MakeFunctionInfo(&info);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800594 if (!result.is_null()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100595 CompilationCache* compilation_cache = isolate->compilation_cache();
Steve Block1e0659c2011-05-24 12:43:12 +0100596 // If caller is strict mode, the result must be strict as well,
597 // but not the other way around. Consider:
598 // eval("'use strict'; ...");
599 ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
Steve Block44f0eee2011-05-26 01:26:41 +0100600 compilation_cache->PutEval(source, context, is_global, result);
Steve Blocka7e24c12009-10-30 11:49:00 +0000601 }
602 }
603
604 return result;
605}
606
607
Leon Clarke4515c472010-02-03 11:58:03 +0000608bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000609 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
610
611 // The VM is in the COMPILER state until exiting this function.
Steve Block44f0eee2011-05-26 01:26:41 +0100612 VMState state(info->isolate(), COMPILER);
Steve Blocka7e24c12009-10-30 11:49:00 +0000613
Steve Block44f0eee2011-05-26 01:26:41 +0100614 Isolate* isolate = info->isolate();
615 PostponeInterruptsScope postpone(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000616
Leon Clarke4515c472010-02-03 11:58:03 +0000617 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdochf87a2032010-10-22 12:50:53 +0100618 int compiled_size = shared->end_position() - shared->start_position();
Steve Block44f0eee2011-05-26 01:26:41 +0100619 isolate->counters()->total_compile_size()->Increment(compiled_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000620
Ben Murdochf87a2032010-10-22 12:50:53 +0100621 // Generate the AST for the lazily compiled function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800622 if (ParserApi::Parse(info)) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100623 // Measure how long it takes to do the lazy compilation; only take the
624 // rest of the function into account to avoid overlap with the lazy
625 // parsing statistics.
Steve Block44f0eee2011-05-26 01:26:41 +0100626 HistogramTimerScope timer(isolate->counters()->compile_lazy());
Steve Blocka7e24c12009-10-30 11:49:00 +0000627
Ben Murdochf87a2032010-10-22 12:50:53 +0100628 // Compile the code.
629 if (!MakeCode(info)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100630 if (!isolate->has_pending_exception()) {
631 isolate->StackOverflow();
Steve Block1e0659c2011-05-24 12:43:12 +0100632 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100633 } else {
634 ASSERT(!info->code().is_null());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100635 Handle<Code> code = info->code();
Steve Block44f0eee2011-05-26 01:26:41 +0100636 // Set optimizable to false if this is disallowed by the shared
637 // function info, e.g., we might have flushed the code and must
638 // reset this bit when lazy compiling the code again.
639 if (shared->optimization_disabled()) code->set_optimizable(false);
640
Ben Murdochb0fe1622011-05-05 13:52:32 +0100641 Handle<JSFunction> function = info->closure();
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100642 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000643
Ben Murdochb0fe1622011-05-05 13:52:32 +0100644 if (info->IsOptimizing()) {
645 function->ReplaceCode(*code);
646 } else {
647 // Update the shared function info with the compiled code and the
648 // scope info. Please note, that the order of the shared function
649 // info initialization is important since set_scope_info might
650 // trigger a GC, causing the ASSERT below to be invalid if the code
651 // was flushed. By settting the code object last we avoid this.
652 Handle<SerializedScopeInfo> scope_info =
653 SerializedScopeInfo::Create(info->scope());
654 shared->set_scope_info(*scope_info);
655 shared->set_code(*code);
656 if (!function.is_null()) {
657 function->ReplaceCode(*code);
658 ASSERT(!function->IsOptimized());
659 }
660
661 // Set the expected number of properties for instances.
662 FunctionLiteral* lit = info->function();
663 int expected = lit->expected_property_count();
664 SetExpectedNofPropertiesFromEstimate(shared, expected);
665
666 // Set the optimization hints after performing lazy compilation, as
667 // these are not set when the function is set up as a lazily
668 // compiled function.
669 shared->SetThisPropertyAssignmentsInfo(
670 lit->has_only_simple_this_property_assignments(),
671 *lit->this_property_assignments());
672
673 // Check the function has compiled code.
674 ASSERT(shared->is_compiled());
675 shared->set_code_age(0);
676
Steve Block44f0eee2011-05-26 01:26:41 +0100677 if (info->AllowOptimize() && !shared->optimization_disabled()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100678 // If we're asked to always optimize, we compile the optimized
679 // version of the function right away - unless the debugger is
680 // active as it makes no sense to compile optimized code then.
Steve Block44f0eee2011-05-26 01:26:41 +0100681 if (FLAG_always_opt &&
682 !Isolate::Current()->debug()->has_break_points()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100683 CompilationInfo optimized(function);
684 optimized.SetOptimizing(AstNode::kNoNumber);
685 return CompileLazy(&optimized);
Steve Block44f0eee2011-05-26 01:26:41 +0100686 } else if (isolate->compilation_cache()->ShouldOptimizeEagerly(
687 function)) {
688 isolate->runtime_profiler()->OptimizeSoon(*function);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100689 }
690 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100691 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000692
Ben Murdochf87a2032010-10-22 12:50:53 +0100693 return true;
694 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000695 }
696
Ben Murdochf87a2032010-10-22 12:50:53 +0100697 ASSERT(info->code().is_null());
698 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000699}
700
701
Steve Block6ded16b2010-05-10 14:33:55 +0100702Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Ben Murdochf87a2032010-10-22 12:50:53 +0100703 Handle<Script> script) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100704 // Precondition: code has been parsed and scopes have been analyzed.
705 CompilationInfo info(script);
706 info.SetFunction(literal);
707 info.SetScope(literal->scope());
708
Steve Block44f0eee2011-05-26 01:26:41 +0100709 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
Ben Murdochf87a2032010-10-22 12:50:53 +0100710 // Determine if the function can be lazily compiled. This is necessary to
711 // allow some of our builtin JS files to be lazily compiled. These
712 // builtins cannot be handled lazily by the parser, since we have to know
713 // if a function uses the special natives syntax, which is something the
714 // parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000715 bool allow_lazy = literal->AllowsLazyCompilation() &&
Steve Block44f0eee2011-05-26 01:26:41 +0100716 !LiveEditFunctionTracker::IsActive(info.isolate());
Steve Blockd0582a62009-12-15 09:54:21 +0000717
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100718 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
719
Steve Blockd0582a62009-12-15 09:54:21 +0000720 // Generate code
Steve Blockd0582a62009-12-15 09:54:21 +0000721 if (FLAG_lazy && allow_lazy) {
Steve Block44f0eee2011-05-26 01:26:41 +0100722 Handle<Code> code = info.isolate()->builtins()->LazyCompile();
Ben Murdochf87a2032010-10-22 12:50:53 +0100723 info.SetCode(code);
Steve Blockd0582a62009-12-15 09:54:21 +0000724 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100725 if (V8::UseCrankshaft()) {
726 if (!MakeCrankshaftCode(&info)) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100727 return Handle<SharedFunctionInfo>::null();
728 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100729 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100730 // The bodies of function literals have not yet been visited by the
731 // AST optimizer/analyzer.
732 if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null();
733
734 bool is_run_once = literal->try_full_codegen();
735 bool can_use_full = FLAG_full_compiler && !literal->contains_loops();
736
737 if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
738 if (!FullCodeGenerator::MakeCode(&info)) {
739 return Handle<SharedFunctionInfo>::null();
740 }
741 } else {
742 // We fall back to the classic V8 code generator.
743 if (!AssignedVariablesAnalyzer::Analyze(&info) ||
744 !CodeGenerator::MakeCode(&info)) {
745 return Handle<SharedFunctionInfo>::null();
746 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100747 }
Steve Blockd0582a62009-12-15 09:54:21 +0000748 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100749 ASSERT(!info.code().is_null());
Steve Blockd0582a62009-12-15 09:54:21 +0000750
751 // Function compilation complete.
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100752 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000753 }
754
Steve Block6ded16b2010-05-10 14:33:55 +0100755 // Create a shared function info object.
756 Handle<SharedFunctionInfo> result =
Steve Block44f0eee2011-05-26 01:26:41 +0100757 FACTORY->NewSharedFunctionInfo(literal->name(),
Steve Block6ded16b2010-05-10 14:33:55 +0100758 literal->materialized_literal_count(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100759 info.code(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100760 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100761 SetFunctionInfo(result, literal, false, script);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100762 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100763 result->set_allows_lazy_compilation(allow_lazy);
Steve Blockd0582a62009-12-15 09:54:21 +0000764
765 // Set the expected number of properties for instances and return
766 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100767 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000768 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100769 live_edit_tracker.RecordFunctionInfo(result, literal);
770 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000771}
772
773
774// Sets the function info on a function.
775// The start_position points to the first '(' character after the function name
776// in the full script source. When counting characters in the script source the
777// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100778void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000779 FunctionLiteral* lit,
780 bool is_toplevel,
781 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100782 function_info->set_length(lit->num_parameters());
783 function_info->set_formal_parameter_count(lit->num_parameters());
784 function_info->set_script(*script);
785 function_info->set_function_token_position(lit->function_token_position());
786 function_info->set_start_position(lit->start_position());
787 function_info->set_end_position(lit->end_position());
788 function_info->set_is_expression(lit->is_expression());
789 function_info->set_is_toplevel(is_toplevel);
790 function_info->set_inferred_name(*lit->inferred_name());
791 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000792 lit->has_only_simple_this_property_assignments(),
793 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100794 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100795 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Block1e0659c2011-05-24 12:43:12 +0100796 function_info->set_strict_mode(lit->strict_mode());
Steve Blockd0582a62009-12-15 09:54:21 +0000797}
798
799
Steve Block6ded16b2010-05-10 14:33:55 +0100800void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100801 CompilationInfo* info,
802 Handle<SharedFunctionInfo> shared) {
803 // SharedFunctionInfo is passed separately, because if CompilationInfo
804 // was created using Script object, it will not have it.
805
Ben Murdochf87a2032010-10-22 12:50:53 +0100806 // Log the code generation. If source information is available include
807 // script name and line number. Check explicitly whether logging is
808 // enabled as finding the line number is not free.
Steve Block44f0eee2011-05-26 01:26:41 +0100809 if (info->isolate()->logger()->is_logging() || CpuProfiler::is_profiling()) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100810 Handle<Script> script = info->script();
811 Handle<Code> code = info->code();
Steve Block44f0eee2011-05-26 01:26:41 +0100812 if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
813 return;
Andrei Popescu31002712010-02-23 13:46:05 +0000814 if (script->name()->IsString()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100815 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100816 USE(line_num);
Steve Block44f0eee2011-05-26 01:26:41 +0100817 PROFILE(info->isolate(),
818 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100819 *code,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100820 *shared,
Ben Murdochf87a2032010-10-22 12:50:53 +0100821 String::cast(script->name()),
822 line_num));
Andrei Popescu31002712010-02-23 13:46:05 +0000823 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100824 PROFILE(info->isolate(),
825 CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100826 *code,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100827 *shared,
828 shared->DebugName()));
Andrei Popescu31002712010-02-23 13:46:05 +0000829 }
830 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100831
832 GDBJIT(AddCode(name,
833 Handle<Script>(info->script()),
834 Handle<Code>(info->code())));
Andrei Popescu31002712010-02-23 13:46:05 +0000835}
Andrei Popescu31002712010-02-23 13:46:05 +0000836
Steve Blocka7e24c12009-10-30 11:49:00 +0000837} } // namespace v8::internal