| 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 3559 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3570   if (expr->is_compound()) { | 3570   if (expr->is_compound()) { | 
| 3571     HandleCompoundAssignment(expr); | 3571     HandleCompoundAssignment(expr); | 
| 3572     return; | 3572     return; | 
| 3573   } | 3573   } | 
| 3574 | 3574 | 
| 3575   if (var != NULL) { | 3575   if (var != NULL) { | 
| 3576     if (var->mode() == Variable::CONST) { | 3576     if (var->mode() == Variable::CONST) { | 
| 3577       if (expr->op() != Token::INIT_CONST) { | 3577       if (expr->op() != Token::INIT_CONST) { | 
| 3578         return Bailout("non-initializer assignment to const"); | 3578         return Bailout("non-initializer assignment to const"); | 
| 3579       } | 3579       } | 
|  | 3580       if (!var->IsStackAllocated()) { | 
|  | 3581         return Bailout("assignment to const context slot"); | 
|  | 3582       } | 
| 3580       // We insert a use of the old value to detect unsupported uses of const | 3583       // We insert a use of the old value to detect unsupported uses of const | 
| 3581       // variables (e.g. initialization inside a loop). | 3584       // variables (e.g. initialization inside a loop). | 
| 3582       HValue* old_value = environment()->Lookup(var); | 3585       HValue* old_value = environment()->Lookup(var); | 
| 3583       AddInstruction(new HUseConst(old_value)); | 3586       AddInstruction(new HUseConst(old_value)); | 
| 3584     } | 3587     } | 
| 3585 | 3588 | 
| 3586     if (proxy->IsArguments()) return Bailout("assignment to arguments"); | 3589     if (proxy->IsArguments()) return Bailout("assignment to arguments"); | 
| 3587 | 3590 | 
| 3588     // Handle the assignment. | 3591     // Handle the assignment. | 
| 3589     if (var->IsStackAllocated()) { | 3592     if (var->IsStackAllocated()) { | 
| 3590       // We do not allow the arguments object to occur in a context where it | 3593       // We do not allow the arguments object to occur in a context where it | 
| 3591       // may escape, but assignments to stack-allocated locals are | 3594       // may escape, but assignments to stack-allocated locals are | 
| 3592       // permitted. | 3595       // permitted. | 
| 3593       CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 3596       CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 
| 3594       HValue* value = Pop(); | 3597       HValue* value = Pop(); | 
| 3595       Bind(var, value); | 3598       Bind(var, value); | 
| 3596       ast_context()->ReturnValue(value); | 3599       ast_context()->ReturnValue(value); | 
| 3597 | 3600 | 
| 3598     } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { | 3601     } else if (var->IsContextSlot()) { | 
|  | 3602       ASSERT(var->mode() != Variable::CONST); | 
| 3599       CHECK_ALIVE(VisitForValue(expr->value())); | 3603       CHECK_ALIVE(VisitForValue(expr->value())); | 
| 3600       HValue* context = BuildContextChainWalk(var); | 3604       HValue* context = BuildContextChainWalk(var); | 
| 3601       int index = var->AsSlot()->index(); | 3605       int index = var->AsSlot()->index(); | 
| 3602       HStoreContextSlot* instr = | 3606       HStoreContextSlot* instr = | 
| 3603           new(zone()) HStoreContextSlot(context, index, Top()); | 3607           new(zone()) HStoreContextSlot(context, index, Top()); | 
| 3604       AddInstruction(instr); | 3608       AddInstruction(instr); | 
| 3605       if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3609       if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 
| 3606       ast_context()->ReturnValue(Pop()); | 3610       ast_context()->ReturnValue(Pop()); | 
| 3607 | 3611 | 
| 3608     } else if (var->is_global()) { | 3612     } else if (var->is_global()) { | 
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4184   } | 4188   } | 
| 4185   FunctionLiteral* function = target_info.function(); | 4189   FunctionLiteral* function = target_info.function(); | 
| 4186 | 4190 | 
| 4187   // Count the number of AST nodes added by inlining this call. | 4191   // Count the number of AST nodes added by inlining this call. | 
| 4188   int nodes_added = AstNode::Count() - count_before; | 4192   int nodes_added = AstNode::Count() - count_before; | 
| 4189   if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { | 4193   if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { | 
| 4190     TraceInline(target, caller, "target AST is too large"); | 4194     TraceInline(target, caller, "target AST is too large"); | 
| 4191     return false; | 4195     return false; | 
| 4192   } | 4196   } | 
| 4193 | 4197 | 
| 4194   // Check if we can handle all declarations in the inlined functions. |  | 
| 4195   VisitDeclarations(target_info.scope()->declarations()); |  | 
| 4196   if (HasStackOverflow()) { |  | 
| 4197     TraceInline(target, caller, "target has non-trivial declaration"); |  | 
| 4198     ClearStackOverflow(); |  | 
| 4199     return false; |  | 
| 4200   } |  | 
| 4201 |  | 
| 4202   // Don't inline functions that uses the arguments object or that | 4198   // Don't inline functions that uses the arguments object or that | 
| 4203   // have a mismatching number of parameters. | 4199   // have a mismatching number of parameters. | 
| 4204   int arity = expr->arguments()->length(); | 4200   int arity = expr->arguments()->length(); | 
| 4205   if (function->scope()->arguments() != NULL || | 4201   if (function->scope()->arguments() != NULL || | 
| 4206       arity != target_shared->formal_parameter_count()) { | 4202       arity != target_shared->formal_parameter_count()) { | 
| 4207     TraceInline(target, caller, "target requires special argument handling"); | 4203     TraceInline(target, caller, "target requires special argument handling"); | 
| 4208     return false; | 4204     return false; | 
| 4209   } | 4205   } | 
| 4210 | 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   } | 
| 4211   // All statements in the body must be inlineable. | 4216   // All statements in the body must be inlineable. | 
| 4212   for (int i = 0, count = function->body()->length(); i < count; ++i) { | 4217   for (int i = 0, count = function->body()->length(); i < count; ++i) { | 
| 4213     if (!function->body()->at(i)->IsInlineable()) { | 4218     if (!function->body()->at(i)->IsInlineable()) { | 
| 4214       TraceInline(target, caller, "target contains unsupported syntax"); | 4219       TraceInline(target, caller, "target contains unsupported syntax"); | 
| 4215       return false; | 4220       return false; | 
| 4216     } | 4221     } | 
| 4217   } | 4222   } | 
| 4218 | 4223 | 
| 4219   // Generate the deoptimization data for the unoptimized version of | 4224   // Generate the deoptimization data for the unoptimized version of | 
| 4220   // the target function if we don't already have it. | 4225   // the target function if we don't already have it. | 
| 4221   if (!target_shared->has_deoptimization_support()) { | 4226   if (!target_shared->has_deoptimization_support()) { | 
| 4222     // 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 | 
| 4223     // generating the optimized inline code. | 4228     // generating the optimized inline code. | 
| 4224     target_info.EnableDeoptimizationSupport(); | 4229     target_info.EnableDeoptimizationSupport(); | 
| 4225     if (!FullCodeGenerator::MakeCode(&target_info)) { | 4230     if (!FullCodeGenerator::MakeCode(&target_info)) { | 
| 4226       TraceInline(target, caller, "could not generate deoptimization info"); | 4231       TraceInline(target, caller, "could not generate deoptimization info"); | 
| 4227       return false; | 4232       return false; | 
| 4228     } | 4233     } | 
| 4229     target_shared->EnableDeoptimizationSupport(*target_info.code()); | 4234     target_shared->EnableDeoptimizationSupport(*target_info.code()); | 
| 4230     Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, | 4235     Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, | 
| 4231                                         &target_info, | 4236                                         &target_info, | 
| 4232                                         target_shared); | 4237                                         target_shared); | 
| 4233   } | 4238   } | 
| 4234 | 4239 | 
| 4235   // ---------------------------------------------------------------- | 4240   // ---------------------------------------------------------------- | 
|  | 4241   // After this point, we've made a decision to inline this function (so | 
|  | 4242   // TryInline should always return true). | 
|  | 4243 | 
| 4236   // 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 | 
| 4237   // for the inlined function. | 4245   // for the inlined function. | 
| 4238   ASSERT(target_shared->has_deoptimization_support()); | 4246   ASSERT(target_shared->has_deoptimization_support()); | 
| 4239   TypeFeedbackOracle target_oracle( | 4247   TypeFeedbackOracle target_oracle( | 
| 4240       Handle<Code>(target_shared->code()), | 4248       Handle<Code>(target_shared->code()), | 
| 4241       Handle<Context>(target->context()->global_context())); | 4249       Handle<Context>(target->context()->global_context())); | 
| 4242   FunctionState target_state(this, &target_info, &target_oracle); | 4250   FunctionState target_state(this, &target_info, &target_oracle); | 
| 4243 | 4251 | 
| 4244   HConstant* undefined = graph()->GetConstantUndefined(); | 4252   HConstant* undefined = graph()->GetConstantUndefined(); | 
| 4245   HEnvironment* inner_env = | 4253   HEnvironment* inner_env = | 
| 4246       environment()->CopyForInlining(target, | 4254       environment()->CopyForInlining(target, | 
| 4247                                      function, | 4255                                      function, | 
| 4248                                      HEnvironment::HYDROGEN, | 4256                                      HEnvironment::HYDROGEN, | 
| 4249                                      undefined, | 4257                                      undefined, | 
| 4250                                      call_kind); | 4258                                      call_kind); | 
| 4251   HBasicBlock* body_entry = CreateBasicBlock(inner_env); | 4259   HBasicBlock* body_entry = CreateBasicBlock(inner_env); | 
| 4252   current_block()->Goto(body_entry); | 4260   current_block()->Goto(body_entry); | 
| 4253 |  | 
| 4254   body_entry->SetJoinId(expr->ReturnId()); | 4261   body_entry->SetJoinId(expr->ReturnId()); | 
| 4255   set_current_block(body_entry); | 4262   set_current_block(body_entry); | 
| 4256   AddInstruction(new(zone()) HEnterInlined(target, | 4263   AddInstruction(new(zone()) HEnterInlined(target, | 
| 4257                                            function, | 4264                                            function, | 
| 4258                                            call_kind)); | 4265                                            call_kind)); | 
|  | 4266   VisitDeclarations(target_info.scope()->declarations()); | 
| 4259   VisitStatements(function->body()); | 4267   VisitStatements(function->body()); | 
| 4260   if (HasStackOverflow()) { | 4268   if (HasStackOverflow()) { | 
| 4261     // 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 | 
| 4262     // instead. | 4270     // instead. | 
| 4263     TraceInline(target, caller, "inline graph construction failed"); | 4271     TraceInline(target, caller, "inline graph construction failed"); | 
| 4264     target_shared->DisableOptimization(*target); | 4272     target_shared->DisableOptimization(*target); | 
| 4265     inline_bailout_ = true; | 4273     inline_bailout_ = true; | 
| 4266     return true; | 4274     return true; | 
| 4267   } | 4275   } | 
| 4268 | 4276 | 
| (...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5086   ASSERT(call->arguments()->length() == 1); | 5094   ASSERT(call->arguments()->length() == 1); | 
| 5087   return true; | 5095   return true; | 
| 5088 } | 5096 } | 
| 5089 | 5097 | 
| 5090 | 5098 | 
| 5091 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 5099 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 
| 5092   ASSERT(!HasStackOverflow()); | 5100   ASSERT(!HasStackOverflow()); | 
| 5093   ASSERT(current_block() != NULL); | 5101   ASSERT(current_block() != NULL); | 
| 5094   ASSERT(current_block()->HasPredecessor()); | 5102   ASSERT(current_block()->HasPredecessor()); | 
| 5095   switch (expr->op()) { | 5103   switch (expr->op()) { | 
| 5096     case Token::COMMA: return VisitComma(expr); | 5104     case Token::COMMA: | 
| 5097     case Token::OR: return VisitAndOr(expr, false); | 5105       return VisitComma(expr); | 
| 5098     case Token::AND: return VisitAndOr(expr, true); | 5106     case Token::OR: | 
| 5099     default: return VisitCommon(expr); | 5107     case Token::AND: | 
|  | 5108       return VisitLogicalExpression(expr); | 
|  | 5109     default: | 
|  | 5110       return VisitArithmeticExpression(expr); | 
| 5100   } | 5111   } | 
| 5101 } | 5112 } | 
| 5102 | 5113 | 
| 5103 | 5114 | 
| 5104 void HGraphBuilder::VisitComma(BinaryOperation* expr) { | 5115 void HGraphBuilder::VisitComma(BinaryOperation* expr) { | 
| 5105   CHECK_ALIVE(VisitForEffect(expr->left())); | 5116   CHECK_ALIVE(VisitForEffect(expr->left())); | 
| 5106   // Visit the right subexpression in the same AST context as the entire | 5117   // Visit the right subexpression in the same AST context as the entire | 
| 5107   // expression. | 5118   // expression. | 
| 5108   Visit(expr->right()); | 5119   Visit(expr->right()); | 
| 5109 } | 5120 } | 
| 5110 | 5121 | 
| 5111 | 5122 | 
| 5112 void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) { | 5123 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { | 
|  | 5124   bool is_logical_and = expr->op() == Token::AND; | 
| 5113   if (ast_context()->IsTest()) { | 5125   if (ast_context()->IsTest()) { | 
| 5114     TestContext* context = TestContext::cast(ast_context()); | 5126     TestContext* context = TestContext::cast(ast_context()); | 
| 5115     // Translate left subexpression. | 5127     // Translate left subexpression. | 
| 5116     HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 5128     HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 
| 5117     if (is_logical_and) { | 5129     if (is_logical_and) { | 
| 5118       CHECK_BAILOUT(VisitForControl(expr->left(), | 5130       CHECK_BAILOUT(VisitForControl(expr->left(), | 
| 5119                                     eval_right, | 5131                                     eval_right, | 
| 5120                                     context->if_false())); | 5132                                     context->if_false())); | 
| 5121     } else { | 5133     } else { | 
| 5122       CHECK_BAILOUT(VisitForControl(expr->left(), | 5134       CHECK_BAILOUT(VisitForControl(expr->left(), | 
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5189 | 5201 | 
| 5190     HBasicBlock* join_block = | 5202     HBasicBlock* join_block = | 
| 5191       CreateJoin(empty_block, right_block, expr->id()); | 5203       CreateJoin(empty_block, right_block, expr->id()); | 
| 5192     set_current_block(join_block); | 5204     set_current_block(join_block); | 
| 5193     // We did not materialize any value in the predecessor environments, | 5205     // We did not materialize any value in the predecessor environments, | 
| 5194     // so there is no need to handle it here. | 5206     // so there is no need to handle it here. | 
| 5195   } | 5207   } | 
| 5196 } | 5208 } | 
| 5197 | 5209 | 
| 5198 | 5210 | 
| 5199 void HGraphBuilder::VisitCommon(BinaryOperation* expr) { | 5211 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { | 
| 5200   CHECK_ALIVE(VisitForValue(expr->left())); | 5212   CHECK_ALIVE(VisitForValue(expr->left())); | 
| 5201   CHECK_ALIVE(VisitForValue(expr->right())); | 5213   CHECK_ALIVE(VisitForValue(expr->right())); | 
| 5202   HValue* right = Pop(); | 5214   HValue* right = Pop(); | 
| 5203   HValue* left = Pop(); | 5215   HValue* left = Pop(); | 
| 5204   HInstruction* instr = BuildBinaryOperation(expr, left, right); | 5216   HInstruction* instr = BuildBinaryOperation(expr, left, right); | 
| 5205   instr->set_position(expr->position()); | 5217   instr->set_position(expr->position()); | 
| 5206   ast_context()->ReturnInstruction(instr, expr->id()); | 5218   ast_context()->ReturnInstruction(instr, expr->id()); | 
| 5207 } | 5219 } | 
| 5208 | 5220 | 
| 5209 | 5221 | 
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5357 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 5369 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 
| 5358   ASSERT(!HasStackOverflow()); | 5370   ASSERT(!HasStackOverflow()); | 
| 5359   ASSERT(current_block() != NULL); | 5371   ASSERT(current_block() != NULL); | 
| 5360   ASSERT(current_block()->HasPredecessor()); | 5372   ASSERT(current_block()->HasPredecessor()); | 
| 5361   HThisFunction* self = new(zone()) HThisFunction; | 5373   HThisFunction* self = new(zone()) HThisFunction; | 
| 5362   return ast_context()->ReturnInstruction(self, expr->id()); | 5374   return ast_context()->ReturnInstruction(self, expr->id()); | 
| 5363 } | 5375 } | 
| 5364 | 5376 | 
| 5365 | 5377 | 
| 5366 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 5378 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 
| 5367   // We allow only declarations that do not require code generation. | 5379   // We support only declarations that do not require code generation. | 
| 5368   // The following all require code generation: global variables, |  | 
| 5369   // functions, and variables with slot type LOOKUP |  | 
| 5370   Variable* var = decl->proxy()->var(); | 5380   Variable* var = decl->proxy()->var(); | 
| 5371   Slot* slot = var->AsSlot(); | 5381   if (!var->IsStackAllocated() || decl->fun() != NULL) { | 
| 5372   if (var->is_global() || |  | 
| 5373       !var->IsStackAllocated() || |  | 
| 5374       (slot != NULL && slot->type() == Slot::LOOKUP) || |  | 
| 5375       decl->fun() != NULL) { |  | 
| 5376     return Bailout("unsupported declaration"); | 5382     return Bailout("unsupported declaration"); | 
| 5377   } | 5383   } | 
| 5378 | 5384 | 
| 5379   if (decl->mode() == Variable::CONST) { | 5385   if (decl->mode() == Variable::CONST) { | 
|  | 5386     ASSERT(var->IsStackAllocated()); | 
| 5380     environment()->Bind(var, graph()->GetConstantHole()); | 5387     environment()->Bind(var, graph()->GetConstantHole()); | 
| 5381   } | 5388   } | 
| 5382 } | 5389 } | 
| 5383 | 5390 | 
| 5384 | 5391 | 
| 5385 // Generators for inline runtime functions. | 5392 // Generators for inline runtime functions. | 
| 5386 // Support for types. | 5393 // Support for types. | 
| 5387 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 5394 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 
| 5388   ASSERT(call->arguments()->length() == 1); | 5395   ASSERT(call->arguments()->length() == 1); | 
| 5389   CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5396   CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 
| (...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 6306     } | 6313     } | 
| 6307   } | 6314   } | 
| 6308 | 6315 | 
| 6309 #ifdef DEBUG | 6316 #ifdef DEBUG | 
| 6310   if (graph_ != NULL) graph_->Verify(); | 6317   if (graph_ != NULL) graph_->Verify(); | 
| 6311   if (allocator_ != NULL) allocator_->Verify(); | 6318   if (allocator_ != NULL) allocator_->Verify(); | 
| 6312 #endif | 6319 #endif | 
| 6313 } | 6320 } | 
| 6314 | 6321 | 
| 6315 } }  // namespace v8::internal | 6322 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|