OLD | NEW |
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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 | 155 |
156 | 156 |
157 #ifdef ENABLE_DEBUGGER_SUPPORT | 157 #ifdef ENABLE_DEBUGGER_SUPPORT |
158 Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) { | 158 Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) { |
159 Handle<Context> context = Handle<Context>::null(); | 159 Handle<Context> context = Handle<Context>::null(); |
160 return MakeCode(context, info); | 160 return MakeCode(context, info); |
161 } | 161 } |
162 #endif | 162 #endif |
163 | 163 |
164 | 164 |
165 static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global, | 165 static Handle<SharedFunctionInfo> MakeFunctionInfo( |
| 166 Isolate* isolate, |
| 167 bool is_global, |
166 bool is_eval, | 168 bool is_eval, |
167 Compiler::ValidationState validate, | 169 Compiler::ValidationState validate, |
168 Handle<Script> script, | 170 Handle<Script> script, |
169 Handle<Context> context, | 171 Handle<Context> context, |
170 v8::Extension* extension, | 172 v8::Extension* extension, |
171 ScriptDataImpl* pre_data) { | 173 ScriptDataImpl* pre_data) { |
172 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 174 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
173 | 175 |
174 PostponeInterruptsScope postpone; | 176 PostponeInterruptsScope postpone; |
175 | 177 |
176 ASSERT(!i::Isolate::Current()->global_context().is_null()); | 178 ASSERT(!isolate->global_context().is_null()); |
177 script->set_context_data((*i::Isolate::Current()->global_context())->data()); | 179 script->set_context_data((*isolate->global_context())->data()); |
178 | 180 |
179 bool is_json = (validate == Compiler::VALIDATE_JSON); | 181 bool is_json = (validate == Compiler::VALIDATE_JSON); |
180 #ifdef ENABLE_DEBUGGER_SUPPORT | 182 #ifdef ENABLE_DEBUGGER_SUPPORT |
181 if (is_eval || is_json) { | 183 if (is_eval || is_json) { |
182 script->set_compilation_type( | 184 script->set_compilation_type( |
183 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) : | 185 is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) : |
184 Smi::FromInt(Script::COMPILATION_TYPE_EVAL)); | 186 Smi::FromInt(Script::COMPILATION_TYPE_EVAL)); |
185 // For eval scripts add information on the function from which eval was | 187 // For eval scripts add information on the function from which eval was |
186 // called. | 188 // called. |
187 if (is_eval) { | 189 if (is_eval) { |
188 StackTraceFrameIterator it; | 190 StackTraceFrameIterator it; |
189 if (!it.done()) { | 191 if (!it.done()) { |
190 script->set_eval_from_shared( | 192 script->set_eval_from_shared( |
191 JSFunction::cast(it.frame()->function())->shared()); | 193 JSFunction::cast(it.frame()->function())->shared()); |
192 int offset = static_cast<int>( | 194 int offset = static_cast<int>( |
193 it.frame()->pc() - it.frame()->code()->instruction_start()); | 195 it.frame()->pc() - it.frame()->code()->instruction_start()); |
194 script->set_eval_from_instructions_offset(Smi::FromInt(offset)); | 196 script->set_eval_from_instructions_offset(Smi::FromInt(offset)); |
195 } | 197 } |
196 } | 198 } |
197 } | 199 } |
198 | 200 |
199 // Notify debugger | 201 // Notify debugger |
200 Isolate::Current()->debugger()->OnBeforeCompile(script); | 202 isolate->debugger()->OnBeforeCompile(script); |
201 #endif | 203 #endif |
202 | 204 |
203 // Only allow non-global compiles for eval. | 205 // Only allow non-global compiles for eval. |
204 ASSERT(is_eval || is_global); | 206 ASSERT(is_eval || is_global); |
205 | 207 |
206 // Build AST. | 208 // Build AST. |
207 FunctionLiteral* lit = | 209 FunctionLiteral* lit = |
208 MakeAST(is_global, script, extension, pre_data, is_json); | 210 MakeAST(is_global, script, extension, pre_data, is_json); |
209 | 211 |
210 LiveEditFunctionTracker live_edit_tracker(lit); | 212 LiveEditFunctionTracker live_edit_tracker(isolate, lit); |
211 | 213 |
212 // Check for parse errors. | 214 // Check for parse errors. |
213 if (lit == NULL) { | 215 if (lit == NULL) { |
214 ASSERT(Isolate::Current()->has_pending_exception()); | 216 ASSERT(isolate->has_pending_exception()); |
215 return Handle<SharedFunctionInfo>::null(); | 217 return Handle<SharedFunctionInfo>::null(); |
216 } | 218 } |
217 | 219 |
218 // Measure how long it takes to do the compilation; only take the | 220 // Measure how long it takes to do the compilation; only take the |
219 // rest of the function into account to avoid overlap with the | 221 // rest of the function into account to avoid overlap with the |
220 // parsing statistics. | 222 // parsing statistics. |
221 HistogramTimer* rate = is_eval | 223 HistogramTimer* rate = is_eval |
222 ? &Counters::compile_eval | 224 ? &Counters::compile_eval |
223 : &Counters::compile; | 225 : &Counters::compile; |
224 HistogramTimerScope timer(rate); | 226 HistogramTimerScope timer(rate); |
225 | 227 |
226 // Compile the code. | 228 // Compile the code. |
227 CompilationInfo info(lit, script, is_eval); | 229 CompilationInfo info(lit, script, is_eval); |
228 Handle<Code> code = MakeCode(context, &info); | 230 Handle<Code> code = MakeCode(context, &info); |
229 | 231 |
230 // Check for stack-overflow exceptions. | 232 // Check for stack-overflow exceptions. |
231 if (code.is_null()) { | 233 if (code.is_null()) { |
232 Isolate::Current()->StackOverflow(); | 234 isolate->StackOverflow(); |
233 return Handle<SharedFunctionInfo>::null(); | 235 return Handle<SharedFunctionInfo>::null(); |
234 } | 236 } |
235 | 237 |
236 if (script->name()->IsString()) { | 238 if (script->name()->IsString()) { |
237 PROFILE(CodeCreateEvent( | 239 PROFILE(CodeCreateEvent( |
238 is_eval ? Logger::EVAL_TAG : | 240 is_eval ? Logger::EVAL_TAG : |
239 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), | 241 Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
240 *code, String::cast(script->name()))); | 242 *code, String::cast(script->name()))); |
241 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), | 243 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), |
242 code->instruction_start(), | 244 code->instruction_start(), |
(...skipping 17 matching lines...) Expand all Loading... |
260 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); | 262 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); |
261 Compiler::SetFunctionInfo(result, lit, true, script); | 263 Compiler::SetFunctionInfo(result, lit, true, script); |
262 | 264 |
263 // Hint to the runtime system used when allocating space for initial | 265 // Hint to the runtime system used when allocating space for initial |
264 // property space by setting the expected number of properties for | 266 // property space by setting the expected number of properties for |
265 // the instances of the function. | 267 // the instances of the function. |
266 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); | 268 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); |
267 | 269 |
268 #ifdef ENABLE_DEBUGGER_SUPPORT | 270 #ifdef ENABLE_DEBUGGER_SUPPORT |
269 // Notify debugger | 271 // Notify debugger |
270 Isolate::Current()->debugger()->OnAfterCompile( | 272 isolate->debugger()->OnAfterCompile( |
271 script, Debugger::NO_AFTER_COMPILE_FLAGS); | 273 script, Debugger::NO_AFTER_COMPILE_FLAGS); |
272 #endif | 274 #endif |
273 | 275 |
274 live_edit_tracker.RecordFunctionInfo(result, lit); | 276 live_edit_tracker.RecordFunctionInfo(result, lit); |
275 | 277 |
276 return result; | 278 return result; |
277 } | 279 } |
278 | 280 |
279 | 281 |
280 static StaticResource<SafeStringInputBuffer> safe_string_input_buffer; | |
281 | |
282 | |
283 Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, | 282 Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, |
284 Handle<Object> script_name, | 283 Handle<Object> script_name, |
285 int line_offset, | 284 int line_offset, |
286 int column_offset, | 285 int column_offset, |
287 v8::Extension* extension, | 286 v8::Extension* extension, |
288 ScriptDataImpl* input_pre_data, | 287 ScriptDataImpl* input_pre_data, |
289 Handle<Object> script_data, | 288 Handle<Object> script_data, |
290 NativesFlag natives) { | 289 NativesFlag natives) { |
| 290 Isolate* isolate = Isolate::Current(); |
291 int source_length = source->length(); | 291 int source_length = source->length(); |
292 Counters::total_load_size.Increment(source_length); | 292 Counters::total_load_size.Increment(source_length); |
293 Counters::total_compile_size.Increment(source_length); | 293 Counters::total_compile_size.Increment(source_length); |
294 | 294 |
295 // The VM is in the COMPILER state until exiting this function. | 295 // The VM is in the COMPILER state until exiting this function. |
296 VMState state(COMPILER); | 296 VMState state(COMPILER); |
297 | 297 |
298 CompilationCache* compilation_cache = Isolate::Current()->compilation_cache(); | 298 CompilationCache* compilation_cache = isolate->compilation_cache(); |
299 | 299 |
300 // Do a lookup in the compilation cache but not for extensions. | 300 // Do a lookup in the compilation cache but not for extensions. |
301 Handle<SharedFunctionInfo> result; | 301 Handle<SharedFunctionInfo> result; |
302 if (extension == NULL) { | 302 if (extension == NULL) { |
303 result = compilation_cache->LookupScript(source, | 303 result = compilation_cache->LookupScript(source, |
304 script_name, | 304 script_name, |
305 line_offset, | 305 line_offset, |
306 column_offset); | 306 column_offset); |
307 } | 307 } |
308 | 308 |
309 if (result.is_null()) { | 309 if (result.is_null()) { |
310 // No cache entry found. Do pre-parsing and compile the script. | 310 // No cache entry found. Do pre-parsing and compile the script. |
311 ScriptDataImpl* pre_data = input_pre_data; | 311 ScriptDataImpl* pre_data = input_pre_data; |
312 if (pre_data == NULL && source_length >= FLAG_min_preparse_length) { | 312 if (pre_data == NULL && source_length >= FLAG_min_preparse_length) { |
313 Access<SafeStringInputBuffer> buf(&safe_string_input_buffer); | 313 Access<SafeStringInputBuffer> buf( |
| 314 isolate->compiler_safe_string_input_buffer()); |
314 buf->Reset(source.location()); | 315 buf->Reset(source.location()); |
315 pre_data = PreParse(source, buf.value(), extension); | 316 pre_data = PreParse(source, buf.value(), extension); |
316 } | 317 } |
317 | 318 |
318 // Create a script object describing the script to be compiled. | 319 // Create a script object describing the script to be compiled. |
319 Handle<Script> script = Factory::NewScript(source); | 320 Handle<Script> script = Factory::NewScript(source); |
320 if (natives == NATIVES_CODE) { | 321 if (natives == NATIVES_CODE) { |
321 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); | 322 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); |
322 } | 323 } |
323 if (!script_name.is_null()) { | 324 if (!script_name.is_null()) { |
324 script->set_name(*script_name); | 325 script->set_name(*script_name); |
325 script->set_line_offset(Smi::FromInt(line_offset)); | 326 script->set_line_offset(Smi::FromInt(line_offset)); |
326 script->set_column_offset(Smi::FromInt(column_offset)); | 327 script->set_column_offset(Smi::FromInt(column_offset)); |
327 } | 328 } |
328 | 329 |
329 script->set_data(script_data.is_null() ? HEAP->undefined_value() | 330 script->set_data(script_data.is_null() ? HEAP->undefined_value() |
330 : *script_data); | 331 : *script_data); |
331 | 332 |
332 // Compile the function and add it to the cache. | 333 // Compile the function and add it to the cache. |
333 result = MakeFunctionInfo(true, | 334 result = MakeFunctionInfo(isolate, |
| 335 true, |
334 false, | 336 false, |
335 DONT_VALIDATE_JSON, | 337 DONT_VALIDATE_JSON, |
336 script, | 338 script, |
337 Handle<Context>::null(), | 339 Handle<Context>::null(), |
338 extension, | 340 extension, |
339 pre_data); | 341 pre_data); |
340 if (extension == NULL && !result.is_null()) { | 342 if (extension == NULL && !result.is_null()) { |
341 compilation_cache->PutScript(source, result); | 343 compilation_cache->PutScript(source, result); |
342 } | 344 } |
343 | 345 |
344 // Get rid of the pre-parsing data (if necessary). | 346 // Get rid of the pre-parsing data (if necessary). |
345 if (input_pre_data == NULL && pre_data != NULL) { | 347 if (input_pre_data == NULL && pre_data != NULL) { |
346 delete pre_data; | 348 delete pre_data; |
347 } | 349 } |
348 } | 350 } |
349 | 351 |
350 if (result.is_null()) Isolate::Current()->ReportPendingMessages(); | 352 if (result.is_null()) isolate->ReportPendingMessages(); |
351 return result; | 353 return result; |
352 } | 354 } |
353 | 355 |
354 | 356 |
355 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, | 357 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, |
356 Handle<Context> context, | 358 Handle<Context> context, |
357 bool is_global, | 359 bool is_global, |
358 ValidationState validate) { | 360 ValidationState validate) { |
| 361 Isolate* isolate = Isolate::Current(); |
359 // Note that if validation is required then no path through this | 362 // Note that if validation is required then no path through this |
360 // function is allowed to return a value without validating that | 363 // function is allowed to return a value without validating that |
361 // the input is legal json. | 364 // the input is legal json. |
362 | 365 |
363 int source_length = source->length(); | 366 int source_length = source->length(); |
364 Counters::total_eval_size.Increment(source_length); | 367 Counters::total_eval_size.Increment(source_length); |
365 Counters::total_compile_size.Increment(source_length); | 368 Counters::total_compile_size.Increment(source_length); |
366 | 369 |
367 // The VM is in the COMPILER state until exiting this function. | 370 // The VM is in the COMPILER state until exiting this function. |
368 VMState state(COMPILER); | 371 VMState state(COMPILER); |
369 | 372 |
370 CompilationCache* compilation_cache = Isolate::Current()->compilation_cache(); | 373 CompilationCache* compilation_cache = isolate->compilation_cache(); |
371 | 374 |
372 // Do a lookup in the compilation cache; if the entry is not there, | 375 // Do a lookup in the compilation cache; if the entry is not there, |
373 // invoke the compiler and add the result to the cache. If we're | 376 // invoke the compiler and add the result to the cache. If we're |
374 // evaluating json we bypass the cache since we can't be sure a | 377 // evaluating json we bypass the cache since we can't be sure a |
375 // potential value in the cache has been validated. | 378 // potential value in the cache has been validated. |
376 Handle<SharedFunctionInfo> result; | 379 Handle<SharedFunctionInfo> result; |
377 if (validate == DONT_VALIDATE_JSON) | 380 if (validate == DONT_VALIDATE_JSON) |
378 result = compilation_cache->LookupEval(source, context, is_global); | 381 result = compilation_cache->LookupEval(source, context, is_global); |
379 | 382 |
380 if (result.is_null()) { | 383 if (result.is_null()) { |
381 // Create a script object describing the script to be compiled. | 384 // Create a script object describing the script to be compiled. |
382 Handle<Script> script = Factory::NewScript(source); | 385 Handle<Script> script = Factory::NewScript(source); |
383 result = MakeFunctionInfo(is_global, | 386 result = MakeFunctionInfo(isolate, |
| 387 is_global, |
384 true, | 388 true, |
385 validate, | 389 validate, |
386 script, | 390 script, |
387 context, | 391 context, |
388 NULL, | 392 NULL, |
389 NULL); | 393 NULL); |
390 if (!result.is_null() && validate != VALIDATE_JSON) { | 394 if (!result.is_null() && validate != VALIDATE_JSON) { |
391 // For json it's unlikely that we'll ever see exactly the same | 395 // For json it's unlikely that we'll ever see exactly the same |
392 // string again so we don't use the compilation cache. | 396 // string again so we don't use the compilation cache. |
393 compilation_cache->PutEval(source, context, is_global, result); | 397 compilation_cache->PutEval(source, context, is_global, result); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 | 469 |
466 // Check the function has compiled code. | 470 // Check the function has compiled code. |
467 ASSERT(shared->is_compiled()); | 471 ASSERT(shared->is_compiled()); |
468 return true; | 472 return true; |
469 } | 473 } |
470 | 474 |
471 | 475 |
472 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 476 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
473 Handle<Script> script, | 477 Handle<Script> script, |
474 AstVisitor* caller) { | 478 AstVisitor* caller) { |
475 LiveEditFunctionTracker live_edit_tracker(literal); | 479 Isolate* isolate = Isolate::Current(); |
| 480 LiveEditFunctionTracker live_edit_tracker(isolate, literal); |
476 #ifdef DEBUG | 481 #ifdef DEBUG |
477 // We should not try to compile the same function literal more than | 482 // We should not try to compile the same function literal more than |
478 // once. | 483 // once. |
479 literal->mark_as_compiled(); | 484 literal->mark_as_compiled(); |
480 #endif | 485 #endif |
481 | 486 |
482 // Determine if the function can be lazily compiled. This is | 487 // Determine if the function can be lazily compiled. This is |
483 // necessary to allow some of our builtin JS files to be lazily | 488 // necessary to allow some of our builtin JS files to be lazily |
484 // compiled. These builtins cannot be handled lazily by the parser, | 489 // compiled. These builtins cannot be handled lazily by the parser, |
485 // since we have to know if a function uses the special natives | 490 // since we have to know if a function uses the special natives |
486 // syntax, which is something the parser records. | 491 // syntax, which is something the parser records. |
487 bool allow_lazy = literal->AllowsLazyCompilation() && | 492 bool allow_lazy = literal->AllowsLazyCompilation() && |
488 !LiveEditFunctionTracker::IsActive(); | 493 !LiveEditFunctionTracker::IsActive(isolate); |
489 | 494 |
490 // Generate code | 495 // Generate code |
491 Handle<Code> code; | 496 Handle<Code> code; |
492 if (FLAG_lazy && allow_lazy) { | 497 if (FLAG_lazy && allow_lazy) { |
493 code = ComputeLazyCompile(literal->num_parameters()); | 498 code = ComputeLazyCompile(literal->num_parameters()); |
494 } else { | 499 } else { |
495 // The bodies of function literals have not yet been visited by | 500 // The bodies of function literals have not yet been visited by |
496 // the AST optimizer/analyzer. | 501 // the AST optimizer/analyzer. |
497 if (!Rewriter::Optimize(literal)) { | 502 if (!Rewriter::Optimize(literal)) { |
498 return Handle<SharedFunctionInfo>::null(); | 503 return Handle<SharedFunctionInfo>::null(); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), | 644 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), |
640 *code, *func_name)); | 645 *code, *func_name)); |
641 OPROFILE(CreateNativeCodeRegion(*func_name, | 646 OPROFILE(CreateNativeCodeRegion(*func_name, |
642 code->instruction_start(), | 647 code->instruction_start(), |
643 code->instruction_size())); | 648 code->instruction_size())); |
644 } | 649 } |
645 } | 650 } |
646 } | 651 } |
647 | 652 |
648 } } // namespace v8::internal | 653 } } // namespace v8::internal |
OLD | NEW |