| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3816 | 3816 |
| 3817 | 3817 |
| 3818 #define CHECK_ALIVE(call) \ | 3818 #define CHECK_ALIVE(call) \ |
| 3819 do { \ | 3819 do { \ |
| 3820 call; \ | 3820 call; \ |
| 3821 if (HasStackOverflow() || current_block() == NULL) return; \ | 3821 if (HasStackOverflow() || current_block() == NULL) return; \ |
| 3822 } while (false) | 3822 } while (false) |
| 3823 | 3823 |
| 3824 | 3824 |
| 3825 void HOptimizedGraphBuilder::Bailout(const char* reason) { | 3825 void HOptimizedGraphBuilder::Bailout(const char* reason) { |
| 3826 info()->set_bailout_reason(reason); | 3826 current_info()->set_bailout_reason(reason); |
| 3827 SetStackOverflow(); | 3827 SetStackOverflow(); |
| 3828 } | 3828 } |
| 3829 | 3829 |
| 3830 | 3830 |
| 3831 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 3831 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
| 3832 EffectContext for_effect(this); | 3832 EffectContext for_effect(this); |
| 3833 Visit(expr); | 3833 Visit(expr); |
| 3834 } | 3834 } |
| 3835 | 3835 |
| 3836 | 3836 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3873 | 3873 |
| 3874 void HOptimizedGraphBuilder::VisitExpressions( | 3874 void HOptimizedGraphBuilder::VisitExpressions( |
| 3875 ZoneList<Expression*>* exprs) { | 3875 ZoneList<Expression*>* exprs) { |
| 3876 for (int i = 0; i < exprs->length(); ++i) { | 3876 for (int i = 0; i < exprs->length(); ++i) { |
| 3877 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 3877 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
| 3878 } | 3878 } |
| 3879 } | 3879 } |
| 3880 | 3880 |
| 3881 | 3881 |
| 3882 bool HOptimizedGraphBuilder::BuildGraph() { | 3882 bool HOptimizedGraphBuilder::BuildGraph() { |
| 3883 if (info()->function()->is_generator()) { | 3883 if (current_info()->function()->is_generator()) { |
| 3884 Bailout("function is a generator"); | 3884 Bailout("function is a generator"); |
| 3885 return false; | 3885 return false; |
| 3886 } | 3886 } |
| 3887 Scope* scope = info()->scope(); | 3887 Scope* scope = current_info()->scope(); |
| 3888 if (scope->HasIllegalRedeclaration()) { | 3888 if (scope->HasIllegalRedeclaration()) { |
| 3889 Bailout("function with illegal redeclaration"); | 3889 Bailout("function with illegal redeclaration"); |
| 3890 return false; | 3890 return false; |
| 3891 } | 3891 } |
| 3892 if (scope->calls_eval()) { | 3892 if (scope->calls_eval()) { |
| 3893 Bailout("function calls eval"); | 3893 Bailout("function calls eval"); |
| 3894 return false; | 3894 return false; |
| 3895 } | 3895 } |
| 3896 SetUpScope(scope); | 3896 SetUpScope(scope); |
| 3897 | 3897 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3921 if (scope->is_function_scope() && scope->function() != NULL) { | 3921 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3922 VisitVariableDeclaration(scope->function()); | 3922 VisitVariableDeclaration(scope->function()); |
| 3923 } | 3923 } |
| 3924 VisitDeclarations(scope->declarations()); | 3924 VisitDeclarations(scope->declarations()); |
| 3925 AddSimulate(BailoutId::Declarations()); | 3925 AddSimulate(BailoutId::Declarations()); |
| 3926 | 3926 |
| 3927 HValue* context = environment()->LookupContext(); | 3927 HValue* context = environment()->LookupContext(); |
| 3928 AddInstruction( | 3928 AddInstruction( |
| 3929 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); | 3929 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); |
| 3930 | 3930 |
| 3931 VisitStatements(info()->function()->body()); | 3931 VisitStatements(current_info()->function()->body()); |
| 3932 if (HasStackOverflow()) return false; | 3932 if (HasStackOverflow()) return false; |
| 3933 | 3933 |
| 3934 if (current_block() != NULL) { | 3934 if (current_block() != NULL) { |
| 3935 AddReturn(graph()->GetConstantUndefined()); | 3935 AddReturn(graph()->GetConstantUndefined()); |
| 3936 set_current_block(NULL); | 3936 set_current_block(NULL); |
| 3937 } | 3937 } |
| 3938 | 3938 |
| 3939 // If the checksum of the number of type info changes is the same as the | 3939 // If the checksum of the number of type info changes is the same as the |
| 3940 // last time this function was compiled, then this recompile is likely not | 3940 // last time this function was compiled, then this recompile is likely not |
| 3941 // due to missing/inadequate type feedback, but rather too aggressive | 3941 // due to missing/inadequate type feedback, but rather too aggressive |
| 3942 // optimization. Disable optimistic LICM in that case. | 3942 // optimization. Disable optimistic LICM in that case. |
| 3943 Handle<Code> unoptimized_code(info()->shared_info()->code()); | 3943 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
| 3944 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 3944 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 3945 Handle<TypeFeedbackInfo> type_info( | 3945 Handle<TypeFeedbackInfo> type_info( |
| 3946 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 3946 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
| 3947 int checksum = type_info->own_type_change_checksum(); | 3947 int checksum = type_info->own_type_change_checksum(); |
| 3948 int composite_checksum = graph()->update_type_change_checksum(checksum); | 3948 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3949 graph()->set_use_optimistic_licm( | 3949 graph()->set_use_optimistic_licm( |
| 3950 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 3950 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3951 type_info->set_inlined_type_change_checksum(composite_checksum); | 3951 type_info->set_inlined_type_change_checksum(composite_checksum); |
| 3952 | 3952 |
| 3953 return true; | 3953 return true; |
| (...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5122 } else { | 5122 } else { |
| 5123 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 5123 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
| 5124 if (last_block != NULL) last_block->Goto(break_block); | 5124 if (last_block != NULL) last_block->Goto(break_block); |
| 5125 break_block->SetJoinId(stmt->ExitId()); | 5125 break_block->SetJoinId(stmt->ExitId()); |
| 5126 set_current_block(break_block); | 5126 set_current_block(break_block); |
| 5127 } | 5127 } |
| 5128 } | 5128 } |
| 5129 | 5129 |
| 5130 | 5130 |
| 5131 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | 5131 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { |
| 5132 return statement->OsrEntryId() == info()->osr_ast_id(); | 5132 return statement->OsrEntryId() == current_info()->osr_ast_id(); |
| 5133 } | 5133 } |
| 5134 | 5134 |
| 5135 | 5135 |
| 5136 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 5136 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
| 5137 if (!HasOsrEntryAt(statement)) return false; | 5137 if (!HasOsrEntryAt(statement)) return false; |
| 5138 | 5138 |
| 5139 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 5139 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
| 5140 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 5140 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
| 5141 HValue* true_value = graph()->GetConstantTrue(); | 5141 HValue* true_value = graph()->GetConstantTrue(); |
| 5142 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | 5142 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5509 | 5509 |
| 5510 return Handle<SharedFunctionInfo>(); | 5510 return Handle<SharedFunctionInfo>(); |
| 5511 } | 5511 } |
| 5512 | 5512 |
| 5513 | 5513 |
| 5514 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 5514 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 5515 ASSERT(!HasStackOverflow()); | 5515 ASSERT(!HasStackOverflow()); |
| 5516 ASSERT(current_block() != NULL); | 5516 ASSERT(current_block() != NULL); |
| 5517 ASSERT(current_block()->HasPredecessor()); | 5517 ASSERT(current_block()->HasPredecessor()); |
| 5518 Handle<SharedFunctionInfo> shared_info = | 5518 Handle<SharedFunctionInfo> shared_info = |
| 5519 SearchSharedFunctionInfo(info()->shared_info()->code(), expr); | 5519 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); |
| 5520 if (shared_info.is_null()) { | 5520 if (shared_info.is_null()) { |
| 5521 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 5521 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); |
| 5522 } | 5522 } |
| 5523 // We also have a stack overflow if the recursive compilation did. | 5523 // We also have a stack overflow if the recursive compilation did. |
| 5524 if (HasStackOverflow()) return; | 5524 if (HasStackOverflow()) return; |
| 5525 HValue* context = environment()->LookupContext(); | 5525 HValue* context = environment()->LookupContext(); |
| 5526 HFunctionLiteral* instr = | 5526 HFunctionLiteral* instr = |
| 5527 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 5527 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
| 5528 return ast_context()->ReturnInstruction(instr, expr->id()); | 5528 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5529 } | 5529 } |
| 5530 | 5530 |
| 5531 | 5531 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5572 if (join != NULL && !ast_context()->IsEffect()) { | 5572 if (join != NULL && !ast_context()->IsEffect()) { |
| 5573 return ast_context()->ReturnValue(Pop()); | 5573 return ast_context()->ReturnValue(Pop()); |
| 5574 } | 5574 } |
| 5575 } | 5575 } |
| 5576 } | 5576 } |
| 5577 | 5577 |
| 5578 | 5578 |
| 5579 HOptimizedGraphBuilder::GlobalPropertyAccess | 5579 HOptimizedGraphBuilder::GlobalPropertyAccess |
| 5580 HOptimizedGraphBuilder::LookupGlobalProperty( | 5580 HOptimizedGraphBuilder::LookupGlobalProperty( |
| 5581 Variable* var, LookupResult* lookup, bool is_store) { | 5581 Variable* var, LookupResult* lookup, bool is_store) { |
| 5582 if (var->is_this() || !info()->has_global_object()) { | 5582 if (var->is_this() || !current_info()->has_global_object()) { |
| 5583 return kUseGeneric; | 5583 return kUseGeneric; |
| 5584 } | 5584 } |
| 5585 Handle<GlobalObject> global(info()->global_object()); | 5585 Handle<GlobalObject> global(current_info()->global_object()); |
| 5586 global->Lookup(*var->name(), lookup); | 5586 global->Lookup(*var->name(), lookup); |
| 5587 if (!lookup->IsNormal() || | 5587 if (!lookup->IsNormal() || |
| 5588 (is_store && lookup->IsReadOnly()) || | 5588 (is_store && lookup->IsReadOnly()) || |
| 5589 lookup->holder() != *global) { | 5589 lookup->holder() != *global) { |
| 5590 return kUseGeneric; | 5590 return kUseGeneric; |
| 5591 } | 5591 } |
| 5592 | 5592 |
| 5593 return kUseCell; | 5593 return kUseCell; |
| 5594 } | 5594 } |
| 5595 | 5595 |
| 5596 | 5596 |
| 5597 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5597 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 5598 ASSERT(var->IsContextSlot()); | 5598 ASSERT(var->IsContextSlot()); |
| 5599 HValue* context = environment()->LookupContext(); | 5599 HValue* context = environment()->LookupContext(); |
| 5600 int length = info()->scope()->ContextChainLength(var->scope()); | 5600 int length = current_info()->scope()->ContextChainLength(var->scope()); |
| 5601 while (length-- > 0) { | 5601 while (length-- > 0) { |
| 5602 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 5602 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
| 5603 AddInstruction(context_instruction); | 5603 AddInstruction(context_instruction); |
| 5604 context = context_instruction; | 5604 context = context_instruction; |
| 5605 } | 5605 } |
| 5606 return context; | 5606 return context; |
| 5607 } | 5607 } |
| 5608 | 5608 |
| 5609 | 5609 |
| 5610 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5610 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5626 HConstant* instr = | 5626 HConstant* instr = |
| 5627 new(zone()) HConstant(constant_value, Representation::Tagged()); | 5627 new(zone()) HConstant(constant_value, Representation::Tagged()); |
| 5628 return ast_context()->ReturnInstruction(instr, expr->id()); | 5628 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5629 } | 5629 } |
| 5630 | 5630 |
| 5631 LookupResult lookup(isolate()); | 5631 LookupResult lookup(isolate()); |
| 5632 GlobalPropertyAccess type = | 5632 GlobalPropertyAccess type = |
| 5633 LookupGlobalProperty(variable, &lookup, false); | 5633 LookupGlobalProperty(variable, &lookup, false); |
| 5634 | 5634 |
| 5635 if (type == kUseCell && | 5635 if (type == kUseCell && |
| 5636 info()->global_object()->IsAccessCheckNeeded()) { | 5636 current_info()->global_object()->IsAccessCheckNeeded()) { |
| 5637 type = kUseGeneric; | 5637 type = kUseGeneric; |
| 5638 } | 5638 } |
| 5639 | 5639 |
| 5640 if (type == kUseCell) { | 5640 if (type == kUseCell) { |
| 5641 Handle<GlobalObject> global(info()->global_object()); | 5641 Handle<GlobalObject> global(current_info()->global_object()); |
| 5642 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5642 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5643 HLoadGlobalCell* instr = | 5643 HLoadGlobalCell* instr = |
| 5644 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); | 5644 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); |
| 5645 return ast_context()->ReturnInstruction(instr, expr->id()); | 5645 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5646 } else { | 5646 } else { |
| 5647 HValue* context = environment()->LookupContext(); | 5647 HValue* context = environment()->LookupContext(); |
| 5648 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5648 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 5649 AddInstruction(global_object); | 5649 AddInstruction(global_object); |
| 5650 HLoadGlobalGeneric* instr = | 5650 HLoadGlobalGeneric* instr = |
| 5651 new(zone()) HLoadGlobalGeneric(context, | 5651 new(zone()) HLoadGlobalGeneric(context, |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6222 // Otherwise, find the top prototype. | 6222 // Otherwise, find the top prototype. |
| 6223 while (proto->GetPrototype(isolate())->IsJSObject()) { | 6223 while (proto->GetPrototype(isolate())->IsJSObject()) { |
| 6224 proto = proto->GetPrototype(isolate()); | 6224 proto = proto->GetPrototype(isolate()); |
| 6225 } | 6225 } |
| 6226 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 6226 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
| 6227 } | 6227 } |
| 6228 ASSERT(proto->IsJSObject()); | 6228 ASSERT(proto->IsJSObject()); |
| 6229 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6229 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 6230 Handle<JSObject>(JSObject::cast(map->prototype())), | 6230 Handle<JSObject>(JSObject::cast(map->prototype())), |
| 6231 Handle<JSObject>(JSObject::cast(proto)), | 6231 Handle<JSObject>(JSObject::cast(proto)), |
| 6232 zone())); | 6232 zone(), |
| 6233 top_info())); |
| 6233 } | 6234 } |
| 6234 | 6235 |
| 6235 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 6236 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
| 6236 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | 6237 Representation representation = ComputeLoadStoreRepresentation(map, lookup); |
| 6237 bool transition_to_field = lookup->IsTransitionToField(*map); | 6238 bool transition_to_field = lookup->IsTransitionToField(*map); |
| 6238 | 6239 |
| 6239 HStoreNamedField *instr; | 6240 HStoreNamedField *instr; |
| 6240 if (FLAG_track_double_fields && representation.IsDouble()) { | 6241 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 6241 if (transition_to_field) { | 6242 if (transition_to_field) { |
| 6242 // The store requires a mutable HeapNumber to be allocated. | 6243 // The store requires a mutable HeapNumber to be allocated. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6258 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); | 6259 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); |
| 6259 } | 6260 } |
| 6260 } else { | 6261 } else { |
| 6261 // This is a non-double store. | 6262 // This is a non-double store. |
| 6262 instr = new(zone()) HStoreNamedField( | 6263 instr = new(zone()) HStoreNamedField( |
| 6263 object, field_access, value, representation); | 6264 object, field_access, value, representation); |
| 6264 } | 6265 } |
| 6265 | 6266 |
| 6266 if (transition_to_field) { | 6267 if (transition_to_field) { |
| 6267 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 6268 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 6268 instr->set_transition(transition); | 6269 instr->SetTransition(transition, top_info()); |
| 6269 // TODO(fschneider): Record the new map type of the object in the IR to | 6270 // TODO(fschneider): Record the new map type of the object in the IR to |
| 6270 // enable elimination of redundant checks after the transition store. | 6271 // enable elimination of redundant checks after the transition store. |
| 6271 instr->SetGVNFlag(kChangesMaps); | 6272 instr->SetGVNFlag(kChangesMaps); |
| 6272 } | 6273 } |
| 6273 return instr; | 6274 return instr; |
| 6274 } | 6275 } |
| 6275 | 6276 |
| 6276 | 6277 |
| 6277 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 6278 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( |
| 6278 HValue* object, | 6279 HValue* object, |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6561 // superclass of Assignment and CountOperation, we cannot just pass the | 6562 // superclass of Assignment and CountOperation, we cannot just pass the |
| 6562 // owning expression instead of position and ast_id separately. | 6563 // owning expression instead of position and ast_id separately. |
| 6563 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6564 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6564 Variable* var, | 6565 Variable* var, |
| 6565 HValue* value, | 6566 HValue* value, |
| 6566 int position, | 6567 int position, |
| 6567 BailoutId ast_id) { | 6568 BailoutId ast_id) { |
| 6568 LookupResult lookup(isolate()); | 6569 LookupResult lookup(isolate()); |
| 6569 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 6570 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 6570 if (type == kUseCell) { | 6571 if (type == kUseCell) { |
| 6571 Handle<GlobalObject> global(info()->global_object()); | 6572 Handle<GlobalObject> global(current_info()->global_object()); |
| 6572 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 6573 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 6573 HInstruction* instr = | 6574 HInstruction* instr = |
| 6574 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 6575 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
| 6575 instr->set_position(position); | 6576 instr->set_position(position); |
| 6576 AddInstruction(instr); | 6577 AddInstruction(instr); |
| 6577 if (instr->HasObservableSideEffects()) { | 6578 if (instr->HasObservableSideEffects()) { |
| 6578 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 6579 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 6579 } | 6580 } |
| 6580 } else { | 6581 } else { |
| 6581 HValue* context = environment()->LookupContext(); | 6582 HValue* context = environment()->LookupContext(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6626 if (var->mode() == CONST) { | 6627 if (var->mode() == CONST) { |
| 6627 return Bailout("unsupported const compound assignment"); | 6628 return Bailout("unsupported const compound assignment"); |
| 6628 } | 6629 } |
| 6629 BindIfLive(var, Top()); | 6630 BindIfLive(var, Top()); |
| 6630 break; | 6631 break; |
| 6631 | 6632 |
| 6632 case Variable::CONTEXT: { | 6633 case Variable::CONTEXT: { |
| 6633 // Bail out if we try to mutate a parameter value in a function | 6634 // Bail out if we try to mutate a parameter value in a function |
| 6634 // using the arguments object. We do not (yet) correctly handle the | 6635 // using the arguments object. We do not (yet) correctly handle the |
| 6635 // arguments property of the function. | 6636 // arguments property of the function. |
| 6636 if (info()->scope()->arguments() != NULL) { | 6637 if (current_info()->scope()->arguments() != NULL) { |
| 6637 // Parameters will be allocated to context slots. We have no | 6638 // Parameters will be allocated to context slots. We have no |
| 6638 // direct way to detect that the variable is a parameter so we do | 6639 // direct way to detect that the variable is a parameter so we do |
| 6639 // a linear search of the parameter variables. | 6640 // a linear search of the parameter variables. |
| 6640 int count = info()->scope()->num_parameters(); | 6641 int count = current_info()->scope()->num_parameters(); |
| 6641 for (int i = 0; i < count; ++i) { | 6642 for (int i = 0; i < count; ++i) { |
| 6642 if (var == info()->scope()->parameter(i)) { | 6643 if (var == current_info()->scope()->parameter(i)) { |
| 6643 Bailout( | 6644 Bailout( |
| 6644 "assignment to parameter, function uses arguments object"); | 6645 "assignment to parameter, function uses arguments object"); |
| 6645 } | 6646 } |
| 6646 } | 6647 } |
| 6647 } | 6648 } |
| 6648 | 6649 |
| 6649 HStoreContextSlot::Mode mode; | 6650 HStoreContextSlot::Mode mode; |
| 6650 | 6651 |
| 6651 switch (var->mode()) { | 6652 switch (var->mode()) { |
| 6652 case LET: | 6653 case LET: |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6852 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 6853 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
| 6853 HValue* value = Pop(); | 6854 HValue* value = Pop(); |
| 6854 BindIfLive(var, value); | 6855 BindIfLive(var, value); |
| 6855 return ast_context()->ReturnValue(value); | 6856 return ast_context()->ReturnValue(value); |
| 6856 } | 6857 } |
| 6857 | 6858 |
| 6858 case Variable::CONTEXT: { | 6859 case Variable::CONTEXT: { |
| 6859 // Bail out if we try to mutate a parameter value in a function using | 6860 // Bail out if we try to mutate a parameter value in a function using |
| 6860 // the arguments object. We do not (yet) correctly handle the | 6861 // the arguments object. We do not (yet) correctly handle the |
| 6861 // arguments property of the function. | 6862 // arguments property of the function. |
| 6862 if (info()->scope()->arguments() != NULL) { | 6863 if (current_info()->scope()->arguments() != NULL) { |
| 6863 // Parameters will rewrite to context slots. We have no direct way | 6864 // Parameters will rewrite to context slots. We have no direct way |
| 6864 // to detect that the variable is a parameter. | 6865 // to detect that the variable is a parameter. |
| 6865 int count = info()->scope()->num_parameters(); | 6866 int count = current_info()->scope()->num_parameters(); |
| 6866 for (int i = 0; i < count; ++i) { | 6867 for (int i = 0; i < count; ++i) { |
| 6867 if (var == info()->scope()->parameter(i)) { | 6868 if (var == current_info()->scope()->parameter(i)) { |
| 6868 return Bailout("assignment to parameter in arguments object"); | 6869 return Bailout("assignment to parameter in arguments object"); |
| 6869 } | 6870 } |
| 6870 } | 6871 } |
| 6871 } | 6872 } |
| 6872 | 6873 |
| 6873 CHECK_ALIVE(VisitForValue(expr->value())); | 6874 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6874 HStoreContextSlot::Mode mode; | 6875 HStoreContextSlot::Mode mode; |
| 6875 if (expr->op() == Token::ASSIGN) { | 6876 if (expr->op() == Token::ASSIGN) { |
| 6876 switch (var->mode()) { | 6877 switch (var->mode()) { |
| 6877 case LET: | 6878 case LET: |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7019 return new(zone()) HConstant(function, Representation::Tagged()); | 7020 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7020 } | 7021 } |
| 7021 | 7022 |
| 7022 // Handle a load from a known field somewhere in the prototype chain. | 7023 // Handle a load from a known field somewhere in the prototype chain. |
| 7023 LookupInPrototypes(map, name, &lookup); | 7024 LookupInPrototypes(map, name, &lookup); |
| 7024 if (lookup.IsField()) { | 7025 if (lookup.IsField()) { |
| 7025 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7026 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7026 Handle<JSObject> holder(lookup.holder()); | 7027 Handle<JSObject> holder(lookup.holder()); |
| 7027 Handle<Map> holder_map(holder->map()); | 7028 Handle<Map> holder_map(holder->map()); |
| 7028 AddCheckMap(object, map); | 7029 AddCheckMap(object, map); |
| 7029 AddInstruction( | 7030 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7030 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7031 prototype, holder, zone(), top_info())); |
| 7031 HValue* holder_value = AddInstruction(new(zone()) | 7032 HValue* holder_value = AddInstruction(new(zone()) |
| 7032 HConstant(holder, Representation::Tagged())); | 7033 HConstant(holder, Representation::Tagged())); |
| 7033 return BuildLoadNamedField(holder_value, | 7034 return BuildLoadNamedField(holder_value, |
| 7034 HObjectAccess::ForField(holder_map, &lookup, name), | 7035 HObjectAccess::ForField(holder_map, &lookup, name), |
| 7035 ComputeLoadStoreRepresentation(map, &lookup)); | 7036 ComputeLoadStoreRepresentation(map, &lookup)); |
| 7036 } | 7037 } |
| 7037 | 7038 |
| 7038 // Handle a load of a constant function somewhere in the prototype chain. | 7039 // Handle a load of a constant function somewhere in the prototype chain. |
| 7039 if (lookup.IsConstantFunction()) { | 7040 if (lookup.IsConstantFunction()) { |
| 7040 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7041 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7041 Handle<JSObject> holder(lookup.holder()); | 7042 Handle<JSObject> holder(lookup.holder()); |
| 7042 Handle<Map> holder_map(holder->map()); | 7043 Handle<Map> holder_map(holder->map()); |
| 7043 AddCheckMap(object, map); | 7044 AddCheckMap(object, map); |
| 7044 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7045 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7046 prototype, holder, zone(), top_info())); |
| 7045 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 7047 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| 7046 return new(zone()) HConstant(function, Representation::Tagged()); | 7048 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7047 } | 7049 } |
| 7048 | 7050 |
| 7049 // No luck, do a generic load. | 7051 // No luck, do a generic load. |
| 7050 return BuildLoadNamedGeneric(object, name, expr); | 7052 return BuildLoadNamedGeneric(object, name, expr); |
| 7051 } | 7053 } |
| 7052 | 7054 |
| 7053 | 7055 |
| 7054 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 7056 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 7071 if (dependency) { | 7073 if (dependency) { |
| 7072 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 7074 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 7073 } | 7075 } |
| 7074 | 7076 |
| 7075 // Loads from a "stock" fast holey double arrays can elide the hole check. | 7077 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 7076 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 7078 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 7077 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 7079 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 7078 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 7080 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 7079 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 7081 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| 7080 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 7082 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
| 7081 AddInstruction( | 7083 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7082 new(zone()) HCheckPrototypeMaps(prototype, object_prototype, zone())); | 7084 prototype, object_prototype, zone(), top_info())); |
| 7083 load_mode = ALLOW_RETURN_HOLE; | 7085 load_mode = ALLOW_RETURN_HOLE; |
| 7084 graph()->MarkDependsOnEmptyArrayProtoElements(); | 7086 graph()->MarkDependsOnEmptyArrayProtoElements(); |
| 7085 } | 7087 } |
| 7086 | 7088 |
| 7087 return BuildUncheckedMonomorphicElementAccess( | 7089 return BuildUncheckedMonomorphicElementAccess( |
| 7088 object, key, val, | 7090 object, key, val, |
| 7089 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 7091 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
| 7090 map->elements_kind(), is_store, load_mode, store_mode); | 7092 map->elements_kind(), is_store, load_mode, store_mode); |
| 7091 } | 7093 } |
| 7092 | 7094 |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7587 } | 7589 } |
| 7588 instr->set_position(expr->position()); | 7590 instr->set_position(expr->position()); |
| 7589 return ast_context()->ReturnInstruction(instr, expr->id()); | 7591 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7590 } | 7592 } |
| 7591 | 7593 |
| 7592 | 7594 |
| 7593 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7595 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 7594 Handle<Map> receiver_map) { | 7596 Handle<Map> receiver_map) { |
| 7595 if (!holder.is_null()) { | 7597 if (!holder.is_null()) { |
| 7596 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7598 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 7597 AddInstruction( | 7599 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7598 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7600 prototype, holder, zone(), top_info())); |
| 7599 } | 7601 } |
| 7600 } | 7602 } |
| 7601 | 7603 |
| 7602 | 7604 |
| 7603 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 7605 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
| 7604 Handle<JSObject> holder, | 7606 Handle<JSObject> holder, |
| 7605 HValue* receiver, | 7607 HValue* receiver, |
| 7606 Handle<Map> receiver_map) { | 7608 Handle<Map> receiver_map) { |
| 7607 // Constant functions have the nice property that the map will change if they | 7609 // Constant functions have the nice property that the map will change if they |
| 7608 // are overwritten. Therefore it is enough to check the map of the holder and | 7610 // are overwritten. Therefore it is enough to check the map of the holder and |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7733 if (expr->check_type() == NUMBER_CHECK) { | 7735 if (expr->check_type() == NUMBER_CHECK) { |
| 7734 if_true->Goto(number_block); | 7736 if_true->Goto(number_block); |
| 7735 if_true = number_block; | 7737 if_true = number_block; |
| 7736 number_block->SetJoinId(expr->id()); | 7738 number_block->SetJoinId(expr->id()); |
| 7737 } | 7739 } |
| 7738 set_current_block(if_true); | 7740 set_current_block(if_true); |
| 7739 | 7741 |
| 7740 expr->ComputeTarget(map, name); | 7742 expr->ComputeTarget(map, name); |
| 7741 AddCheckPrototypeMaps(expr->holder(), map); | 7743 AddCheckPrototypeMaps(expr->holder(), map); |
| 7742 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 7744 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 7743 Handle<JSFunction> caller = info()->closure(); | 7745 Handle<JSFunction> caller = current_info()->closure(); |
| 7744 SmartArrayPointer<char> caller_name = | 7746 SmartArrayPointer<char> caller_name = |
| 7745 caller->shared()->DebugName()->ToCString(); | 7747 caller->shared()->DebugName()->ToCString(); |
| 7746 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 7748 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 7747 *name->ToCString(), | 7749 *name->ToCString(), |
| 7748 *caller_name); | 7750 *caller_name); |
| 7749 } | 7751 } |
| 7750 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 7752 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
| 7751 // Trying to inline will signal that we should bailout from the | 7753 // Trying to inline will signal that we should bailout from the |
| 7752 // entire compilation by setting stack overflow on the visitor. | 7754 // entire compilation by setting stack overflow on the visitor. |
| 7753 if (HasStackOverflow()) return; | 7755 if (HasStackOverflow()) return; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7817 | 7819 |
| 7818 | 7820 |
| 7819 static const int kNotInlinable = 1000000000; | 7821 static const int kNotInlinable = 1000000000; |
| 7820 | 7822 |
| 7821 | 7823 |
| 7822 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 7824 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
| 7823 if (!FLAG_use_inlining) return kNotInlinable; | 7825 if (!FLAG_use_inlining) return kNotInlinable; |
| 7824 | 7826 |
| 7825 // Precondition: call is monomorphic and we have found a target with the | 7827 // Precondition: call is monomorphic and we have found a target with the |
| 7826 // appropriate arity. | 7828 // appropriate arity. |
| 7827 Handle<JSFunction> caller = info()->closure(); | 7829 Handle<JSFunction> caller = current_info()->closure(); |
| 7828 Handle<SharedFunctionInfo> target_shared(target->shared()); | 7830 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 7829 | 7831 |
| 7830 // Do a quick check on source code length to avoid parsing large | 7832 // Do a quick check on source code length to avoid parsing large |
| 7831 // inlining candidates. | 7833 // inlining candidates. |
| 7832 if (target_shared->SourceSize() > | 7834 if (target_shared->SourceSize() > |
| 7833 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { | 7835 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { |
| 7834 TraceInline(target, caller, "target text too big"); | 7836 TraceInline(target, caller, "target text too big"); |
| 7835 return kNotInlinable; | 7837 return kNotInlinable; |
| 7836 } | 7838 } |
| 7837 | 7839 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7853 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, | 7855 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, |
| 7854 Handle<JSFunction> target, | 7856 Handle<JSFunction> target, |
| 7855 int arguments_count, | 7857 int arguments_count, |
| 7856 HValue* implicit_return_value, | 7858 HValue* implicit_return_value, |
| 7857 BailoutId ast_id, | 7859 BailoutId ast_id, |
| 7858 BailoutId return_id, | 7860 BailoutId return_id, |
| 7859 InliningKind inlining_kind) { | 7861 InliningKind inlining_kind) { |
| 7860 int nodes_added = InliningAstSize(target); | 7862 int nodes_added = InliningAstSize(target); |
| 7861 if (nodes_added == kNotInlinable) return false; | 7863 if (nodes_added == kNotInlinable) return false; |
| 7862 | 7864 |
| 7863 Handle<JSFunction> caller = info()->closure(); | 7865 Handle<JSFunction> caller = current_info()->closure(); |
| 7864 | 7866 |
| 7865 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 7867 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 7866 TraceInline(target, caller, "target AST is too large [early]"); | 7868 TraceInline(target, caller, "target AST is too large [early]"); |
| 7867 return false; | 7869 return false; |
| 7868 } | 7870 } |
| 7869 | 7871 |
| 7870 #if !defined(V8_TARGET_ARCH_IA32) | 7872 #if !defined(V8_TARGET_ARCH_IA32) |
| 7871 // Target must be able to use caller's context. | 7873 // Target must be able to use caller's context. |
| 7872 CompilationInfo* outer_info = info(); | 7874 CompilationInfo* outer_info = current_info(); |
| 7873 if (target->context() != outer_info->closure()->context() || | 7875 if (target->context() != outer_info->closure()->context() || |
| 7874 outer_info->scope()->contains_with() || | 7876 outer_info->scope()->contains_with() || |
| 7875 outer_info->scope()->num_heap_slots() > 0) { | 7877 outer_info->scope()->num_heap_slots() > 0) { |
| 7876 TraceInline(target, caller, "target requires context change"); | 7878 TraceInline(target, caller, "target requires context change"); |
| 7877 return false; | 7879 return false; |
| 7878 } | 7880 } |
| 7879 #endif | 7881 #endif |
| 7880 | 7882 |
| 7881 | 7883 |
| 7882 // Don't inline deeper than kMaxInliningLevels calls. | 7884 // Don't inline deeper than kMaxInliningLevels calls. |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8297 case kStringCharAt: | 8299 case kStringCharAt: |
| 8298 if (argument_count == 2 && check_type == STRING_CHECK) { | 8300 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 8299 HValue* index = Pop(); | 8301 HValue* index = Pop(); |
| 8300 HValue* string = Pop(); | 8302 HValue* string = Pop(); |
| 8301 HValue* context = environment()->LookupContext(); | 8303 HValue* context = environment()->LookupContext(); |
| 8302 ASSERT(!expr->holder().is_null()); | 8304 ASSERT(!expr->holder().is_null()); |
| 8303 AddInstruction(new(zone()) HCheckPrototypeMaps( | 8305 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 8304 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, | 8306 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, |
| 8305 expr->holder()->GetIsolate()), | 8307 expr->holder()->GetIsolate()), |
| 8306 expr->holder(), | 8308 expr->holder(), |
| 8307 zone())); | 8309 zone(), |
| 8310 top_info())); |
| 8308 HInstruction* char_code = | 8311 HInstruction* char_code = |
| 8309 BuildStringCharCodeAt(context, string, index); | 8312 BuildStringCharCodeAt(context, string, index); |
| 8310 if (id == kStringCharCodeAt) { | 8313 if (id == kStringCharCodeAt) { |
| 8311 ast_context()->ReturnInstruction(char_code, expr->id()); | 8314 ast_context()->ReturnInstruction(char_code, expr->id()); |
| 8312 return true; | 8315 return true; |
| 8313 } | 8316 } |
| 8314 AddInstruction(char_code); | 8317 AddInstruction(char_code); |
| 8315 HInstruction* result = | 8318 HInstruction* result = |
| 8316 HStringCharFromCode::New(zone(), context, char_code); | 8319 HStringCharFromCode::New(zone(), context, char_code); |
| 8317 ast_context()->ReturnInstruction(result, expr->id()); | 8320 ast_context()->ReturnInstruction(result, expr->id()); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8448 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 8451 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 8449 return false; | 8452 return false; |
| 8450 } | 8453 } |
| 8451 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 8454 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 8452 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 8455 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 8453 !expr->target()->shared()->HasBuiltinFunctionId() || | 8456 !expr->target()->shared()->HasBuiltinFunctionId() || |
| 8454 expr->target()->shared()->builtin_function_id() != kFunctionApply) { | 8457 expr->target()->shared()->builtin_function_id() != kFunctionApply) { |
| 8455 return false; | 8458 return false; |
| 8456 } | 8459 } |
| 8457 | 8460 |
| 8458 if (info()->scope()->arguments() == NULL) return false; | 8461 if (current_info()->scope()->arguments() == NULL) return false; |
| 8459 | 8462 |
| 8460 ZoneList<Expression*>* args = expr->arguments(); | 8463 ZoneList<Expression*>* args = expr->arguments(); |
| 8461 if (args->length() != 2) return false; | 8464 if (args->length() != 2) return false; |
| 8462 | 8465 |
| 8463 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 8466 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 8464 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 8467 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 8465 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | 8468 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 8466 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 8469 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 8467 | 8470 |
| 8468 // Found pattern f.apply(receiver, arguments). | 8471 // Found pattern f.apply(receiver, arguments). |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8689 | 8692 |
| 8690 if (global_call) { | 8693 if (global_call) { |
| 8691 Variable* var = proxy->var(); | 8694 Variable* var = proxy->var(); |
| 8692 bool known_global_function = false; | 8695 bool known_global_function = false; |
| 8693 // If there is a global property cell for the name at compile time and | 8696 // If there is a global property cell for the name at compile time and |
| 8694 // access check is not enabled we assume that the function will not change | 8697 // access check is not enabled we assume that the function will not change |
| 8695 // and generate optimized code for calling the function. | 8698 // and generate optimized code for calling the function. |
| 8696 LookupResult lookup(isolate()); | 8699 LookupResult lookup(isolate()); |
| 8697 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 8700 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 8698 if (type == kUseCell && | 8701 if (type == kUseCell && |
| 8699 !info()->global_object()->IsAccessCheckNeeded()) { | 8702 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 8700 Handle<GlobalObject> global(info()->global_object()); | 8703 Handle<GlobalObject> global(current_info()->global_object()); |
| 8701 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 8704 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 8702 } | 8705 } |
| 8703 if (known_global_function) { | 8706 if (known_global_function) { |
| 8704 // Push the global object instead of the global receiver because | 8707 // Push the global object instead of the global receiver because |
| 8705 // code generated by the full code generator expects it. | 8708 // code generated by the full code generator expects it. |
| 8706 HValue* context = environment()->LookupContext(); | 8709 HValue* context = environment()->LookupContext(); |
| 8707 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 8710 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 8708 PushAndAdd(global_object); | 8711 PushAndAdd(global_object); |
| 8709 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8712 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8710 | 8713 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 8725 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. | 8728 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. |
| 8726 if (FLAG_trace_inlining) { | 8729 if (FLAG_trace_inlining) { |
| 8727 PrintF("Inlining builtin "); | 8730 PrintF("Inlining builtin "); |
| 8728 expr->target()->ShortPrint(); | 8731 expr->target()->ShortPrint(); |
| 8729 PrintF("\n"); | 8732 PrintF("\n"); |
| 8730 } | 8733 } |
| 8731 return; | 8734 return; |
| 8732 } | 8735 } |
| 8733 if (TryInlineCall(expr)) return; | 8736 if (TryInlineCall(expr)) return; |
| 8734 | 8737 |
| 8735 if (expr->target().is_identical_to(info()->closure())) { | 8738 if (expr->target().is_identical_to(current_info()->closure())) { |
| 8736 graph()->MarkRecursive(); | 8739 graph()->MarkRecursive(); |
| 8737 } | 8740 } |
| 8738 | 8741 |
| 8739 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 8742 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 8740 argument_count)); | 8743 argument_count)); |
| 8741 } else { | 8744 } else { |
| 8742 HValue* context = environment()->LookupContext(); | 8745 HValue* context = environment()->LookupContext(); |
| 8743 HGlobalObject* receiver = new(zone()) HGlobalObject(context); | 8746 HGlobalObject* receiver = new(zone()) HGlobalObject(context); |
| 8744 AddInstruction(receiver); | 8747 AddInstruction(receiver); |
| 8745 PushAndAdd(new(zone()) HPushArgument(receiver)); | 8748 PushAndAdd(new(zone()) HPushArgument(receiver)); |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9224 | 9227 |
| 9225 case Variable::PARAMETER: | 9228 case Variable::PARAMETER: |
| 9226 case Variable::LOCAL: | 9229 case Variable::LOCAL: |
| 9227 BindIfLive(var, after); | 9230 BindIfLive(var, after); |
| 9228 break; | 9231 break; |
| 9229 | 9232 |
| 9230 case Variable::CONTEXT: { | 9233 case Variable::CONTEXT: { |
| 9231 // Bail out if we try to mutate a parameter value in a function | 9234 // Bail out if we try to mutate a parameter value in a function |
| 9232 // using the arguments object. We do not (yet) correctly handle the | 9235 // using the arguments object. We do not (yet) correctly handle the |
| 9233 // arguments property of the function. | 9236 // arguments property of the function. |
| 9234 if (info()->scope()->arguments() != NULL) { | 9237 if (current_info()->scope()->arguments() != NULL) { |
| 9235 // Parameters will rewrite to context slots. We have no direct | 9238 // Parameters will rewrite to context slots. We have no direct |
| 9236 // way to detect that the variable is a parameter so we use a | 9239 // way to detect that the variable is a parameter so we use a |
| 9237 // linear search of the parameter list. | 9240 // linear search of the parameter list. |
| 9238 int count = info()->scope()->num_parameters(); | 9241 int count = current_info()->scope()->num_parameters(); |
| 9239 for (int i = 0; i < count; ++i) { | 9242 for (int i = 0; i < count; ++i) { |
| 9240 if (var == info()->scope()->parameter(i)) { | 9243 if (var == current_info()->scope()->parameter(i)) { |
| 9241 return Bailout("assignment to parameter in arguments object"); | 9244 return Bailout("assignment to parameter in arguments object"); |
| 9242 } | 9245 } |
| 9243 } | 9246 } |
| 9244 } | 9247 } |
| 9245 | 9248 |
| 9246 HValue* context = BuildContextChainWalk(var); | 9249 HValue* context = BuildContextChainWalk(var); |
| 9247 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 9250 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
| 9248 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 9251 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
| 9249 HStoreContextSlot* instr = | 9252 HStoreContextSlot* instr = |
| 9250 new(zone()) HStoreContextSlot(context, var->index(), mode, after); | 9253 new(zone()) HStoreContextSlot(context, var->index(), mode, after); |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9829 } | 9832 } |
| 9830 | 9833 |
| 9831 if (op == Token::INSTANCEOF) { | 9834 if (op == Token::INSTANCEOF) { |
| 9832 // Check to see if the rhs of the instanceof is a global function not | 9835 // Check to see if the rhs of the instanceof is a global function not |
| 9833 // residing in new space. If it is we assume that the function will stay the | 9836 // residing in new space. If it is we assume that the function will stay the |
| 9834 // same. | 9837 // same. |
| 9835 Handle<JSFunction> target = Handle<JSFunction>::null(); | 9838 Handle<JSFunction> target = Handle<JSFunction>::null(); |
| 9836 VariableProxy* proxy = expr->right()->AsVariableProxy(); | 9839 VariableProxy* proxy = expr->right()->AsVariableProxy(); |
| 9837 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); | 9840 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); |
| 9838 if (global_function && | 9841 if (global_function && |
| 9839 info()->has_global_object() && | 9842 current_info()->has_global_object() && |
| 9840 !info()->global_object()->IsAccessCheckNeeded()) { | 9843 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 9841 Handle<String> name = proxy->name(); | 9844 Handle<String> name = proxy->name(); |
| 9842 Handle<GlobalObject> global(info()->global_object()); | 9845 Handle<GlobalObject> global(current_info()->global_object()); |
| 9843 LookupResult lookup(isolate()); | 9846 LookupResult lookup(isolate()); |
| 9844 global->Lookup(*name, &lookup); | 9847 global->Lookup(*name, &lookup); |
| 9845 if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) { | 9848 if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) { |
| 9846 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); | 9849 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); |
| 9847 // If the function is in new space we assume it's more likely to | 9850 // If the function is in new space we assume it's more likely to |
| 9848 // change and thus prefer the general IC code. | 9851 // change and thus prefer the general IC code. |
| 9849 if (!isolate()->heap()->InNewSpace(*candidate)) { | 9852 if (!isolate()->heap()->InNewSpace(*candidate)) { |
| 9850 target = candidate; | 9853 target = candidate; |
| 9851 } | 9854 } |
| 9852 } | 9855 } |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10275 | 10278 |
| 10276 | 10279 |
| 10277 void HOptimizedGraphBuilder::VisitDeclarations( | 10280 void HOptimizedGraphBuilder::VisitDeclarations( |
| 10278 ZoneList<Declaration*>* declarations) { | 10281 ZoneList<Declaration*>* declarations) { |
| 10279 ASSERT(globals_.is_empty()); | 10282 ASSERT(globals_.is_empty()); |
| 10280 AstVisitor::VisitDeclarations(declarations); | 10283 AstVisitor::VisitDeclarations(declarations); |
| 10281 if (!globals_.is_empty()) { | 10284 if (!globals_.is_empty()) { |
| 10282 Handle<FixedArray> array = | 10285 Handle<FixedArray> array = |
| 10283 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 10286 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
| 10284 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 10287 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
| 10285 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 10288 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | |
| 10286 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 10289 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | |
| 10287 DeclareGlobalsLanguageMode::encode(info()->language_mode()); | 10290 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); |
| 10288 HInstruction* result = new(zone()) HDeclareGlobals( | 10291 HInstruction* result = new(zone()) HDeclareGlobals( |
| 10289 environment()->LookupContext(), array, flags); | 10292 environment()->LookupContext(), array, flags); |
| 10290 AddInstruction(result); | 10293 AddInstruction(result); |
| 10291 globals_.Clear(); | 10294 globals_.Clear(); |
| 10292 } | 10295 } |
| 10293 } | 10296 } |
| 10294 | 10297 |
| 10295 | 10298 |
| 10296 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 10299 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
| 10297 VariableDeclaration* declaration) { | 10300 VariableDeclaration* declaration) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10331 } | 10334 } |
| 10332 | 10335 |
| 10333 | 10336 |
| 10334 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 10337 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
| 10335 FunctionDeclaration* declaration) { | 10338 FunctionDeclaration* declaration) { |
| 10336 VariableProxy* proxy = declaration->proxy(); | 10339 VariableProxy* proxy = declaration->proxy(); |
| 10337 Variable* variable = proxy->var(); | 10340 Variable* variable = proxy->var(); |
| 10338 switch (variable->location()) { | 10341 switch (variable->location()) { |
| 10339 case Variable::UNALLOCATED: { | 10342 case Variable::UNALLOCATED: { |
| 10340 globals_.Add(variable->name(), zone()); | 10343 globals_.Add(variable->name(), zone()); |
| 10341 Handle<SharedFunctionInfo> function = | 10344 Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo( |
| 10342 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); | 10345 declaration->fun(), current_info()->script()); |
| 10343 // Check for stack-overflow exception. | 10346 // Check for stack-overflow exception. |
| 10344 if (function.is_null()) return SetStackOverflow(); | 10347 if (function.is_null()) return SetStackOverflow(); |
| 10345 globals_.Add(function, zone()); | 10348 globals_.Add(function, zone()); |
| 10346 return; | 10349 return; |
| 10347 } | 10350 } |
| 10348 case Variable::PARAMETER: | 10351 case Variable::PARAMETER: |
| 10349 case Variable::LOCAL: { | 10352 case Variable::LOCAL: { |
| 10350 CHECK_ALIVE(VisitForValue(declaration->fun())); | 10353 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 10351 HValue* value = Pop(); | 10354 HValue* value = Pop(); |
| 10352 BindIfLive(variable, value); | 10355 BindIfLive(variable, value); |
| (...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11613 } | 11616 } |
| 11614 } | 11617 } |
| 11615 | 11618 |
| 11616 #ifdef DEBUG | 11619 #ifdef DEBUG |
| 11617 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11620 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11618 if (allocator_ != NULL) allocator_->Verify(); | 11621 if (allocator_ != NULL) allocator_->Verify(); |
| 11619 #endif | 11622 #endif |
| 11620 } | 11623 } |
| 11621 | 11624 |
| 11622 } } // namespace v8::internal | 11625 } } // namespace v8::internal |
| OLD | NEW |