| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 4177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4188 } | 4188 } |
| 4189 FunctionLiteral* function = target_info.function(); | 4189 FunctionLiteral* function = target_info.function(); |
| 4190 | 4190 |
| 4191 // Count the number of AST nodes added by inlining this call. | 4191 // Count the number of AST nodes added by inlining this call. |
| 4192 int nodes_added = AstNode::Count() - count_before; | 4192 int nodes_added = AstNode::Count() - count_before; |
| 4193 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { | 4193 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { |
| 4194 TraceInline(target, caller, "target AST is too large"); | 4194 TraceInline(target, caller, "target AST is too large"); |
| 4195 return false; | 4195 return false; |
| 4196 } | 4196 } |
| 4197 | 4197 |
| 4198 // Check if we can handle all declarations in the inlined functions. | |
| 4199 VisitDeclarations(target_info.scope()->declarations()); | |
| 4200 if (HasStackOverflow()) { | |
| 4201 TraceInline(target, caller, "target has non-trivial declaration"); | |
| 4202 ClearStackOverflow(); | |
| 4203 return false; | |
| 4204 } | |
| 4205 | |
| 4206 // Don't inline functions that uses the arguments object or that | 4198 // Don't inline functions that uses the arguments object or that |
| 4207 // have a mismatching number of parameters. | 4199 // have a mismatching number of parameters. |
| 4208 int arity = expr->arguments()->length(); | 4200 int arity = expr->arguments()->length(); |
| 4209 if (function->scope()->arguments() != NULL || | 4201 if (function->scope()->arguments() != NULL || |
| 4210 arity != target_shared->formal_parameter_count()) { | 4202 arity != target_shared->formal_parameter_count()) { |
| 4211 TraceInline(target, caller, "target requires special argument handling"); | 4203 TraceInline(target, caller, "target requires special argument handling"); |
| 4212 return false; | 4204 return false; |
| 4213 } | 4205 } |
| 4214 | 4206 |
| 4207 // All declarations must be inlineable. |
| 4208 ZoneList<Declaration*>* decls = target_info.scope()->declarations(); |
| 4209 int decl_count = decls->length(); |
| 4210 for (int i = 0; i < decl_count; ++i) { |
| 4211 if (!decls->at(i)->IsInlineable()) { |
| 4212 TraceInline(target, caller, "target has non-trivial declaration"); |
| 4213 return false; |
| 4214 } |
| 4215 } |
| 4215 // All statements in the body must be inlineable. | 4216 // All statements in the body must be inlineable. |
| 4216 for (int i = 0, count = function->body()->length(); i < count; ++i) { | 4217 for (int i = 0, count = function->body()->length(); i < count; ++i) { |
| 4217 if (!function->body()->at(i)->IsInlineable()) { | 4218 if (!function->body()->at(i)->IsInlineable()) { |
| 4218 TraceInline(target, caller, "target contains unsupported syntax"); | 4219 TraceInline(target, caller, "target contains unsupported syntax"); |
| 4219 return false; | 4220 return false; |
| 4220 } | 4221 } |
| 4221 } | 4222 } |
| 4222 | 4223 |
| 4223 // Generate the deoptimization data for the unoptimized version of | 4224 // Generate the deoptimization data for the unoptimized version of |
| 4224 // the target function if we don't already have it. | 4225 // the target function if we don't already have it. |
| 4225 if (!target_shared->has_deoptimization_support()) { | 4226 if (!target_shared->has_deoptimization_support()) { |
| 4226 // Note that we compile here using the same AST that we will use for | 4227 // Note that we compile here using the same AST that we will use for |
| 4227 // generating the optimized inline code. | 4228 // generating the optimized inline code. |
| 4228 target_info.EnableDeoptimizationSupport(); | 4229 target_info.EnableDeoptimizationSupport(); |
| 4229 if (!FullCodeGenerator::MakeCode(&target_info)) { | 4230 if (!FullCodeGenerator::MakeCode(&target_info)) { |
| 4230 TraceInline(target, caller, "could not generate deoptimization info"); | 4231 TraceInline(target, caller, "could not generate deoptimization info"); |
| 4231 return false; | 4232 return false; |
| 4232 } | 4233 } |
| 4233 target_shared->EnableDeoptimizationSupport(*target_info.code()); | 4234 target_shared->EnableDeoptimizationSupport(*target_info.code()); |
| 4234 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, | 4235 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, |
| 4235 &target_info, | 4236 &target_info, |
| 4236 target_shared); | 4237 target_shared); |
| 4237 } | 4238 } |
| 4238 | 4239 |
| 4239 // ---------------------------------------------------------------- | 4240 // ---------------------------------------------------------------- |
| 4241 // After this point, we've made a decision to inline this function (so |
| 4242 // TryInline should always return true). |
| 4243 |
| 4240 // Save the pending call context and type feedback oracle. Set up new ones | 4244 // Save the pending call context and type feedback oracle. Set up new ones |
| 4241 // for the inlined function. | 4245 // for the inlined function. |
| 4242 ASSERT(target_shared->has_deoptimization_support()); | 4246 ASSERT(target_shared->has_deoptimization_support()); |
| 4243 TypeFeedbackOracle target_oracle( | 4247 TypeFeedbackOracle target_oracle( |
| 4244 Handle<Code>(target_shared->code()), | 4248 Handle<Code>(target_shared->code()), |
| 4245 Handle<Context>(target->context()->global_context())); | 4249 Handle<Context>(target->context()->global_context())); |
| 4246 FunctionState target_state(this, &target_info, &target_oracle); | 4250 FunctionState target_state(this, &target_info, &target_oracle); |
| 4247 | 4251 |
| 4248 HConstant* undefined = graph()->GetConstantUndefined(); | 4252 HConstant* undefined = graph()->GetConstantUndefined(); |
| 4249 HEnvironment* inner_env = | 4253 HEnvironment* inner_env = |
| 4250 environment()->CopyForInlining(target, | 4254 environment()->CopyForInlining(target, |
| 4251 function, | 4255 function, |
| 4252 HEnvironment::HYDROGEN, | 4256 HEnvironment::HYDROGEN, |
| 4253 undefined, | 4257 undefined, |
| 4254 call_kind); | 4258 call_kind); |
| 4255 HBasicBlock* body_entry = CreateBasicBlock(inner_env); | 4259 HBasicBlock* body_entry = CreateBasicBlock(inner_env); |
| 4256 current_block()->Goto(body_entry); | 4260 current_block()->Goto(body_entry); |
| 4257 | |
| 4258 body_entry->SetJoinId(expr->ReturnId()); | 4261 body_entry->SetJoinId(expr->ReturnId()); |
| 4259 set_current_block(body_entry); | 4262 set_current_block(body_entry); |
| 4260 AddInstruction(new(zone()) HEnterInlined(target, | 4263 AddInstruction(new(zone()) HEnterInlined(target, |
| 4261 function, | 4264 function, |
| 4262 call_kind)); | 4265 call_kind)); |
| 4266 VisitDeclarations(target_info.scope()->declarations()); |
| 4263 VisitStatements(function->body()); | 4267 VisitStatements(function->body()); |
| 4264 if (HasStackOverflow()) { | 4268 if (HasStackOverflow()) { |
| 4265 // Bail out if the inline function did, as we cannot residualize a call | 4269 // Bail out if the inline function did, as we cannot residualize a call |
| 4266 // instead. | 4270 // instead. |
| 4267 TraceInline(target, caller, "inline graph construction failed"); | 4271 TraceInline(target, caller, "inline graph construction failed"); |
| 4268 target_shared->DisableOptimization(*target); | 4272 target_shared->DisableOptimization(*target); |
| 4269 inline_bailout_ = true; | 4273 inline_bailout_ = true; |
| 4270 return true; | 4274 return true; |
| 4271 } | 4275 } |
| 4272 | 4276 |
| (...skipping 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5365 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 5369 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 5366 ASSERT(!HasStackOverflow()); | 5370 ASSERT(!HasStackOverflow()); |
| 5367 ASSERT(current_block() != NULL); | 5371 ASSERT(current_block() != NULL); |
| 5368 ASSERT(current_block()->HasPredecessor()); | 5372 ASSERT(current_block()->HasPredecessor()); |
| 5369 HThisFunction* self = new(zone()) HThisFunction; | 5373 HThisFunction* self = new(zone()) HThisFunction; |
| 5370 return ast_context()->ReturnInstruction(self, expr->id()); | 5374 return ast_context()->ReturnInstruction(self, expr->id()); |
| 5371 } | 5375 } |
| 5372 | 5376 |
| 5373 | 5377 |
| 5374 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 5378 void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
| 5375 // We allow only declarations that do not require code generation. | 5379 // We support only declarations that do not require code generation. |
| 5376 // The following all require code generation: global variables, | |
| 5377 // functions, and variables with slot type LOOKUP | |
| 5378 Variable* var = decl->proxy()->var(); | 5380 Variable* var = decl->proxy()->var(); |
| 5379 Slot* slot = var->AsSlot(); | 5381 if (!var->IsStackAllocated() || decl->fun() != NULL) { |
| 5380 if (var->is_global() || | |
| 5381 !var->IsStackAllocated() || | |
| 5382 (slot != NULL && slot->type() == Slot::LOOKUP) || | |
| 5383 decl->fun() != NULL) { | |
| 5384 return Bailout("unsupported declaration"); | 5382 return Bailout("unsupported declaration"); |
| 5385 } | 5383 } |
| 5386 | 5384 |
| 5387 if (decl->mode() == Variable::CONST) { | 5385 if (decl->mode() == Variable::CONST) { |
| 5388 ASSERT(var->IsStackAllocated()); | 5386 ASSERT(var->IsStackAllocated()); |
| 5389 environment()->Bind(var, graph()->GetConstantHole()); | 5387 environment()->Bind(var, graph()->GetConstantHole()); |
| 5390 } | 5388 } |
| 5391 } | 5389 } |
| 5392 | 5390 |
| 5393 | 5391 |
| (...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6315 } | 6313 } |
| 6316 } | 6314 } |
| 6317 | 6315 |
| 6318 #ifdef DEBUG | 6316 #ifdef DEBUG |
| 6319 if (graph_ != NULL) graph_->Verify(); | 6317 if (graph_ != NULL) graph_->Verify(); |
| 6320 if (allocator_ != NULL) allocator_->Verify(); | 6318 if (allocator_ != NULL) allocator_->Verify(); |
| 6321 #endif | 6319 #endif |
| 6322 } | 6320 } |
| 6323 | 6321 |
| 6324 } } // namespace v8::internal | 6322 } } // namespace v8::internal |
| OLD | NEW |