blob: e4864e48015df3ef51186b5f814920b6d5364518 [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 Murdochb0fe1622011-05-05 13:52:32 +010038#include "hydrogen.h"
39#include "lithium-allocator.h"
Steve Block6ded16b2010-05-10 14:33:55 +010040#include "liveedit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "oprofile-agent.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)
54 : flags_(0),
55 function_(NULL),
56 scope_(NULL),
57 script_(script),
58 extension_(NULL),
Ben Murdochb0fe1622011-05-05 13:52:32 +010059 pre_parse_data_(NULL),
60 supports_deoptimization_(false),
61 osr_ast_id_(AstNode::kNoNumber) {
62 Initialize(NONOPT);
Ben Murdochf87a2032010-10-22 12:50:53 +010063}
64
65
66CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
67 : flags_(IsLazy::encode(true)),
68 function_(NULL),
69 scope_(NULL),
70 shared_info_(shared_info),
71 script_(Handle<Script>(Script::cast(shared_info->script()))),
72 extension_(NULL),
Ben Murdochb0fe1622011-05-05 13:52:32 +010073 pre_parse_data_(NULL),
74 supports_deoptimization_(false),
75 osr_ast_id_(AstNode::kNoNumber) {
76 Initialize(BASE);
Ben Murdochf87a2032010-10-22 12:50:53 +010077}
78
79
80CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
81 : flags_(IsLazy::encode(true)),
82 function_(NULL),
83 scope_(NULL),
84 closure_(closure),
85 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
86 script_(Handle<Script>(Script::cast(shared_info_->script()))),
87 extension_(NULL),
Ben Murdochb0fe1622011-05-05 13:52:32 +010088 pre_parse_data_(NULL),
89 supports_deoptimization_(false),
90 osr_ast_id_(AstNode::kNoNumber) {
91 Initialize(BASE);
Ben Murdochf87a2032010-10-22 12:50:53 +010092}
93
94
Ben Murdochb0fe1622011-05-05 13:52:32 +010095// Determine whether to use the full compiler for all code. If the flag
96// --always-full-compiler is specified this is the case. For the virtual frame
97// based compiler the full compiler is also used if a debugger is connected, as
98// the code from the full compiler supports mode precise break points. For the
99// crankshaft adaptive compiler debugging the optimized code is not possible at
100// all. However crankshaft support recompilation of functions, so in this case
101// the full compiler need not be be used if a debugger is attached, but only if
102// break points has actually been set.
Leon Clarkef7060e22010-06-03 12:02:55 +0100103static bool AlwaysFullCompiler() {
104#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdochb0fe1622011-05-05 13:52:32 +0100105 if (V8::UseCrankshaft()) {
106 return FLAG_always_full_compiler || Debug::has_break_points();
107 } else {
108 return FLAG_always_full_compiler || Debugger::IsDebuggerActive();
109 }
Leon Clarkef7060e22010-06-03 12:02:55 +0100110#else
111 return FLAG_always_full_compiler;
112#endif
113}
114
Steve Block3ce2e202009-11-05 08:53:23 +0000115
Ben Murdochb0fe1622011-05-05 13:52:32 +0100116static void FinishOptimization(Handle<JSFunction> function, int64_t start) {
117 int opt_count = function->shared()->opt_count();
118 function->shared()->set_opt_count(opt_count + 1);
119 double ms = static_cast<double>(OS::Ticks() - start) / 1000;
120 if (FLAG_trace_opt) {
121 PrintF("[optimizing: ");
122 function->PrintName();
123 PrintF(" / %" V8PRIxPTR, reinterpret_cast<intptr_t>(*function));
124 PrintF(" - took %0.3f ms]\n", ms);
125 }
126 if (FLAG_trace_opt_stats) {
127 static double compilation_time = 0.0;
128 static int compiled_functions = 0;
129 static int code_size = 0;
130
131 compilation_time += ms;
132 compiled_functions++;
133 code_size += function->shared()->SourceSize();
134 PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
135 compiled_functions,
136 code_size,
137 compilation_time);
138 }
139}
140
141
142static void AbortAndDisable(CompilationInfo* info) {
143 // Disable optimization for the shared function info and mark the
144 // code as non-optimizable. The marker on the shared function info
145 // is there because we flush non-optimized code thereby loosing the
146 // non-optimizable information for the code. When the code is
147 // regenerated and set on the shared function info it is marked as
148 // non-optimizable if optimization is disabled for the shared
149 // function info.
150 Handle<SharedFunctionInfo> shared = info->shared_info();
151 shared->set_optimization_disabled(true);
152 Handle<Code> code = Handle<Code>(shared->code());
153 ASSERT(code->kind() == Code::FUNCTION);
154 code->set_optimizable(false);
155 info->SetCode(code);
156 if (FLAG_trace_opt) {
157 PrintF("[disabled optimization for: ");
158 info->closure()->PrintName();
159 PrintF(" / %" V8PRIxPTR "]\n",
160 reinterpret_cast<intptr_t>(*info->closure()));
161 }
162}
163
164
165static bool MakeCrankshaftCode(CompilationInfo* info) {
166 // Test if we can optimize this function when asked to. We can only
167 // do this after the scopes are computed.
168 if (!info->AllowOptimize()) info->DisableOptimization();
169
170 // In case we are not optimizing simply return the code from
171 // the full code generator.
172 if (!info->IsOptimizing()) {
173 return FullCodeGenerator::MakeCode(info);
174 }
175
176 // We should never arrive here if there is not code object on the
177 // shared function object.
178 Handle<Code> code(info->shared_info()->code());
179 ASSERT(code->kind() == Code::FUNCTION);
180
181 // Fall back to using the full code generator if it's not possible
182 // to use the Hydrogen-based optimizing compiler. We already have
183 // generated code for this from the shared function object.
184 if (AlwaysFullCompiler() || !FLAG_use_hydrogen) {
185 info->SetCode(code);
186 return true;
187 }
188
189 // Limit the number of times we re-compile a functions with
190 // the optimizing compiler.
191 const int kMaxOptCount = FLAG_deopt_every_n_times == 0 ? 10 : 1000;
192 if (info->shared_info()->opt_count() > kMaxOptCount) {
193 AbortAndDisable(info);
194 // True indicates the compilation pipeline is still going, not
195 // necessarily that we optimized the code.
196 return true;
197 }
198
199 // Due to an encoding limit on LUnallocated operands in the Lithium
200 // language, we cannot optimize functions with too many formal parameters
201 // or perform on-stack replacement for function with too many
202 // stack-allocated local variables.
203 //
204 // The encoding is as a signed value, with parameters using the negative
205 // indices and locals the non-negative ones.
206 const int limit = LUnallocated::kMaxFixedIndices / 2;
207 Scope* scope = info->scope();
208 if (scope->num_parameters() > limit || scope->num_stack_slots() > limit) {
209 AbortAndDisable(info);
210 // True indicates the compilation pipeline is still going, not
211 // necessarily that we optimized the code.
212 return true;
213 }
214
215 // Take --hydrogen-filter into account.
216 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
217 Handle<String> name = info->function()->debug_name();
218 bool match = filter.is_empty() || name->IsEqualTo(filter);
219 if (!match) {
220 info->SetCode(code);
221 return true;
222 }
223
224 // Recompile the unoptimized version of the code if the current version
225 // doesn't have deoptimization support. Alternatively, we may decide to
226 // run the full code generator to get a baseline for the compile-time
227 // performance of the hydrogen-based compiler.
228 int64_t start = OS::Ticks();
229 bool should_recompile = !info->shared_info()->has_deoptimization_support();
230 if (should_recompile || FLAG_time_hydrogen) {
231 HPhase phase(HPhase::kFullCodeGen);
232 CompilationInfo unoptimized(info->shared_info());
233 // Note that we use the same AST that we will use for generating the
234 // optimized code.
235 unoptimized.SetFunction(info->function());
236 unoptimized.SetScope(info->scope());
237 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
238 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
239 if (should_recompile) {
240 if (!succeeded) return false;
241 Handle<SharedFunctionInfo> shared = info->shared_info();
242 shared->EnableDeoptimizationSupport(*unoptimized.code());
243 // The existing unoptimized code was replaced with the new one.
244 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
245 Handle<String>(shared->DebugName()),
246 shared->start_position(),
247 &unoptimized);
248 }
249 }
250
251 // Check that the unoptimized, shared code is ready for
252 // optimizations. When using the always_opt flag we disregard the
253 // optimizable marker in the code object and optimize anyway. This
254 // is safe as long as the unoptimized code has deoptimization
255 // support.
256 ASSERT(FLAG_always_opt || info->shared_info()->code()->optimizable());
257 ASSERT(info->shared_info()->has_deoptimization_support());
258
259 if (FLAG_trace_hydrogen) {
260 PrintF("-----------------------------------------------------------\n");
261 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
262 HTracer::Instance()->TraceCompilation(info->function());
263 }
264
265 TypeFeedbackOracle oracle(Handle<Code>(info->shared_info()->code()));
266 HGraphBuilder builder(&oracle);
267 HPhase phase(HPhase::kTotal);
268 HGraph* graph = builder.CreateGraph(info);
269 if (graph != NULL && FLAG_build_lithium) {
270 Handle<Code> code = graph->Compile();
271 if (!code.is_null()) {
272 info->SetCode(code);
273 FinishOptimization(info->closure(), start);
274 return true;
275 }
276 }
277
278 // Compilation with the Hydrogen compiler failed. Keep using the
279 // shared code but mark it as unoptimizable.
280 AbortAndDisable(info);
281 // True indicates the compilation pipeline is still going, not necessarily
282 // that we optimized the code.
283 return true;
284}
285
286
Ben Murdochf87a2032010-10-22 12:50:53 +0100287static bool MakeCode(CompilationInfo* info) {
288 // Precondition: code has been parsed. Postcondition: the code field in
289 // the compilation info is set if compilation succeeded.
290 ASSERT(info->function() != NULL);
291
Ben Murdochb0fe1622011-05-05 13:52:32 +0100292 if (Rewriter::Rewrite(info) && Scope::Analyze(info)) {
293 if (V8::UseCrankshaft()) return MakeCrankshaftCode(info);
294
Ben Murdochf87a2032010-10-22 12:50:53 +0100295 // Generate code and return it. Code generator selection is governed by
296 // which backends are enabled and whether the function is considered
297 // run-once code or not.
298 //
299 // --full-compiler enables the dedicated backend for code we expect to
300 // be run once
301 //
302 // The normal choice of backend can be overridden with the flags
303 // --always-full-compiler.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100304 if (Rewriter::Analyze(info)) {
305 Handle<SharedFunctionInfo> shared = info->shared_info();
306 bool is_run_once = (shared.is_null())
307 ? info->scope()->is_global_scope()
308 : (shared->is_toplevel() || shared->try_full_codegen());
309 bool can_use_full =
310 FLAG_full_compiler && !info->function()->contains_loops();
311 if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
312 return FullCodeGenerator::MakeCode(info);
313 } else {
314 return AssignedVariablesAnalyzer::Analyze(info) &&
315 CodeGenerator::MakeCode(info);
316 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100317 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 }
319
Ben Murdochf87a2032010-10-22 12:50:53 +0100320 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000321}
322
323
Steve Block6ded16b2010-05-10 14:33:55 +0100324#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdochf87a2032010-10-22 12:50:53 +0100325bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
326 // Precondition: code has been parsed. Postcondition: the code field in
327 // the compilation info is set if compilation succeeded.
328 bool succeeded = MakeCode(info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100329 if (!info->shared_info().is_null()) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100330 Handle<SerializedScopeInfo> scope_info =
331 SerializedScopeInfo::Create(info->scope());
332 info->shared_info()->set_scope_info(*scope_info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100333 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100334 return succeeded;
Steve Block6ded16b2010-05-10 14:33:55 +0100335}
336#endif
337
338
Ben Murdochf87a2032010-10-22 12:50:53 +0100339static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
341
342 PostponeInterruptsScope postpone;
343
344 ASSERT(!i::Top::global_context().is_null());
Ben Murdochf87a2032010-10-22 12:50:53 +0100345 Handle<Script> script = info->script();
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 script->set_context_data((*i::Top::global_context())->data());
347
Leon Clarke4515c472010-02-03 11:58:03 +0000348#ifdef ENABLE_DEBUGGER_SUPPORT
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800349 if (info->is_eval()) {
350 Script::CompilationType compilation_type = Script::COMPILATION_TYPE_EVAL;
Ben Murdochf87a2032010-10-22 12:50:53 +0100351 script->set_compilation_type(Smi::FromInt(compilation_type));
Steve Blocka7e24c12009-10-30 11:49:00 +0000352 // For eval scripts add information on the function from which eval was
353 // called.
Ben Murdochf87a2032010-10-22 12:50:53 +0100354 if (info->is_eval()) {
Leon Clarke4515c472010-02-03 11:58:03 +0000355 StackTraceFrameIterator it;
356 if (!it.done()) {
357 script->set_eval_from_shared(
358 JSFunction::cast(it.frame()->function())->shared());
359 int offset = static_cast<int>(
360 it.frame()->pc() - it.frame()->code()->instruction_start());
361 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
362 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000363 }
364 }
365
366 // Notify debugger
367 Debugger::OnBeforeCompile(script);
368#endif
369
370 // Only allow non-global compiles for eval.
Ben Murdochf87a2032010-10-22 12:50:53 +0100371 ASSERT(info->is_eval() || info->is_global());
Steve Blocka7e24c12009-10-30 11:49:00 +0000372
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800373 if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000374
Steve Blocka7e24c12009-10-30 11:49:00 +0000375 // Measure how long it takes to do the compilation; only take the
376 // rest of the function into account to avoid overlap with the
377 // parsing statistics.
Ben Murdochf87a2032010-10-22 12:50:53 +0100378 HistogramTimer* rate = info->is_eval()
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 ? &Counters::compile_eval
380 : &Counters::compile;
381 HistogramTimerScope timer(rate);
382
383 // Compile the code.
Ben Murdochf87a2032010-10-22 12:50:53 +0100384 FunctionLiteral* lit = info->function();
385 LiveEditFunctionTracker live_edit_tracker(lit);
386 if (!MakeCode(info)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 Top::StackOverflow();
Steve Block6ded16b2010-05-10 14:33:55 +0100388 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 }
390
Ben Murdochf87a2032010-10-22 12:50:53 +0100391 ASSERT(!info->code().is_null());
Steve Block6ded16b2010-05-10 14:33:55 +0100392 if (script->name()->IsString()) {
393 PROFILE(CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100394 info->is_eval()
395 ? Logger::EVAL_TAG
396 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
397 *info->code(),
398 String::cast(script->name())));
Steve Block6ded16b2010-05-10 14:33:55 +0100399 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
Ben Murdochf87a2032010-10-22 12:50:53 +0100400 info->code()->instruction_start(),
401 info->code()->instruction_size()));
Steve Block6ded16b2010-05-10 14:33:55 +0100402 } else {
403 PROFILE(CodeCreateEvent(
Ben Murdochf87a2032010-10-22 12:50:53 +0100404 info->is_eval()
405 ? Logger::EVAL_TAG
406 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
407 *info->code(),
408 ""));
409 OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
410 info->code()->instruction_start(),
411 info->code()->instruction_size()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000413
414 // Allocate function.
Steve Block6ded16b2010-05-10 14:33:55 +0100415 Handle<SharedFunctionInfo> result =
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100416 Factory::NewSharedFunctionInfo(
417 lit->name(),
418 lit->materialized_literal_count(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100419 info->code(),
420 SerializedScopeInfo::Create(info->scope()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000421
422 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Steve Block6ded16b2010-05-10 14:33:55 +0100423 Compiler::SetFunctionInfo(result, lit, true, script);
Steve Blocka7e24c12009-10-30 11:49:00 +0000424
425 // Hint to the runtime system used when allocating space for initial
426 // property space by setting the expected number of properties for
427 // the instances of the function.
Steve Block6ded16b2010-05-10 14:33:55 +0100428 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
Steve Blocka7e24c12009-10-30 11:49:00 +0000429
430#ifdef ENABLE_DEBUGGER_SUPPORT
431 // Notify debugger
Steve Block6ded16b2010-05-10 14:33:55 +0100432 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
Steve Blocka7e24c12009-10-30 11:49:00 +0000433#endif
434
Steve Block6ded16b2010-05-10 14:33:55 +0100435 live_edit_tracker.RecordFunctionInfo(result, lit);
436
437 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000438}
439
440
Steve Block6ded16b2010-05-10 14:33:55 +0100441Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
442 Handle<Object> script_name,
443 int line_offset,
444 int column_offset,
445 v8::Extension* extension,
446 ScriptDataImpl* input_pre_data,
447 Handle<Object> script_data,
448 NativesFlag natives) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 int source_length = source->length();
450 Counters::total_load_size.Increment(source_length);
451 Counters::total_compile_size.Increment(source_length);
452
453 // The VM is in the COMPILER state until exiting this function.
454 VMState state(COMPILER);
455
456 // Do a lookup in the compilation cache but not for extensions.
Steve Block6ded16b2010-05-10 14:33:55 +0100457 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 if (extension == NULL) {
459 result = CompilationCache::LookupScript(source,
460 script_name,
461 line_offset,
462 column_offset);
463 }
464
465 if (result.is_null()) {
Steve Block59151502010-09-22 15:07:15 +0100466 // No cache entry found. Do pre-parsing, if it makes sense, and compile
467 // the script.
468 // Building preparse data that is only used immediately after is only a
469 // saving if we might skip building the AST for lazily compiled functions.
470 // I.e., preparse data isn't relevant when the lazy flag is off, and
471 // for small sources, odds are that there aren't many functions
472 // that would be compiled lazily anyway, so we skip the preparse step
473 // in that case too.
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 ScriptDataImpl* pre_data = input_pre_data;
Steve Block59151502010-09-22 15:07:15 +0100475 if (pre_data == NULL
Steve Block59151502010-09-22 15:07:15 +0100476 && source_length >= FLAG_min_preparse_length) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100477 if (source->IsExternalTwoByteString()) {
478 ExternalTwoByteStringUC16CharacterStream stream(
479 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
480 pre_data = ParserApi::PartialPreParse(&stream, extension);
481 } else {
482 GenericStringUC16CharacterStream stream(source, 0, source->length());
483 pre_data = ParserApi::PartialPreParse(&stream, extension);
484 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 }
486
487 // Create a script object describing the script to be compiled.
488 Handle<Script> script = Factory::NewScript(source);
Andrei Popescu31002712010-02-23 13:46:05 +0000489 if (natives == NATIVES_CODE) {
490 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
491 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000492 if (!script_name.is_null()) {
493 script->set_name(*script_name);
494 script->set_line_offset(Smi::FromInt(line_offset));
495 script->set_column_offset(Smi::FromInt(column_offset));
496 }
497
Andrei Popescu402d9372010-02-26 13:31:12 +0000498 script->set_data(script_data.is_null() ? Heap::undefined_value()
499 : *script_data);
500
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 // Compile the function and add it to the cache.
Ben Murdochf87a2032010-10-22 12:50:53 +0100502 CompilationInfo info(script);
503 info.MarkAsGlobal();
504 info.SetExtension(extension);
505 info.SetPreParseData(pre_data);
506 result = MakeFunctionInfo(&info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 if (extension == NULL && !result.is_null()) {
508 CompilationCache::PutScript(source, result);
509 }
510
511 // Get rid of the pre-parsing data (if necessary).
512 if (input_pre_data == NULL && pre_data != NULL) {
513 delete pre_data;
514 }
515 }
516
517 if (result.is_null()) Top::ReportPendingMessages();
518 return result;
519}
520
521
Steve Block6ded16b2010-05-10 14:33:55 +0100522Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
523 Handle<Context> context,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800524 bool is_global) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 int source_length = source->length();
526 Counters::total_eval_size.Increment(source_length);
527 Counters::total_compile_size.Increment(source_length);
528
529 // The VM is in the COMPILER state until exiting this function.
530 VMState state(COMPILER);
531
Ben Murdochf87a2032010-10-22 12:50:53 +0100532 // Do a lookup in the compilation cache; if the entry is not there, invoke
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800533 // the compiler and add the result to the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100534 Handle<SharedFunctionInfo> result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800535 result = CompilationCache::LookupEval(source, context, is_global);
Steve Blocka7e24c12009-10-30 11:49:00 +0000536
537 if (result.is_null()) {
538 // Create a script object describing the script to be compiled.
539 Handle<Script> script = Factory::NewScript(source);
Ben Murdochf87a2032010-10-22 12:50:53 +0100540 CompilationInfo info(script);
541 info.MarkAsEval();
542 if (is_global) info.MarkAsGlobal();
Ben Murdochf87a2032010-10-22 12:50:53 +0100543 info.SetCallingContext(context);
544 result = MakeFunctionInfo(&info);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800545 if (!result.is_null()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000546 CompilationCache::PutEval(source, context, is_global, result);
547 }
548 }
549
550 return result;
551}
552
553
Leon Clarke4515c472010-02-03 11:58:03 +0000554bool Compiler::CompileLazy(CompilationInfo* info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
556
557 // The VM is in the COMPILER state until exiting this function.
558 VMState state(COMPILER);
559
560 PostponeInterruptsScope postpone;
561
Leon Clarke4515c472010-02-03 11:58:03 +0000562 Handle<SharedFunctionInfo> shared = info->shared_info();
Ben Murdochf87a2032010-10-22 12:50:53 +0100563 int compiled_size = shared->end_position() - shared->start_position();
564 Counters::total_compile_size.Increment(compiled_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000565
Ben Murdochf87a2032010-10-22 12:50:53 +0100566 // Generate the AST for the lazily compiled function.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800567 if (ParserApi::Parse(info)) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100568 // Measure how long it takes to do the lazy compilation; only take the
569 // rest of the function into account to avoid overlap with the lazy
570 // parsing statistics.
571 HistogramTimerScope timer(&Counters::compile_lazy);
Steve Blocka7e24c12009-10-30 11:49:00 +0000572
Ben Murdochf87a2032010-10-22 12:50:53 +0100573 // Compile the code.
574 if (!MakeCode(info)) {
575 Top::StackOverflow();
576 } else {
577 ASSERT(!info->code().is_null());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100578 Handle<Code> code = info->code();
579 Handle<JSFunction> function = info->closure();
Ben Murdochf87a2032010-10-22 12:50:53 +0100580 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
581 Handle<String>(shared->DebugName()),
582 shared->start_position(),
583 info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000584
Ben Murdochb0fe1622011-05-05 13:52:32 +0100585 if (info->IsOptimizing()) {
586 function->ReplaceCode(*code);
587 } else {
588 // Update the shared function info with the compiled code and the
589 // scope info. Please note, that the order of the shared function
590 // info initialization is important since set_scope_info might
591 // trigger a GC, causing the ASSERT below to be invalid if the code
592 // was flushed. By settting the code object last we avoid this.
593 Handle<SerializedScopeInfo> scope_info =
594 SerializedScopeInfo::Create(info->scope());
595 shared->set_scope_info(*scope_info);
596 shared->set_code(*code);
597 if (!function.is_null()) {
598 function->ReplaceCode(*code);
599 ASSERT(!function->IsOptimized());
600 }
601
602 // Set the expected number of properties for instances.
603 FunctionLiteral* lit = info->function();
604 int expected = lit->expected_property_count();
605 SetExpectedNofPropertiesFromEstimate(shared, expected);
606
607 // Set the optimization hints after performing lazy compilation, as
608 // these are not set when the function is set up as a lazily
609 // compiled function.
610 shared->SetThisPropertyAssignmentsInfo(
611 lit->has_only_simple_this_property_assignments(),
612 *lit->this_property_assignments());
613
614 // Check the function has compiled code.
615 ASSERT(shared->is_compiled());
616 shared->set_code_age(0);
617
618 if (V8::UseCrankshaft() && info->AllowOptimize()) {
619 // If we're asked to always optimize, we compile the optimized
620 // version of the function right away - unless the debugger is
621 // active as it makes no sense to compile optimized code then.
622 if (FLAG_always_opt && !Debug::has_break_points()) {
623 CompilationInfo optimized(function);
624 optimized.SetOptimizing(AstNode::kNoNumber);
625 return CompileLazy(&optimized);
626 } else if (CompilationCache::ShouldOptimizeEagerly(function)) {
627 RuntimeProfiler::OptimizeSoon(*function);
628 }
629 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100630 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000631
Ben Murdochf87a2032010-10-22 12:50:53 +0100632 return true;
633 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000634 }
635
Ben Murdochf87a2032010-10-22 12:50:53 +0100636 ASSERT(info->code().is_null());
637 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000638}
639
640
Steve Block6ded16b2010-05-10 14:33:55 +0100641Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Ben Murdochf87a2032010-10-22 12:50:53 +0100642 Handle<Script> script) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100643 // Precondition: code has been parsed and scopes have been analyzed.
644 CompilationInfo info(script);
645 info.SetFunction(literal);
646 info.SetScope(literal->scope());
647
648 LiveEditFunctionTracker live_edit_tracker(literal);
649 // Determine if the function can be lazily compiled. This is necessary to
650 // allow some of our builtin JS files to be lazily compiled. These
651 // builtins cannot be handled lazily by the parser, since we have to know
652 // if a function uses the special natives syntax, which is something the
653 // parser records.
Andrei Popescu402d9372010-02-26 13:31:12 +0000654 bool allow_lazy = literal->AllowsLazyCompilation() &&
655 !LiveEditFunctionTracker::IsActive();
Steve Blockd0582a62009-12-15 09:54:21 +0000656
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100657 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
658
Steve Blockd0582a62009-12-15 09:54:21 +0000659 // Generate code
Steve Blockd0582a62009-12-15 09:54:21 +0000660 if (FLAG_lazy && allow_lazy) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100661 Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
662 info.SetCode(code);
Steve Blockd0582a62009-12-15 09:54:21 +0000663 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664 if (V8::UseCrankshaft()) {
665 if (!MakeCrankshaftCode(&info)) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100666 return Handle<SharedFunctionInfo>::null();
667 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100668 } else {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100669 // The bodies of function literals have not yet been visited by the
670 // AST optimizer/analyzer.
671 if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null();
672
673 bool is_run_once = literal->try_full_codegen();
674 bool can_use_full = FLAG_full_compiler && !literal->contains_loops();
675
676 if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
677 if (!FullCodeGenerator::MakeCode(&info)) {
678 return Handle<SharedFunctionInfo>::null();
679 }
680 } else {
681 // We fall back to the classic V8 code generator.
682 if (!AssignedVariablesAnalyzer::Analyze(&info) ||
683 !CodeGenerator::MakeCode(&info)) {
684 return Handle<SharedFunctionInfo>::null();
685 }
Ben Murdochf87a2032010-10-22 12:50:53 +0100686 }
Steve Blockd0582a62009-12-15 09:54:21 +0000687 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100688 ASSERT(!info.code().is_null());
Steve Blockd0582a62009-12-15 09:54:21 +0000689
690 // Function compilation complete.
Steve Block6ded16b2010-05-10 14:33:55 +0100691 RecordFunctionCompilation(Logger::FUNCTION_TAG,
Ben Murdochf87a2032010-10-22 12:50:53 +0100692 literal->debug_name(),
Steve Block6ded16b2010-05-10 14:33:55 +0100693 literal->start_position(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100694 &info);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100695 scope_info = SerializedScopeInfo::Create(info.scope());
Steve Blockd0582a62009-12-15 09:54:21 +0000696 }
697
Steve Block6ded16b2010-05-10 14:33:55 +0100698 // Create a shared function info object.
699 Handle<SharedFunctionInfo> result =
700 Factory::NewSharedFunctionInfo(literal->name(),
701 literal->materialized_literal_count(),
Ben Murdochf87a2032010-10-22 12:50:53 +0100702 info.code(),
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100703 scope_info);
Steve Block6ded16b2010-05-10 14:33:55 +0100704 SetFunctionInfo(result, literal, false, script);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100705 result->set_allows_lazy_compilation(allow_lazy);
Steve Blockd0582a62009-12-15 09:54:21 +0000706
707 // Set the expected number of properties for instances and return
708 // the resulting function.
Steve Block6ded16b2010-05-10 14:33:55 +0100709 SetExpectedNofPropertiesFromEstimate(result,
Steve Blockd0582a62009-12-15 09:54:21 +0000710 literal->expected_property_count());
Steve Block6ded16b2010-05-10 14:33:55 +0100711 live_edit_tracker.RecordFunctionInfo(result, literal);
712 return result;
Steve Blockd0582a62009-12-15 09:54:21 +0000713}
714
715
716// Sets the function info on a function.
717// The start_position points to the first '(' character after the function name
718// in the full script source. When counting characters in the script source the
719// the first character is number 0 (not 1).
Steve Block6ded16b2010-05-10 14:33:55 +0100720void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
Steve Blockd0582a62009-12-15 09:54:21 +0000721 FunctionLiteral* lit,
722 bool is_toplevel,
723 Handle<Script> script) {
Steve Block6ded16b2010-05-10 14:33:55 +0100724 function_info->set_length(lit->num_parameters());
725 function_info->set_formal_parameter_count(lit->num_parameters());
726 function_info->set_script(*script);
727 function_info->set_function_token_position(lit->function_token_position());
728 function_info->set_start_position(lit->start_position());
729 function_info->set_end_position(lit->end_position());
730 function_info->set_is_expression(lit->is_expression());
731 function_info->set_is_toplevel(is_toplevel);
732 function_info->set_inferred_name(*lit->inferred_name());
733 function_info->SetThisPropertyAssignmentsInfo(
Steve Blockd0582a62009-12-15 09:54:21 +0000734 lit->has_only_simple_this_property_assignments(),
735 *lit->this_property_assignments());
Steve Block6ded16b2010-05-10 14:33:55 +0100736 function_info->set_try_full_codegen(lit->try_full_codegen());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100737 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
Steve Blockd0582a62009-12-15 09:54:21 +0000738}
739
740
Steve Block6ded16b2010-05-10 14:33:55 +0100741void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
742 Handle<String> name,
Steve Block6ded16b2010-05-10 14:33:55 +0100743 int start_position,
Ben Murdochf87a2032010-10-22 12:50:53 +0100744 CompilationInfo* info) {
745 // Log the code generation. If source information is available include
746 // script name and line number. Check explicitly whether logging is
747 // enabled as finding the line number is not free.
748 if (Logger::is_logging() ||
749 OProfileAgent::is_enabled() ||
750 CpuProfiler::is_profiling()) {
751 Handle<Script> script = info->script();
752 Handle<Code> code = info->code();
Andrei Popescu31002712010-02-23 13:46:05 +0000753 if (script->name()->IsString()) {
754 int line_num = GetScriptLineNumber(script, start_position) + 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100755 USE(line_num);
756 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100757 *code,
758 *name,
759 String::cast(script->name()),
760 line_num));
761 OPROFILE(CreateNativeCodeRegion(*name,
Steve Block6ded16b2010-05-10 14:33:55 +0100762 String::cast(script->name()),
763 line_num,
764 code->instruction_start(),
765 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000766 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100767 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
Ben Murdochf87a2032010-10-22 12:50:53 +0100768 *code,
769 *name));
770 OPROFILE(CreateNativeCodeRegion(*name,
Steve Block6ded16b2010-05-10 14:33:55 +0100771 code->instruction_start(),
772 code->instruction_size()));
Andrei Popescu31002712010-02-23 13:46:05 +0000773 }
774 }
775}
Andrei Popescu31002712010-02-23 13:46:05 +0000776
Steve Blocka7e24c12009-10-30 11:49:00 +0000777} } // namespace v8::internal