Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: src/compiler.cc

Issue 3586006: Begin a more aggressive refactoring of the Compiler interface. (Closed)
Patch Set: Always return false on a parse failure. Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler.h ('k') | src/handles.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 27 matching lines...) Expand all
38 #include "liveedit.h" 38 #include "liveedit.h"
39 #include "oprofile-agent.h" 39 #include "oprofile-agent.h"
40 #include "parser.h" 40 #include "parser.h"
41 #include "rewriter.h" 41 #include "rewriter.h"
42 #include "scopeinfo.h" 42 #include "scopeinfo.h"
43 #include "scopes.h" 43 #include "scopes.h"
44 44
45 namespace v8 { 45 namespace v8 {
46 namespace internal { 46 namespace internal {
47 47
48
49 CompilationInfo::CompilationInfo(Handle<Script> script)
50 : flags_(0),
51 function_(NULL),
52 scope_(NULL),
53 script_(script),
54 extension_(NULL),
55 pre_parse_data_(NULL) {
56 }
57
58
59 CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
60 : flags_(IsLazy::encode(true)),
61 function_(NULL),
62 scope_(NULL),
63 shared_info_(shared_info),
64 script_(Handle<Script>(Script::cast(shared_info->script()))),
65 extension_(NULL),
66 pre_parse_data_(NULL) {
67 }
68
69
70 CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
71 : flags_(IsLazy::encode(true)),
72 function_(NULL),
73 scope_(NULL),
74 closure_(closure),
75 shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
76 script_(Handle<Script>(Script::cast(shared_info_->script()))),
77 extension_(NULL),
78 pre_parse_data_(NULL) {
79 }
80
81
48 // For normal operation the syntax checker is used to determine whether to 82 // For normal operation the syntax checker is used to determine whether to
49 // use the full compiler for top level code or not. However if the flag 83 // use the full compiler for top level code or not. However if the flag
50 // --always-full-compiler is specified or debugging is active the full 84 // --always-full-compiler is specified or debugging is active the full
51 // compiler will be used for all code. 85 // compiler will be used for all code.
52 static bool AlwaysFullCompiler() { 86 static bool AlwaysFullCompiler() {
53 #ifdef ENABLE_DEBUGGER_SUPPORT 87 #ifdef ENABLE_DEBUGGER_SUPPORT
54 return FLAG_always_full_compiler || Debugger::IsDebuggerActive(); 88 return FLAG_always_full_compiler || Debugger::IsDebuggerActive();
55 #else 89 #else
56 return FLAG_always_full_compiler; 90 return FLAG_always_full_compiler;
57 #endif 91 #endif
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 if (!info->shared_info().is_null()) { 158 if (!info->shared_info().is_null()) {
125 Handle<SerializedScopeInfo> scope_info = 159 Handle<SerializedScopeInfo> scope_info =
126 SerializedScopeInfo::Create(info->scope()); 160 SerializedScopeInfo::Create(info->scope());
127 info->shared_info()->set_scope_info(*scope_info); 161 info->shared_info()->set_scope_info(*scope_info);
128 } 162 }
129 return code; 163 return code;
130 } 164 }
131 #endif 165 #endif
132 166
133 167
134 static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global, 168 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info,
135 bool is_eval, 169 Handle<Context> context) {
136 Compiler::ValidationState validate,
137 Handle<Script> script,
138 Handle<Context> context,
139 v8::Extension* extension,
140 ScriptDataImpl* pre_data) {
141 CompilationZoneScope zone_scope(DELETE_ON_EXIT); 170 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
142 171
143 PostponeInterruptsScope postpone; 172 PostponeInterruptsScope postpone;
144 173
145 ASSERT(!i::Top::global_context().is_null()); 174 ASSERT(!i::Top::global_context().is_null());
175 Handle<Script> script = info->script();
146 script->set_context_data((*i::Top::global_context())->data()); 176 script->set_context_data((*i::Top::global_context())->data());
147 177
148 bool is_json = (validate == Compiler::VALIDATE_JSON);
149 #ifdef ENABLE_DEBUGGER_SUPPORT 178 #ifdef ENABLE_DEBUGGER_SUPPORT
150 if (is_eval || is_json) { 179 if (info->is_eval() || info->is_json()) {
151 Script::CompilationType compilation_type = is_json 180 Script::CompilationType compilation_type = info->is_json()
152 ? Script::COMPILATION_TYPE_JSON 181 ? Script::COMPILATION_TYPE_JSON
153 : Script::COMPILATION_TYPE_EVAL; 182 : Script::COMPILATION_TYPE_EVAL;
154 script->set_compilation_type(Smi::FromInt(compilation_type)); 183 script->set_compilation_type(Smi::FromInt(compilation_type));
155 // For eval scripts add information on the function from which eval was 184 // For eval scripts add information on the function from which eval was
156 // called. 185 // called.
157 if (is_eval) { 186 if (info->is_eval()) {
158 StackTraceFrameIterator it; 187 StackTraceFrameIterator it;
159 if (!it.done()) { 188 if (!it.done()) {
160 script->set_eval_from_shared( 189 script->set_eval_from_shared(
161 JSFunction::cast(it.frame()->function())->shared()); 190 JSFunction::cast(it.frame()->function())->shared());
162 int offset = static_cast<int>( 191 int offset = static_cast<int>(
163 it.frame()->pc() - it.frame()->code()->instruction_start()); 192 it.frame()->pc() - it.frame()->code()->instruction_start());
164 script->set_eval_from_instructions_offset(Smi::FromInt(offset)); 193 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
165 } 194 }
166 } 195 }
167 } 196 }
168 197
169 // Notify debugger 198 // Notify debugger
170 Debugger::OnBeforeCompile(script); 199 Debugger::OnBeforeCompile(script);
171 #endif 200 #endif
172 201
173 // Only allow non-global compiles for eval. 202 // Only allow non-global compiles for eval.
174 ASSERT(is_eval || is_global); 203 ASSERT(info->is_eval() || info->is_global());
175 204
176 // Build AST. 205 if (!Parser::Parse(info)) return Handle<SharedFunctionInfo>::null();
177 EagerCompilationInfo info(script, is_eval);
178 FunctionLiteral* lit =
179 Parser::MakeAST(is_global, script, extension, pre_data, is_json);
180
181 // Check for parse errors.
182 if (lit == NULL) {
183 ASSERT(Top::has_pending_exception());
184 return Handle<SharedFunctionInfo>::null();
185 }
186 info.set_function(lit);
187 206
188 // Measure how long it takes to do the compilation; only take the 207 // Measure how long it takes to do the compilation; only take the
189 // rest of the function into account to avoid overlap with the 208 // rest of the function into account to avoid overlap with the
190 // parsing statistics. 209 // parsing statistics.
191 HistogramTimer* rate = is_eval 210 HistogramTimer* rate = info->is_eval()
192 ? &Counters::compile_eval 211 ? &Counters::compile_eval
193 : &Counters::compile; 212 : &Counters::compile;
194 HistogramTimerScope timer(rate); 213 HistogramTimerScope timer(rate);
195 214
196 // Compile the code. 215 // Compile the code.
216 FunctionLiteral* lit = info->function();
197 LiveEditFunctionTracker live_edit_tracker(lit); 217 LiveEditFunctionTracker live_edit_tracker(lit);
198 Handle<Code> code = MakeCode(context, &info); 218 Handle<Code> code = MakeCode(context, info);
199 219
200 // Check for stack-overflow exceptions. 220 // Check for stack-overflow exceptions.
201 if (code.is_null()) { 221 if (code.is_null()) {
202 Top::StackOverflow(); 222 Top::StackOverflow();
203 return Handle<SharedFunctionInfo>::null(); 223 return Handle<SharedFunctionInfo>::null();
204 } 224 }
205 225
206 if (script->name()->IsString()) { 226 if (script->name()->IsString()) {
207 PROFILE(CodeCreateEvent( 227 PROFILE(CodeCreateEvent(
208 is_eval ? Logger::EVAL_TAG : 228 info->is_eval()
209 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), 229 ? Logger::EVAL_TAG
210 *code, String::cast(script->name()))); 230 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
231 *code,
232 String::cast(script->name())));
211 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), 233 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
212 code->instruction_start(), 234 code->instruction_start(),
213 code->instruction_size())); 235 code->instruction_size()));
214 } else { 236 } else {
215 PROFILE(CodeCreateEvent( 237 PROFILE(CodeCreateEvent(
216 is_eval ? Logger::EVAL_TAG : 238 info->is_eval()
217 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), 239 ? Logger::EVAL_TAG
218 *code, "")); 240 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
219 OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script", 241 *code,
242 ""));
243 OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
220 code->instruction_start(), 244 code->instruction_start(),
221 code->instruction_size())); 245 code->instruction_size()));
222 } 246 }
223 247
224 // Allocate function. 248 // Allocate function.
225 Handle<SharedFunctionInfo> result = 249 Handle<SharedFunctionInfo> result =
226 Factory::NewSharedFunctionInfo( 250 Factory::NewSharedFunctionInfo(
227 lit->name(), 251 lit->name(),
228 lit->materialized_literal_count(), 252 lit->materialized_literal_count(),
229 code, 253 code,
230 SerializedScopeInfo::Create(info.scope())); 254 SerializedScopeInfo::Create(info->scope()));
231 255
232 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); 256 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
233 Compiler::SetFunctionInfo(result, lit, true, script); 257 Compiler::SetFunctionInfo(result, lit, true, script);
234 258
235 // Hint to the runtime system used when allocating space for initial 259 // Hint to the runtime system used when allocating space for initial
236 // property space by setting the expected number of properties for 260 // property space by setting the expected number of properties for
237 // the instances of the function. 261 // the instances of the function.
238 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); 262 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
239 263
240 #ifdef ENABLE_DEBUGGER_SUPPORT 264 #ifdef ENABLE_DEBUGGER_SUPPORT
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 if (!script_name.is_null()) { 320 if (!script_name.is_null()) {
297 script->set_name(*script_name); 321 script->set_name(*script_name);
298 script->set_line_offset(Smi::FromInt(line_offset)); 322 script->set_line_offset(Smi::FromInt(line_offset));
299 script->set_column_offset(Smi::FromInt(column_offset)); 323 script->set_column_offset(Smi::FromInt(column_offset));
300 } 324 }
301 325
302 script->set_data(script_data.is_null() ? Heap::undefined_value() 326 script->set_data(script_data.is_null() ? Heap::undefined_value()
303 : *script_data); 327 : *script_data);
304 328
305 // Compile the function and add it to the cache. 329 // Compile the function and add it to the cache.
306 result = MakeFunctionInfo(true, 330 CompilationInfo info(script);
307 false, 331 info.MarkAsGlobal();
308 DONT_VALIDATE_JSON, 332 info.SetExtension(extension);
309 script, 333 info.SetPreParseData(pre_data);
310 Handle<Context>::null(), 334 result = MakeFunctionInfo(&info, Handle<Context>::null());
311 extension,
312 pre_data);
313 if (extension == NULL && !result.is_null()) { 335 if (extension == NULL && !result.is_null()) {
314 CompilationCache::PutScript(source, result); 336 CompilationCache::PutScript(source, result);
315 } 337 }
316 338
317 // Get rid of the pre-parsing data (if necessary). 339 // Get rid of the pre-parsing data (if necessary).
318 if (input_pre_data == NULL && pre_data != NULL) { 340 if (input_pre_data == NULL && pre_data != NULL) {
319 delete pre_data; 341 delete pre_data;
320 } 342 }
321 } 343 }
322 344
323 if (result.is_null()) Top::ReportPendingMessages(); 345 if (result.is_null()) Top::ReportPendingMessages();
324 return result; 346 return result;
325 } 347 }
326 348
327 349
328 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, 350 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
329 Handle<Context> context, 351 Handle<Context> context,
330 bool is_global, 352 bool is_global,
331 ValidationState validate) { 353 ValidationState validate) {
332 // Note that if validation is required then no path through this 354 // Note that if validation is required then no path through this function
333 // function is allowed to return a value without validating that 355 // is allowed to return a value without validating that the input is legal
334 // the input is legal json. 356 // json.
357 bool is_json = (validate == VALIDATE_JSON);
335 358
336 int source_length = source->length(); 359 int source_length = source->length();
337 Counters::total_eval_size.Increment(source_length); 360 Counters::total_eval_size.Increment(source_length);
338 Counters::total_compile_size.Increment(source_length); 361 Counters::total_compile_size.Increment(source_length);
339 362
340 // The VM is in the COMPILER state until exiting this function. 363 // The VM is in the COMPILER state until exiting this function.
341 VMState state(COMPILER); 364 VMState state(COMPILER);
342 365
343 // Do a lookup in the compilation cache; if the entry is not there, 366 // Do a lookup in the compilation cache; if the entry is not there, invoke
344 // invoke the compiler and add the result to the cache. If we're 367 // the compiler and add the result to the cache. If we're evaluating json
345 // evaluating json we bypass the cache since we can't be sure a 368 // we bypass the cache since we can't be sure a potential value in the
346 // potential value in the cache has been validated. 369 // cache has been validated.
347 Handle<SharedFunctionInfo> result; 370 Handle<SharedFunctionInfo> result;
348 if (validate == DONT_VALIDATE_JSON) 371 if (!is_json) {
349 result = CompilationCache::LookupEval(source, context, is_global); 372 result = CompilationCache::LookupEval(source, context, is_global);
373 }
350 374
351 if (result.is_null()) { 375 if (result.is_null()) {
352 // Create a script object describing the script to be compiled. 376 // Create a script object describing the script to be compiled.
353 Handle<Script> script = Factory::NewScript(source); 377 Handle<Script> script = Factory::NewScript(source);
354 result = MakeFunctionInfo(is_global, 378 CompilationInfo info(script);
355 true, 379 info.MarkAsEval();
356 validate, 380 if (is_global) info.MarkAsGlobal();
357 script, 381 if (is_json) info.MarkAsJson();
358 context, 382 result = MakeFunctionInfo(&info, context);
359 NULL, 383 if (!result.is_null() && !is_json) {
360 NULL); 384 // For json it's unlikely that we'll ever see exactly the same string
361 if (!result.is_null() && validate != VALIDATE_JSON) { 385 // again so we don't use the compilation cache.
362 // For json it's unlikely that we'll ever see exactly the same
363 // string again so we don't use the compilation cache.
364 CompilationCache::PutEval(source, context, is_global, result); 386 CompilationCache::PutEval(source, context, is_global, result);
365 } 387 }
366 } 388 }
367 389
368 return result; 390 return result;
369 } 391 }
370 392
371 393
372 bool Compiler::CompileLazy(CompilationInfo* info) { 394 bool Compiler::CompileLazy(CompilationInfo* info) {
373 CompilationZoneScope zone_scope(DELETE_ON_EXIT); 395 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
374 396
375 // The VM is in the COMPILER state until exiting this function. 397 // The VM is in the COMPILER state until exiting this function.
376 VMState state(COMPILER); 398 VMState state(COMPILER);
377 399
378 PostponeInterruptsScope postpone; 400 PostponeInterruptsScope postpone;
379 401
380 // Compute name, source code and script data. 402 // Compute name, source code and script data.
381 Handle<SharedFunctionInfo> shared = info->shared_info(); 403 Handle<SharedFunctionInfo> shared = info->shared_info();
382 int compiled_size = shared->end_position() - shared->start_position(); 404 int compiled_size = shared->end_position() - shared->start_position();
383 Counters::total_compile_size.Increment(compiled_size); 405 Counters::total_compile_size.Increment(compiled_size);
384 406
385 // Generate the AST for the lazily compiled function. The AST may be 407 // Generate the AST for the lazily compiled function.
386 // NULL in case of parser stack overflow. 408 if (!Parser::Parse(info)) return false;
387 FunctionLiteral* lit = Parser::MakeLazyAST(shared);
388
389 // Check for parse errors.
390 if (lit == NULL) {
391 ASSERT(Top::has_pending_exception());
392 return false;
393 }
394 info->set_function(lit);
395 409
396 // Measure how long it takes to do the lazy compilation; only take 410 // Measure how long it takes to do the lazy compilation; only take
397 // the rest of the function into account to avoid overlap with the 411 // the rest of the function into account to avoid overlap with the
398 // lazy parsing statistics. 412 // lazy parsing statistics.
399 HistogramTimerScope timer(&Counters::compile_lazy); 413 HistogramTimerScope timer(&Counters::compile_lazy);
400 414
401 // Compile the code. 415 // Compile the code.
402 Handle<Code> code = MakeCode(Handle<Context>::null(), info); 416 Handle<Code> code = MakeCode(Handle<Context>::null(), info);
403 417
404 // Check for stack-overflow exception. 418 // Check for stack-overflow exception.
(...skipping 16 matching lines...) Expand all
421 // object last we avoid this. 435 // object last we avoid this.
422 Handle<SerializedScopeInfo> scope_info = 436 Handle<SerializedScopeInfo> scope_info =
423 SerializedScopeInfo::Create(info->scope()); 437 SerializedScopeInfo::Create(info->scope());
424 shared->set_scope_info(*scope_info); 438 shared->set_scope_info(*scope_info);
425 shared->set_code(*code); 439 shared->set_code(*code);
426 if (!info->closure().is_null()) { 440 if (!info->closure().is_null()) {
427 info->closure()->set_code(*code); 441 info->closure()->set_code(*code);
428 } 442 }
429 443
430 // Set the expected number of properties for instances. 444 // Set the expected number of properties for instances.
445 FunctionLiteral* lit = info->function();
431 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); 446 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
432 447
433 // Set the optimication hints after performing lazy compilation, as these are 448 // Set the optimication hints after performing lazy compilation, as these are
434 // not set when the function is set up as a lazily compiled function. 449 // not set when the function is set up as a lazily compiled function.
435 shared->SetThisPropertyAssignmentsInfo( 450 shared->SetThisPropertyAssignmentsInfo(
436 lit->has_only_simple_this_property_assignments(), 451 lit->has_only_simple_this_property_assignments(),
437 *lit->this_property_assignments()); 452 *lit->this_property_assignments());
438 453
439 // Check the function has compiled code. 454 // Check the function has compiled code.
440 ASSERT(shared->is_compiled()); 455 ASSERT(shared->is_compiled());
(...skipping 29 matching lines...) Expand all
470 } else { 485 } else {
471 // The bodies of function literals have not yet been visited by 486 // The bodies of function literals have not yet been visited by
472 // the AST optimizer/analyzer. 487 // the AST optimizer/analyzer.
473 if (!Rewriter::Optimize(literal)) { 488 if (!Rewriter::Optimize(literal)) {
474 return Handle<SharedFunctionInfo>::null(); 489 return Handle<SharedFunctionInfo>::null();
475 } 490 }
476 491
477 // Generate code and return it. The way that the compilation mode 492 // Generate code and return it. The way that the compilation mode
478 // is controlled by the command-line flags is described in 493 // is controlled by the command-line flags is described in
479 // the static helper function MakeCode. 494 // the static helper function MakeCode.
480 EagerCompilationInfo info(script, false); 495 CompilationInfo info(script);
481 info.set_function(literal); 496 info.SetFunction(literal);
482 497
483 bool is_run_once = literal->try_full_codegen(); 498 bool is_run_once = literal->try_full_codegen();
484 bool use_full = FLAG_full_compiler && !literal->contains_loops(); 499 bool use_full = FLAG_full_compiler && !literal->contains_loops();
485 if (AlwaysFullCompiler() || (use_full && is_run_once)) { 500 if (AlwaysFullCompiler() || (use_full && is_run_once)) {
486 code = FullCodeGenerator::MakeCode(&info); 501 code = FullCodeGenerator::MakeCode(&info);
487 } else { 502 } else {
488 // We fall back to the classic V8 code generator. 503 // We fall back to the classic V8 code generator.
489 AssignedVariablesAnalyzer ava(literal); 504 AssignedVariablesAnalyzer ava(literal);
490 if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null(); 505 if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
491 code = CodeGenerator::MakeCode(&info); 506 code = CodeGenerator::MakeCode(&info);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), 592 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
578 *code, *func_name)); 593 *code, *func_name));
579 OPROFILE(CreateNativeCodeRegion(*func_name, 594 OPROFILE(CreateNativeCodeRegion(*func_name,
580 code->instruction_start(), 595 code->instruction_start(),
581 code->instruction_size())); 596 code->instruction_size()));
582 } 597 }
583 } 598 }
584 } 599 }
585 600
586 } } // namespace v8::internal 601 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compiler.h ('k') | src/handles.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698