| 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 3789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3800 | 3800 |
| 3801 | 3801 |
| 3802 #define CHECK_ALIVE(call) \ | 3802 #define CHECK_ALIVE(call) \ |
| 3803 do { \ | 3803 do { \ |
| 3804 call; \ | 3804 call; \ |
| 3805 if (HasStackOverflow() || current_block() == NULL) return; \ | 3805 if (HasStackOverflow() || current_block() == NULL) return; \ |
| 3806 } while (false) | 3806 } while (false) |
| 3807 | 3807 |
| 3808 | 3808 |
| 3809 void HOptimizedGraphBuilder::Bailout(const char* reason) { | 3809 void HOptimizedGraphBuilder::Bailout(const char* reason) { |
| 3810 current_info()->set_bailout_reason(reason); | 3810 info()->set_bailout_reason(reason); |
| 3811 SetStackOverflow(); | 3811 SetStackOverflow(); |
| 3812 } | 3812 } |
| 3813 | 3813 |
| 3814 | 3814 |
| 3815 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 3815 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
| 3816 EffectContext for_effect(this); | 3816 EffectContext for_effect(this); |
| 3817 Visit(expr); | 3817 Visit(expr); |
| 3818 } | 3818 } |
| 3819 | 3819 |
| 3820 | 3820 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3857 | 3857 |
| 3858 void HOptimizedGraphBuilder::VisitExpressions( | 3858 void HOptimizedGraphBuilder::VisitExpressions( |
| 3859 ZoneList<Expression*>* exprs) { | 3859 ZoneList<Expression*>* exprs) { |
| 3860 for (int i = 0; i < exprs->length(); ++i) { | 3860 for (int i = 0; i < exprs->length(); ++i) { |
| 3861 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 3861 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
| 3862 } | 3862 } |
| 3863 } | 3863 } |
| 3864 | 3864 |
| 3865 | 3865 |
| 3866 bool HOptimizedGraphBuilder::BuildGraph() { | 3866 bool HOptimizedGraphBuilder::BuildGraph() { |
| 3867 if (current_info()->function()->is_generator()) { | 3867 if (info()->function()->is_generator()) { |
| 3868 Bailout("function is a generator"); | 3868 Bailout("function is a generator"); |
| 3869 return false; | 3869 return false; |
| 3870 } | 3870 } |
| 3871 Scope* scope = current_info()->scope(); | 3871 Scope* scope = info()->scope(); |
| 3872 if (scope->HasIllegalRedeclaration()) { | 3872 if (scope->HasIllegalRedeclaration()) { |
| 3873 Bailout("function with illegal redeclaration"); | 3873 Bailout("function with illegal redeclaration"); |
| 3874 return false; | 3874 return false; |
| 3875 } | 3875 } |
| 3876 if (scope->calls_eval()) { | 3876 if (scope->calls_eval()) { |
| 3877 Bailout("function calls eval"); | 3877 Bailout("function calls eval"); |
| 3878 return false; | 3878 return false; |
| 3879 } | 3879 } |
| 3880 SetUpScope(scope); | 3880 SetUpScope(scope); |
| 3881 | 3881 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3905 if (scope->is_function_scope() && scope->function() != NULL) { | 3905 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3906 VisitVariableDeclaration(scope->function()); | 3906 VisitVariableDeclaration(scope->function()); |
| 3907 } | 3907 } |
| 3908 VisitDeclarations(scope->declarations()); | 3908 VisitDeclarations(scope->declarations()); |
| 3909 AddSimulate(BailoutId::Declarations()); | 3909 AddSimulate(BailoutId::Declarations()); |
| 3910 | 3910 |
| 3911 HValue* context = environment()->LookupContext(); | 3911 HValue* context = environment()->LookupContext(); |
| 3912 AddInstruction( | 3912 AddInstruction( |
| 3913 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); | 3913 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); |
| 3914 | 3914 |
| 3915 VisitStatements(current_info()->function()->body()); | 3915 VisitStatements(info()->function()->body()); |
| 3916 if (HasStackOverflow()) return false; | 3916 if (HasStackOverflow()) return false; |
| 3917 | 3917 |
| 3918 if (current_block() != NULL) { | 3918 if (current_block() != NULL) { |
| 3919 AddReturn(graph()->GetConstantUndefined()); | 3919 AddReturn(graph()->GetConstantUndefined()); |
| 3920 set_current_block(NULL); | 3920 set_current_block(NULL); |
| 3921 } | 3921 } |
| 3922 | 3922 |
| 3923 // If the checksum of the number of type info changes is the same as the | 3923 // If the checksum of the number of type info changes is the same as the |
| 3924 // last time this function was compiled, then this recompile is likely not | 3924 // last time this function was compiled, then this recompile is likely not |
| 3925 // due to missing/inadequate type feedback, but rather too aggressive | 3925 // due to missing/inadequate type feedback, but rather too aggressive |
| 3926 // optimization. Disable optimistic LICM in that case. | 3926 // optimization. Disable optimistic LICM in that case. |
| 3927 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 3927 Handle<Code> unoptimized_code(info()->shared_info()->code()); |
| 3928 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 3928 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 3929 Handle<TypeFeedbackInfo> type_info( | 3929 Handle<TypeFeedbackInfo> type_info( |
| 3930 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 3930 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
| 3931 int checksum = type_info->own_type_change_checksum(); | 3931 int checksum = type_info->own_type_change_checksum(); |
| 3932 int composite_checksum = graph()->update_type_change_checksum(checksum); | 3932 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3933 graph()->set_use_optimistic_licm( | 3933 graph()->set_use_optimistic_licm( |
| 3934 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 3934 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3935 type_info->set_inlined_type_change_checksum(composite_checksum); | 3935 type_info->set_inlined_type_change_checksum(composite_checksum); |
| 3936 | 3936 |
| 3937 return true; | 3937 return true; |
| (...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5106 } else { | 5106 } else { |
| 5107 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 5107 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
| 5108 if (last_block != NULL) last_block->Goto(break_block); | 5108 if (last_block != NULL) last_block->Goto(break_block); |
| 5109 break_block->SetJoinId(stmt->ExitId()); | 5109 break_block->SetJoinId(stmt->ExitId()); |
| 5110 set_current_block(break_block); | 5110 set_current_block(break_block); |
| 5111 } | 5111 } |
| 5112 } | 5112 } |
| 5113 | 5113 |
| 5114 | 5114 |
| 5115 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | 5115 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { |
| 5116 return statement->OsrEntryId() == current_info()->osr_ast_id(); | 5116 return statement->OsrEntryId() == info()->osr_ast_id(); |
| 5117 } | 5117 } |
| 5118 | 5118 |
| 5119 | 5119 |
| 5120 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 5120 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
| 5121 if (!HasOsrEntryAt(statement)) return false; | 5121 if (!HasOsrEntryAt(statement)) return false; |
| 5122 | 5122 |
| 5123 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 5123 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
| 5124 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 5124 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
| 5125 HValue* true_value = graph()->GetConstantTrue(); | 5125 HValue* true_value = graph()->GetConstantTrue(); |
| 5126 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | 5126 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... |
| 5493 | 5493 |
| 5494 return Handle<SharedFunctionInfo>(); | 5494 return Handle<SharedFunctionInfo>(); |
| 5495 } | 5495 } |
| 5496 | 5496 |
| 5497 | 5497 |
| 5498 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 5498 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 5499 ASSERT(!HasStackOverflow()); | 5499 ASSERT(!HasStackOverflow()); |
| 5500 ASSERT(current_block() != NULL); | 5500 ASSERT(current_block() != NULL); |
| 5501 ASSERT(current_block()->HasPredecessor()); | 5501 ASSERT(current_block()->HasPredecessor()); |
| 5502 Handle<SharedFunctionInfo> shared_info = | 5502 Handle<SharedFunctionInfo> shared_info = |
| 5503 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); | 5503 SearchSharedFunctionInfo(info()->shared_info()->code(), expr); |
| 5504 if (shared_info.is_null()) { | 5504 if (shared_info.is_null()) { |
| 5505 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); | 5505 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
| 5506 } | 5506 } |
| 5507 // We also have a stack overflow if the recursive compilation did. | 5507 // We also have a stack overflow if the recursive compilation did. |
| 5508 if (HasStackOverflow()) return; | 5508 if (HasStackOverflow()) return; |
| 5509 HValue* context = environment()->LookupContext(); | 5509 HValue* context = environment()->LookupContext(); |
| 5510 HFunctionLiteral* instr = | 5510 HFunctionLiteral* instr = |
| 5511 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 5511 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
| 5512 return ast_context()->ReturnInstruction(instr, expr->id()); | 5512 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5513 } | 5513 } |
| 5514 | 5514 |
| 5515 | 5515 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5556 if (join != NULL && !ast_context()->IsEffect()) { | 5556 if (join != NULL && !ast_context()->IsEffect()) { |
| 5557 return ast_context()->ReturnValue(Pop()); | 5557 return ast_context()->ReturnValue(Pop()); |
| 5558 } | 5558 } |
| 5559 } | 5559 } |
| 5560 } | 5560 } |
| 5561 | 5561 |
| 5562 | 5562 |
| 5563 HOptimizedGraphBuilder::GlobalPropertyAccess | 5563 HOptimizedGraphBuilder::GlobalPropertyAccess |
| 5564 HOptimizedGraphBuilder::LookupGlobalProperty( | 5564 HOptimizedGraphBuilder::LookupGlobalProperty( |
| 5565 Variable* var, LookupResult* lookup, bool is_store) { | 5565 Variable* var, LookupResult* lookup, bool is_store) { |
| 5566 if (var->is_this() || !current_info()->has_global_object()) { | 5566 if (var->is_this() || !info()->has_global_object()) { |
| 5567 return kUseGeneric; | 5567 return kUseGeneric; |
| 5568 } | 5568 } |
| 5569 Handle<GlobalObject> global(current_info()->global_object()); | 5569 Handle<GlobalObject> global(info()->global_object()); |
| 5570 global->Lookup(*var->name(), lookup); | 5570 global->Lookup(*var->name(), lookup); |
| 5571 if (!lookup->IsNormal() || | 5571 if (!lookup->IsNormal() || |
| 5572 (is_store && lookup->IsReadOnly()) || | 5572 (is_store && lookup->IsReadOnly()) || |
| 5573 lookup->holder() != *global) { | 5573 lookup->holder() != *global) { |
| 5574 return kUseGeneric; | 5574 return kUseGeneric; |
| 5575 } | 5575 } |
| 5576 | 5576 |
| 5577 return kUseCell; | 5577 return kUseCell; |
| 5578 } | 5578 } |
| 5579 | 5579 |
| 5580 | 5580 |
| 5581 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5581 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 5582 ASSERT(var->IsContextSlot()); | 5582 ASSERT(var->IsContextSlot()); |
| 5583 HValue* context = environment()->LookupContext(); | 5583 HValue* context = environment()->LookupContext(); |
| 5584 int length = current_info()->scope()->ContextChainLength(var->scope()); | 5584 int length = info()->scope()->ContextChainLength(var->scope()); |
| 5585 while (length-- > 0) { | 5585 while (length-- > 0) { |
| 5586 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 5586 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
| 5587 AddInstruction(context_instruction); | 5587 AddInstruction(context_instruction); |
| 5588 context = context_instruction; | 5588 context = context_instruction; |
| 5589 } | 5589 } |
| 5590 return context; | 5590 return context; |
| 5591 } | 5591 } |
| 5592 | 5592 |
| 5593 | 5593 |
| 5594 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5594 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5610 HConstant* instr = | 5610 HConstant* instr = |
| 5611 new(zone()) HConstant(constant_value, Representation::Tagged()); | 5611 new(zone()) HConstant(constant_value, Representation::Tagged()); |
| 5612 return ast_context()->ReturnInstruction(instr, expr->id()); | 5612 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5613 } | 5613 } |
| 5614 | 5614 |
| 5615 LookupResult lookup(isolate()); | 5615 LookupResult lookup(isolate()); |
| 5616 GlobalPropertyAccess type = | 5616 GlobalPropertyAccess type = |
| 5617 LookupGlobalProperty(variable, &lookup, false); | 5617 LookupGlobalProperty(variable, &lookup, false); |
| 5618 | 5618 |
| 5619 if (type == kUseCell && | 5619 if (type == kUseCell && |
| 5620 current_info()->global_object()->IsAccessCheckNeeded()) { | 5620 info()->global_object()->IsAccessCheckNeeded()) { |
| 5621 type = kUseGeneric; | 5621 type = kUseGeneric; |
| 5622 } | 5622 } |
| 5623 | 5623 |
| 5624 if (type == kUseCell) { | 5624 if (type == kUseCell) { |
| 5625 Handle<GlobalObject> global(current_info()->global_object()); | 5625 Handle<GlobalObject> global(info()->global_object()); |
| 5626 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5626 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5627 HLoadGlobalCell* instr = | 5627 HLoadGlobalCell* instr = |
| 5628 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); | 5628 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); |
| 5629 return ast_context()->ReturnInstruction(instr, expr->id()); | 5629 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5630 } else { | 5630 } else { |
| 5631 HValue* context = environment()->LookupContext(); | 5631 HValue* context = environment()->LookupContext(); |
| 5632 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5632 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 5633 AddInstruction(global_object); | 5633 AddInstruction(global_object); |
| 5634 HLoadGlobalGeneric* instr = | 5634 HLoadGlobalGeneric* instr = |
| 5635 new(zone()) HLoadGlobalGeneric(context, | 5635 new(zone()) HLoadGlobalGeneric(context, |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6206 // Otherwise, find the top prototype. | 6206 // Otherwise, find the top prototype. |
| 6207 while (proto->GetPrototype(isolate())->IsJSObject()) { | 6207 while (proto->GetPrototype(isolate())->IsJSObject()) { |
| 6208 proto = proto->GetPrototype(isolate()); | 6208 proto = proto->GetPrototype(isolate()); |
| 6209 } | 6209 } |
| 6210 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 6210 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
| 6211 } | 6211 } |
| 6212 ASSERT(proto->IsJSObject()); | 6212 ASSERT(proto->IsJSObject()); |
| 6213 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6213 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 6214 Handle<JSObject>(JSObject::cast(map->prototype())), | 6214 Handle<JSObject>(JSObject::cast(map->prototype())), |
| 6215 Handle<JSObject>(JSObject::cast(proto)), | 6215 Handle<JSObject>(JSObject::cast(proto)), |
| 6216 zone(), | 6216 zone())); |
| 6217 top_info())); | |
| 6218 } | 6217 } |
| 6219 | 6218 |
| 6220 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 6219 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
| 6221 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | 6220 Representation representation = ComputeLoadStoreRepresentation(map, lookup); |
| 6222 bool transition_to_field = lookup->IsTransitionToField(*map); | 6221 bool transition_to_field = lookup->IsTransitionToField(*map); |
| 6223 | 6222 |
| 6224 HStoreNamedField *instr; | 6223 HStoreNamedField *instr; |
| 6225 if (FLAG_track_double_fields && representation.IsDouble()) { | 6224 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 6226 if (transition_to_field) { | 6225 if (transition_to_field) { |
| 6227 // The store requires a mutable HeapNumber to be allocated. | 6226 // The store requires a mutable HeapNumber to be allocated. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6243 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); | 6242 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); |
| 6244 } | 6243 } |
| 6245 } else { | 6244 } else { |
| 6246 // This is a non-double store. | 6245 // This is a non-double store. |
| 6247 instr = new(zone()) HStoreNamedField( | 6246 instr = new(zone()) HStoreNamedField( |
| 6248 object, field_access, value, representation); | 6247 object, field_access, value, representation); |
| 6249 } | 6248 } |
| 6250 | 6249 |
| 6251 if (transition_to_field) { | 6250 if (transition_to_field) { |
| 6252 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 6251 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 6253 instr->SetTransition(transition, top_info()); | 6252 instr->set_transition(transition); |
| 6254 // TODO(fschneider): Record the new map type of the object in the IR to | 6253 // TODO(fschneider): Record the new map type of the object in the IR to |
| 6255 // enable elimination of redundant checks after the transition store. | 6254 // enable elimination of redundant checks after the transition store. |
| 6256 instr->SetGVNFlag(kChangesMaps); | 6255 instr->SetGVNFlag(kChangesMaps); |
| 6257 } | 6256 } |
| 6258 return instr; | 6257 return instr; |
| 6259 } | 6258 } |
| 6260 | 6259 |
| 6261 | 6260 |
| 6262 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 6261 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( |
| 6263 HValue* object, | 6262 HValue* object, |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6546 // superclass of Assignment and CountOperation, we cannot just pass the | 6545 // superclass of Assignment and CountOperation, we cannot just pass the |
| 6547 // owning expression instead of position and ast_id separately. | 6546 // owning expression instead of position and ast_id separately. |
| 6548 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6547 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6549 Variable* var, | 6548 Variable* var, |
| 6550 HValue* value, | 6549 HValue* value, |
| 6551 int position, | 6550 int position, |
| 6552 BailoutId ast_id) { | 6551 BailoutId ast_id) { |
| 6553 LookupResult lookup(isolate()); | 6552 LookupResult lookup(isolate()); |
| 6554 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 6553 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 6555 if (type == kUseCell) { | 6554 if (type == kUseCell) { |
| 6556 Handle<GlobalObject> global(current_info()->global_object()); | 6555 Handle<GlobalObject> global(info()->global_object()); |
| 6557 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 6556 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 6558 HInstruction* instr = | 6557 HInstruction* instr = |
| 6559 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 6558 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
| 6560 instr->set_position(position); | 6559 instr->set_position(position); |
| 6561 AddInstruction(instr); | 6560 AddInstruction(instr); |
| 6562 if (instr->HasObservableSideEffects()) { | 6561 if (instr->HasObservableSideEffects()) { |
| 6563 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 6562 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 6564 } | 6563 } |
| 6565 } else { | 6564 } else { |
| 6566 HValue* context = environment()->LookupContext(); | 6565 HValue* context = environment()->LookupContext(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6611 if (var->mode() == CONST) { | 6610 if (var->mode() == CONST) { |
| 6612 return Bailout("unsupported const compound assignment"); | 6611 return Bailout("unsupported const compound assignment"); |
| 6613 } | 6612 } |
| 6614 BindIfLive(var, Top()); | 6613 BindIfLive(var, Top()); |
| 6615 break; | 6614 break; |
| 6616 | 6615 |
| 6617 case Variable::CONTEXT: { | 6616 case Variable::CONTEXT: { |
| 6618 // Bail out if we try to mutate a parameter value in a function | 6617 // Bail out if we try to mutate a parameter value in a function |
| 6619 // using the arguments object. We do not (yet) correctly handle the | 6618 // using the arguments object. We do not (yet) correctly handle the |
| 6620 // arguments property of the function. | 6619 // arguments property of the function. |
| 6621 if (current_info()->scope()->arguments() != NULL) { | 6620 if (info()->scope()->arguments() != NULL) { |
| 6622 // Parameters will be allocated to context slots. We have no | 6621 // Parameters will be allocated to context slots. We have no |
| 6623 // direct way to detect that the variable is a parameter so we do | 6622 // direct way to detect that the variable is a parameter so we do |
| 6624 // a linear search of the parameter variables. | 6623 // a linear search of the parameter variables. |
| 6625 int count = current_info()->scope()->num_parameters(); | 6624 int count = info()->scope()->num_parameters(); |
| 6626 for (int i = 0; i < count; ++i) { | 6625 for (int i = 0; i < count; ++i) { |
| 6627 if (var == current_info()->scope()->parameter(i)) { | 6626 if (var == info()->scope()->parameter(i)) { |
| 6628 Bailout( | 6627 Bailout( |
| 6629 "assignment to parameter, function uses arguments object"); | 6628 "assignment to parameter, function uses arguments object"); |
| 6630 } | 6629 } |
| 6631 } | 6630 } |
| 6632 } | 6631 } |
| 6633 | 6632 |
| 6634 HStoreContextSlot::Mode mode; | 6633 HStoreContextSlot::Mode mode; |
| 6635 | 6634 |
| 6636 switch (var->mode()) { | 6635 switch (var->mode()) { |
| 6637 case LET: | 6636 case LET: |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6837 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 6836 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
| 6838 HValue* value = Pop(); | 6837 HValue* value = Pop(); |
| 6839 BindIfLive(var, value); | 6838 BindIfLive(var, value); |
| 6840 return ast_context()->ReturnValue(value); | 6839 return ast_context()->ReturnValue(value); |
| 6841 } | 6840 } |
| 6842 | 6841 |
| 6843 case Variable::CONTEXT: { | 6842 case Variable::CONTEXT: { |
| 6844 // Bail out if we try to mutate a parameter value in a function using | 6843 // Bail out if we try to mutate a parameter value in a function using |
| 6845 // the arguments object. We do not (yet) correctly handle the | 6844 // the arguments object. We do not (yet) correctly handle the |
| 6846 // arguments property of the function. | 6845 // arguments property of the function. |
| 6847 if (current_info()->scope()->arguments() != NULL) { | 6846 if (info()->scope()->arguments() != NULL) { |
| 6848 // Parameters will rewrite to context slots. We have no direct way | 6847 // Parameters will rewrite to context slots. We have no direct way |
| 6849 // to detect that the variable is a parameter. | 6848 // to detect that the variable is a parameter. |
| 6850 int count = current_info()->scope()->num_parameters(); | 6849 int count = info()->scope()->num_parameters(); |
| 6851 for (int i = 0; i < count; ++i) { | 6850 for (int i = 0; i < count; ++i) { |
| 6852 if (var == current_info()->scope()->parameter(i)) { | 6851 if (var == info()->scope()->parameter(i)) { |
| 6853 return Bailout("assignment to parameter in arguments object"); | 6852 return Bailout("assignment to parameter in arguments object"); |
| 6854 } | 6853 } |
| 6855 } | 6854 } |
| 6856 } | 6855 } |
| 6857 | 6856 |
| 6858 CHECK_ALIVE(VisitForValue(expr->value())); | 6857 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6859 HStoreContextSlot::Mode mode; | 6858 HStoreContextSlot::Mode mode; |
| 6860 if (expr->op() == Token::ASSIGN) { | 6859 if (expr->op() == Token::ASSIGN) { |
| 6861 switch (var->mode()) { | 6860 switch (var->mode()) { |
| 6862 case LET: | 6861 case LET: |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7004 return new(zone()) HConstant(function, Representation::Tagged()); | 7003 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7005 } | 7004 } |
| 7006 | 7005 |
| 7007 // Handle a load from a known field somewhere in the prototype chain. | 7006 // Handle a load from a known field somewhere in the prototype chain. |
| 7008 LookupInPrototypes(map, name, &lookup); | 7007 LookupInPrototypes(map, name, &lookup); |
| 7009 if (lookup.IsField()) { | 7008 if (lookup.IsField()) { |
| 7010 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7009 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7011 Handle<JSObject> holder(lookup.holder()); | 7010 Handle<JSObject> holder(lookup.holder()); |
| 7012 Handle<Map> holder_map(holder->map()); | 7011 Handle<Map> holder_map(holder->map()); |
| 7013 AddCheckMap(object, map); | 7012 AddCheckMap(object, map); |
| 7014 AddInstruction(new(zone()) HCheckPrototypeMaps( | 7013 AddInstruction( |
| 7015 prototype, holder, zone(), top_info())); | 7014 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| 7016 HValue* holder_value = AddInstruction(new(zone()) | 7015 HValue* holder_value = AddInstruction(new(zone()) |
| 7017 HConstant(holder, Representation::Tagged())); | 7016 HConstant(holder, Representation::Tagged())); |
| 7018 return BuildLoadNamedField(holder_value, | 7017 return BuildLoadNamedField(holder_value, |
| 7019 HObjectAccess::ForField(holder_map, &lookup, name), | 7018 HObjectAccess::ForField(holder_map, &lookup, name), |
| 7020 ComputeLoadStoreRepresentation(map, &lookup)); | 7019 ComputeLoadStoreRepresentation(map, &lookup)); |
| 7021 } | 7020 } |
| 7022 | 7021 |
| 7023 // Handle a load of a constant function somewhere in the prototype chain. | 7022 // Handle a load of a constant function somewhere in the prototype chain. |
| 7024 if (lookup.IsConstantFunction()) { | 7023 if (lookup.IsConstantFunction()) { |
| 7025 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7024 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7026 Handle<JSObject> holder(lookup.holder()); | 7025 Handle<JSObject> holder(lookup.holder()); |
| 7027 Handle<Map> holder_map(holder->map()); | 7026 Handle<Map> holder_map(holder->map()); |
| 7028 AddCheckMap(object, map); | 7027 AddCheckMap(object, map); |
| 7029 AddInstruction(new(zone()) HCheckPrototypeMaps( | 7028 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| 7030 prototype, holder, zone(), top_info())); | |
| 7031 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 7029 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| 7032 return new(zone()) HConstant(function, Representation::Tagged()); | 7030 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7033 } | 7031 } |
| 7034 | 7032 |
| 7035 // No luck, do a generic load. | 7033 // No luck, do a generic load. |
| 7036 return BuildLoadNamedGeneric(object, name, expr); | 7034 return BuildLoadNamedGeneric(object, name, expr); |
| 7037 } | 7035 } |
| 7038 | 7036 |
| 7039 | 7037 |
| 7040 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 7038 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 7057 if (dependency) { | 7055 if (dependency) { |
| 7058 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 7056 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 7059 } | 7057 } |
| 7060 | 7058 |
| 7061 // Loads from a "stock" fast holey double arrays can elide the hole check. | 7059 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 7062 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 7060 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 7063 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 7061 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 7064 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 7062 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 7065 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 7063 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| 7066 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 7064 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
| 7067 AddInstruction(new(zone()) HCheckPrototypeMaps( | 7065 AddInstruction( |
| 7068 prototype, object_prototype, zone(), top_info())); | 7066 new(zone()) HCheckPrototypeMaps(prototype, object_prototype, zone())); |
| 7069 load_mode = ALLOW_RETURN_HOLE; | 7067 load_mode = ALLOW_RETURN_HOLE; |
| 7070 graph()->MarkDependsOnEmptyArrayProtoElements(); | 7068 graph()->MarkDependsOnEmptyArrayProtoElements(); |
| 7071 } | 7069 } |
| 7072 | 7070 |
| 7073 return BuildUncheckedMonomorphicElementAccess( | 7071 return BuildUncheckedMonomorphicElementAccess( |
| 7074 object, key, val, | 7072 object, key, val, |
| 7075 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 7073 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
| 7076 map->elements_kind(), is_store, load_mode, store_mode); | 7074 map->elements_kind(), is_store, load_mode, store_mode); |
| 7077 } | 7075 } |
| 7078 | 7076 |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7573 } | 7571 } |
| 7574 instr->set_position(expr->position()); | 7572 instr->set_position(expr->position()); |
| 7575 return ast_context()->ReturnInstruction(instr, expr->id()); | 7573 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7576 } | 7574 } |
| 7577 | 7575 |
| 7578 | 7576 |
| 7579 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7577 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 7580 Handle<Map> receiver_map) { | 7578 Handle<Map> receiver_map) { |
| 7581 if (!holder.is_null()) { | 7579 if (!holder.is_null()) { |
| 7582 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7580 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 7583 AddInstruction(new(zone()) HCheckPrototypeMaps( | 7581 AddInstruction( |
| 7584 prototype, holder, zone(), top_info())); | 7582 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| 7585 } | 7583 } |
| 7586 } | 7584 } |
| 7587 | 7585 |
| 7588 | 7586 |
| 7589 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 7587 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
| 7590 Handle<JSObject> holder, | 7588 Handle<JSObject> holder, |
| 7591 HValue* receiver, | 7589 HValue* receiver, |
| 7592 Handle<Map> receiver_map) { | 7590 Handle<Map> receiver_map) { |
| 7593 // Constant functions have the nice property that the map will change if they | 7591 // Constant functions have the nice property that the map will change if they |
| 7594 // are overwritten. Therefore it is enough to check the map of the holder and | 7592 // 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... |
| 7719 if (expr->check_type() == NUMBER_CHECK) { | 7717 if (expr->check_type() == NUMBER_CHECK) { |
| 7720 if_true->Goto(number_block); | 7718 if_true->Goto(number_block); |
| 7721 if_true = number_block; | 7719 if_true = number_block; |
| 7722 number_block->SetJoinId(expr->id()); | 7720 number_block->SetJoinId(expr->id()); |
| 7723 } | 7721 } |
| 7724 set_current_block(if_true); | 7722 set_current_block(if_true); |
| 7725 | 7723 |
| 7726 expr->ComputeTarget(map, name); | 7724 expr->ComputeTarget(map, name); |
| 7727 AddCheckPrototypeMaps(expr->holder(), map); | 7725 AddCheckPrototypeMaps(expr->holder(), map); |
| 7728 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 7726 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 7729 Handle<JSFunction> caller = current_info()->closure(); | 7727 Handle<JSFunction> caller = info()->closure(); |
| 7730 SmartArrayPointer<char> caller_name = | 7728 SmartArrayPointer<char> caller_name = |
| 7731 caller->shared()->DebugName()->ToCString(); | 7729 caller->shared()->DebugName()->ToCString(); |
| 7732 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 7730 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 7733 *name->ToCString(), | 7731 *name->ToCString(), |
| 7734 *caller_name); | 7732 *caller_name); |
| 7735 } | 7733 } |
| 7736 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 7734 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
| 7737 // Trying to inline will signal that we should bailout from the | 7735 // Trying to inline will signal that we should bailout from the |
| 7738 // entire compilation by setting stack overflow on the visitor. | 7736 // entire compilation by setting stack overflow on the visitor. |
| 7739 if (HasStackOverflow()) return; | 7737 if (HasStackOverflow()) return; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7803 | 7801 |
| 7804 | 7802 |
| 7805 static const int kNotInlinable = 1000000000; | 7803 static const int kNotInlinable = 1000000000; |
| 7806 | 7804 |
| 7807 | 7805 |
| 7808 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 7806 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
| 7809 if (!FLAG_use_inlining) return kNotInlinable; | 7807 if (!FLAG_use_inlining) return kNotInlinable; |
| 7810 | 7808 |
| 7811 // Precondition: call is monomorphic and we have found a target with the | 7809 // Precondition: call is monomorphic and we have found a target with the |
| 7812 // appropriate arity. | 7810 // appropriate arity. |
| 7813 Handle<JSFunction> caller = current_info()->closure(); | 7811 Handle<JSFunction> caller = info()->closure(); |
| 7814 Handle<SharedFunctionInfo> target_shared(target->shared()); | 7812 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 7815 | 7813 |
| 7816 // Do a quick check on source code length to avoid parsing large | 7814 // Do a quick check on source code length to avoid parsing large |
| 7817 // inlining candidates. | 7815 // inlining candidates. |
| 7818 if (target_shared->SourceSize() > | 7816 if (target_shared->SourceSize() > |
| 7819 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { | 7817 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { |
| 7820 TraceInline(target, caller, "target text too big"); | 7818 TraceInline(target, caller, "target text too big"); |
| 7821 return kNotInlinable; | 7819 return kNotInlinable; |
| 7822 } | 7820 } |
| 7823 | 7821 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7839 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, | 7837 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, |
| 7840 Handle<JSFunction> target, | 7838 Handle<JSFunction> target, |
| 7841 int arguments_count, | 7839 int arguments_count, |
| 7842 HValue* implicit_return_value, | 7840 HValue* implicit_return_value, |
| 7843 BailoutId ast_id, | 7841 BailoutId ast_id, |
| 7844 BailoutId return_id, | 7842 BailoutId return_id, |
| 7845 InliningKind inlining_kind) { | 7843 InliningKind inlining_kind) { |
| 7846 int nodes_added = InliningAstSize(target); | 7844 int nodes_added = InliningAstSize(target); |
| 7847 if (nodes_added == kNotInlinable) return false; | 7845 if (nodes_added == kNotInlinable) return false; |
| 7848 | 7846 |
| 7849 Handle<JSFunction> caller = current_info()->closure(); | 7847 Handle<JSFunction> caller = info()->closure(); |
| 7850 | 7848 |
| 7851 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 7849 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 7852 TraceInline(target, caller, "target AST is too large [early]"); | 7850 TraceInline(target, caller, "target AST is too large [early]"); |
| 7853 return false; | 7851 return false; |
| 7854 } | 7852 } |
| 7855 | 7853 |
| 7856 #if !defined(V8_TARGET_ARCH_IA32) | 7854 #if !defined(V8_TARGET_ARCH_IA32) |
| 7857 // Target must be able to use caller's context. | 7855 // Target must be able to use caller's context. |
| 7858 CompilationInfo* outer_info = current_info(); | 7856 CompilationInfo* outer_info = info(); |
| 7859 if (target->context() != outer_info->closure()->context() || | 7857 if (target->context() != outer_info->closure()->context() || |
| 7860 outer_info->scope()->contains_with() || | 7858 outer_info->scope()->contains_with() || |
| 7861 outer_info->scope()->num_heap_slots() > 0) { | 7859 outer_info->scope()->num_heap_slots() > 0) { |
| 7862 TraceInline(target, caller, "target requires context change"); | 7860 TraceInline(target, caller, "target requires context change"); |
| 7863 return false; | 7861 return false; |
| 7864 } | 7862 } |
| 7865 #endif | 7863 #endif |
| 7866 | 7864 |
| 7867 | 7865 |
| 7868 // Don't inline deeper than kMaxInliningLevels calls. | 7866 // Don't inline deeper than kMaxInliningLevels calls. |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8283 case kStringCharAt: | 8281 case kStringCharAt: |
| 8284 if (argument_count == 2 && check_type == STRING_CHECK) { | 8282 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 8285 HValue* index = Pop(); | 8283 HValue* index = Pop(); |
| 8286 HValue* string = Pop(); | 8284 HValue* string = Pop(); |
| 8287 HValue* context = environment()->LookupContext(); | 8285 HValue* context = environment()->LookupContext(); |
| 8288 ASSERT(!expr->holder().is_null()); | 8286 ASSERT(!expr->holder().is_null()); |
| 8289 AddInstruction(new(zone()) HCheckPrototypeMaps( | 8287 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 8290 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, | 8288 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, |
| 8291 expr->holder()->GetIsolate()), | 8289 expr->holder()->GetIsolate()), |
| 8292 expr->holder(), | 8290 expr->holder(), |
| 8293 zone(), | 8291 zone())); |
| 8294 top_info())); | |
| 8295 HInstruction* char_code = | 8292 HInstruction* char_code = |
| 8296 BuildStringCharCodeAt(context, string, index); | 8293 BuildStringCharCodeAt(context, string, index); |
| 8297 if (id == kStringCharCodeAt) { | 8294 if (id == kStringCharCodeAt) { |
| 8298 ast_context()->ReturnInstruction(char_code, expr->id()); | 8295 ast_context()->ReturnInstruction(char_code, expr->id()); |
| 8299 return true; | 8296 return true; |
| 8300 } | 8297 } |
| 8301 AddInstruction(char_code); | 8298 AddInstruction(char_code); |
| 8302 HInstruction* result = | 8299 HInstruction* result = |
| 8303 HStringCharFromCode::New(zone(), context, char_code); | 8300 HStringCharFromCode::New(zone(), context, char_code); |
| 8304 ast_context()->ReturnInstruction(result, expr->id()); | 8301 ast_context()->ReturnInstruction(result, expr->id()); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8435 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 8432 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 8436 return false; | 8433 return false; |
| 8437 } | 8434 } |
| 8438 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 8435 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 8439 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 8436 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 8440 !expr->target()->shared()->HasBuiltinFunctionId() || | 8437 !expr->target()->shared()->HasBuiltinFunctionId() || |
| 8441 expr->target()->shared()->builtin_function_id() != kFunctionApply) { | 8438 expr->target()->shared()->builtin_function_id() != kFunctionApply) { |
| 8442 return false; | 8439 return false; |
| 8443 } | 8440 } |
| 8444 | 8441 |
| 8445 if (current_info()->scope()->arguments() == NULL) return false; | 8442 if (info()->scope()->arguments() == NULL) return false; |
| 8446 | 8443 |
| 8447 ZoneList<Expression*>* args = expr->arguments(); | 8444 ZoneList<Expression*>* args = expr->arguments(); |
| 8448 if (args->length() != 2) return false; | 8445 if (args->length() != 2) return false; |
| 8449 | 8446 |
| 8450 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 8447 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 8451 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 8448 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 8452 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | 8449 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 8453 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 8450 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 8454 | 8451 |
| 8455 // Found pattern f.apply(receiver, arguments). | 8452 // Found pattern f.apply(receiver, arguments). |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8676 | 8673 |
| 8677 if (global_call) { | 8674 if (global_call) { |
| 8678 Variable* var = proxy->var(); | 8675 Variable* var = proxy->var(); |
| 8679 bool known_global_function = false; | 8676 bool known_global_function = false; |
| 8680 // If there is a global property cell for the name at compile time and | 8677 // If there is a global property cell for the name at compile time and |
| 8681 // access check is not enabled we assume that the function will not change | 8678 // access check is not enabled we assume that the function will not change |
| 8682 // and generate optimized code for calling the function. | 8679 // and generate optimized code for calling the function. |
| 8683 LookupResult lookup(isolate()); | 8680 LookupResult lookup(isolate()); |
| 8684 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 8681 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 8685 if (type == kUseCell && | 8682 if (type == kUseCell && |
| 8686 !current_info()->global_object()->IsAccessCheckNeeded()) { | 8683 !info()->global_object()->IsAccessCheckNeeded()) { |
| 8687 Handle<GlobalObject> global(current_info()->global_object()); | 8684 Handle<GlobalObject> global(info()->global_object()); |
| 8688 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 8685 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 8689 } | 8686 } |
| 8690 if (known_global_function) { | 8687 if (known_global_function) { |
| 8691 // Push the global object instead of the global receiver because | 8688 // Push the global object instead of the global receiver because |
| 8692 // code generated by the full code generator expects it. | 8689 // code generated by the full code generator expects it. |
| 8693 HValue* context = environment()->LookupContext(); | 8690 HValue* context = environment()->LookupContext(); |
| 8694 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 8691 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 8695 PushAndAdd(global_object); | 8692 PushAndAdd(global_object); |
| 8696 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8693 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8697 | 8694 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 8712 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. | 8709 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. |
| 8713 if (FLAG_trace_inlining) { | 8710 if (FLAG_trace_inlining) { |
| 8714 PrintF("Inlining builtin "); | 8711 PrintF("Inlining builtin "); |
| 8715 expr->target()->ShortPrint(); | 8712 expr->target()->ShortPrint(); |
| 8716 PrintF("\n"); | 8713 PrintF("\n"); |
| 8717 } | 8714 } |
| 8718 return; | 8715 return; |
| 8719 } | 8716 } |
| 8720 if (TryInlineCall(expr)) return; | 8717 if (TryInlineCall(expr)) return; |
| 8721 | 8718 |
| 8722 if (expr->target().is_identical_to(current_info()->closure())) { | 8719 if (expr->target().is_identical_to(info()->closure())) { |
| 8723 graph()->MarkRecursive(); | 8720 graph()->MarkRecursive(); |
| 8724 } | 8721 } |
| 8725 | 8722 |
| 8726 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 8723 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 8727 argument_count)); | 8724 argument_count)); |
| 8728 } else { | 8725 } else { |
| 8729 HValue* context = environment()->LookupContext(); | 8726 HValue* context = environment()->LookupContext(); |
| 8730 HGlobalObject* receiver = new(zone()) HGlobalObject(context); | 8727 HGlobalObject* receiver = new(zone()) HGlobalObject(context); |
| 8731 AddInstruction(receiver); | 8728 AddInstruction(receiver); |
| 8732 PushAndAdd(new(zone()) HPushArgument(receiver)); | 8729 PushAndAdd(new(zone()) HPushArgument(receiver)); |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9211 | 9208 |
| 9212 case Variable::PARAMETER: | 9209 case Variable::PARAMETER: |
| 9213 case Variable::LOCAL: | 9210 case Variable::LOCAL: |
| 9214 BindIfLive(var, after); | 9211 BindIfLive(var, after); |
| 9215 break; | 9212 break; |
| 9216 | 9213 |
| 9217 case Variable::CONTEXT: { | 9214 case Variable::CONTEXT: { |
| 9218 // Bail out if we try to mutate a parameter value in a function | 9215 // Bail out if we try to mutate a parameter value in a function |
| 9219 // using the arguments object. We do not (yet) correctly handle the | 9216 // using the arguments object. We do not (yet) correctly handle the |
| 9220 // arguments property of the function. | 9217 // arguments property of the function. |
| 9221 if (current_info()->scope()->arguments() != NULL) { | 9218 if (info()->scope()->arguments() != NULL) { |
| 9222 // Parameters will rewrite to context slots. We have no direct | 9219 // Parameters will rewrite to context slots. We have no direct |
| 9223 // way to detect that the variable is a parameter so we use a | 9220 // way to detect that the variable is a parameter so we use a |
| 9224 // linear search of the parameter list. | 9221 // linear search of the parameter list. |
| 9225 int count = current_info()->scope()->num_parameters(); | 9222 int count = info()->scope()->num_parameters(); |
| 9226 for (int i = 0; i < count; ++i) { | 9223 for (int i = 0; i < count; ++i) { |
| 9227 if (var == current_info()->scope()->parameter(i)) { | 9224 if (var == info()->scope()->parameter(i)) { |
| 9228 return Bailout("assignment to parameter in arguments object"); | 9225 return Bailout("assignment to parameter in arguments object"); |
| 9229 } | 9226 } |
| 9230 } | 9227 } |
| 9231 } | 9228 } |
| 9232 | 9229 |
| 9233 HValue* context = BuildContextChainWalk(var); | 9230 HValue* context = BuildContextChainWalk(var); |
| 9234 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 9231 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
| 9235 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 9232 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
| 9236 HStoreContextSlot* instr = | 9233 HStoreContextSlot* instr = |
| 9237 new(zone()) HStoreContextSlot(context, var->index(), mode, after); | 9234 new(zone()) HStoreContextSlot(context, var->index(), mode, after); |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9816 } | 9813 } |
| 9817 | 9814 |
| 9818 if (op == Token::INSTANCEOF) { | 9815 if (op == Token::INSTANCEOF) { |
| 9819 // Check to see if the rhs of the instanceof is a global function not | 9816 // Check to see if the rhs of the instanceof is a global function not |
| 9820 // residing in new space. If it is we assume that the function will stay the | 9817 // residing in new space. If it is we assume that the function will stay the |
| 9821 // same. | 9818 // same. |
| 9822 Handle<JSFunction> target = Handle<JSFunction>::null(); | 9819 Handle<JSFunction> target = Handle<JSFunction>::null(); |
| 9823 VariableProxy* proxy = expr->right()->AsVariableProxy(); | 9820 VariableProxy* proxy = expr->right()->AsVariableProxy(); |
| 9824 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); | 9821 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); |
| 9825 if (global_function && | 9822 if (global_function && |
| 9826 current_info()->has_global_object() && | 9823 info()->has_global_object() && |
| 9827 !current_info()->global_object()->IsAccessCheckNeeded()) { | 9824 !info()->global_object()->IsAccessCheckNeeded()) { |
| 9828 Handle<String> name = proxy->name(); | 9825 Handle<String> name = proxy->name(); |
| 9829 Handle<GlobalObject> global(current_info()->global_object()); | 9826 Handle<GlobalObject> global(info()->global_object()); |
| 9830 LookupResult lookup(isolate()); | 9827 LookupResult lookup(isolate()); |
| 9831 global->Lookup(*name, &lookup); | 9828 global->Lookup(*name, &lookup); |
| 9832 if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) { | 9829 if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) { |
| 9833 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); | 9830 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); |
| 9834 // If the function is in new space we assume it's more likely to | 9831 // If the function is in new space we assume it's more likely to |
| 9835 // change and thus prefer the general IC code. | 9832 // change and thus prefer the general IC code. |
| 9836 if (!isolate()->heap()->InNewSpace(*candidate)) { | 9833 if (!isolate()->heap()->InNewSpace(*candidate)) { |
| 9837 target = candidate; | 9834 target = candidate; |
| 9838 } | 9835 } |
| 9839 } | 9836 } |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10262 | 10259 |
| 10263 | 10260 |
| 10264 void HOptimizedGraphBuilder::VisitDeclarations( | 10261 void HOptimizedGraphBuilder::VisitDeclarations( |
| 10265 ZoneList<Declaration*>* declarations) { | 10262 ZoneList<Declaration*>* declarations) { |
| 10266 ASSERT(globals_.is_empty()); | 10263 ASSERT(globals_.is_empty()); |
| 10267 AstVisitor::VisitDeclarations(declarations); | 10264 AstVisitor::VisitDeclarations(declarations); |
| 10268 if (!globals_.is_empty()) { | 10265 if (!globals_.is_empty()) { |
| 10269 Handle<FixedArray> array = | 10266 Handle<FixedArray> array = |
| 10270 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 10267 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
| 10271 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 10268 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
| 10272 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | | 10269 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
| 10273 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | | 10270 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
| 10274 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); | 10271 DeclareGlobalsLanguageMode::encode(info()->language_mode()); |
| 10275 HInstruction* result = new(zone()) HDeclareGlobals( | 10272 HInstruction* result = new(zone()) HDeclareGlobals( |
| 10276 environment()->LookupContext(), array, flags); | 10273 environment()->LookupContext(), array, flags); |
| 10277 AddInstruction(result); | 10274 AddInstruction(result); |
| 10278 globals_.Clear(); | 10275 globals_.Clear(); |
| 10279 } | 10276 } |
| 10280 } | 10277 } |
| 10281 | 10278 |
| 10282 | 10279 |
| 10283 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 10280 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
| 10284 VariableDeclaration* declaration) { | 10281 VariableDeclaration* declaration) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10318 } | 10315 } |
| 10319 | 10316 |
| 10320 | 10317 |
| 10321 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 10318 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
| 10322 FunctionDeclaration* declaration) { | 10319 FunctionDeclaration* declaration) { |
| 10323 VariableProxy* proxy = declaration->proxy(); | 10320 VariableProxy* proxy = declaration->proxy(); |
| 10324 Variable* variable = proxy->var(); | 10321 Variable* variable = proxy->var(); |
| 10325 switch (variable->location()) { | 10322 switch (variable->location()) { |
| 10326 case Variable::UNALLOCATED: { | 10323 case Variable::UNALLOCATED: { |
| 10327 globals_.Add(variable->name(), zone()); | 10324 globals_.Add(variable->name(), zone()); |
| 10328 Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo( | 10325 Handle<SharedFunctionInfo> function = |
| 10329 declaration->fun(), current_info()->script()); | 10326 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); |
| 10330 // Check for stack-overflow exception. | 10327 // Check for stack-overflow exception. |
| 10331 if (function.is_null()) return SetStackOverflow(); | 10328 if (function.is_null()) return SetStackOverflow(); |
| 10332 globals_.Add(function, zone()); | 10329 globals_.Add(function, zone()); |
| 10333 return; | 10330 return; |
| 10334 } | 10331 } |
| 10335 case Variable::PARAMETER: | 10332 case Variable::PARAMETER: |
| 10336 case Variable::LOCAL: { | 10333 case Variable::LOCAL: { |
| 10337 CHECK_ALIVE(VisitForValue(declaration->fun())); | 10334 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 10338 HValue* value = Pop(); | 10335 HValue* value = Pop(); |
| 10339 BindIfLive(variable, value); | 10336 BindIfLive(variable, value); |
| (...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11600 } | 11597 } |
| 11601 } | 11598 } |
| 11602 | 11599 |
| 11603 #ifdef DEBUG | 11600 #ifdef DEBUG |
| 11604 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11601 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11605 if (allocator_ != NULL) allocator_->Verify(); | 11602 if (allocator_ != NULL) allocator_->Verify(); |
| 11606 #endif | 11603 #endif |
| 11607 } | 11604 } |
| 11608 | 11605 |
| 11609 } } // namespace v8::internal | 11606 } } // namespace v8::internal |
| OLD | NEW |