| 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 |