| 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 3793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3804 | 3804 |
| 3805 | 3805 |
| 3806 #define CHECK_ALIVE(call) \ | 3806 #define CHECK_ALIVE(call) \ |
| 3807 do { \ | 3807 do { \ |
| 3808 call; \ | 3808 call; \ |
| 3809 if (HasStackOverflow() || current_block() == NULL) return; \ | 3809 if (HasStackOverflow() || current_block() == NULL) return; \ |
| 3810 } while (false) | 3810 } while (false) |
| 3811 | 3811 |
| 3812 | 3812 |
| 3813 void HOptimizedGraphBuilder::Bailout(const char* reason) { | 3813 void HOptimizedGraphBuilder::Bailout(const char* reason) { |
| 3814 info()->set_bailout_reason(reason); | 3814 current_info()->set_bailout_reason(reason); |
| 3815 SetStackOverflow(); | 3815 SetStackOverflow(); |
| 3816 } | 3816 } |
| 3817 | 3817 |
| 3818 | 3818 |
| 3819 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 3819 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
| 3820 EffectContext for_effect(this); | 3820 EffectContext for_effect(this); |
| 3821 Visit(expr); | 3821 Visit(expr); |
| 3822 } | 3822 } |
| 3823 | 3823 |
| 3824 | 3824 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3861 | 3861 |
| 3862 void HOptimizedGraphBuilder::VisitExpressions( | 3862 void HOptimizedGraphBuilder::VisitExpressions( |
| 3863 ZoneList<Expression*>* exprs) { | 3863 ZoneList<Expression*>* exprs) { |
| 3864 for (int i = 0; i < exprs->length(); ++i) { | 3864 for (int i = 0; i < exprs->length(); ++i) { |
| 3865 CHECK_ALIVE(VisitForValue(exprs->at(i))); | 3865 CHECK_ALIVE(VisitForValue(exprs->at(i))); |
| 3866 } | 3866 } |
| 3867 } | 3867 } |
| 3868 | 3868 |
| 3869 | 3869 |
| 3870 bool HOptimizedGraphBuilder::BuildGraph() { | 3870 bool HOptimizedGraphBuilder::BuildGraph() { |
| 3871 if (info()->function()->is_generator()) { | 3871 if (current_info()->function()->is_generator()) { |
| 3872 Bailout("function is a generator"); | 3872 Bailout("function is a generator"); |
| 3873 return false; | 3873 return false; |
| 3874 } | 3874 } |
| 3875 Scope* scope = info()->scope(); | 3875 Scope* scope = current_info()->scope(); |
| 3876 if (scope->HasIllegalRedeclaration()) { | 3876 if (scope->HasIllegalRedeclaration()) { |
| 3877 Bailout("function with illegal redeclaration"); | 3877 Bailout("function with illegal redeclaration"); |
| 3878 return false; | 3878 return false; |
| 3879 } | 3879 } |
| 3880 if (scope->calls_eval()) { | 3880 if (scope->calls_eval()) { |
| 3881 Bailout("function calls eval"); | 3881 Bailout("function calls eval"); |
| 3882 return false; | 3882 return false; |
| 3883 } | 3883 } |
| 3884 SetUpScope(scope); | 3884 SetUpScope(scope); |
| 3885 | 3885 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3909 if (scope->is_function_scope() && scope->function() != NULL) { | 3909 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3910 VisitVariableDeclaration(scope->function()); | 3910 VisitVariableDeclaration(scope->function()); |
| 3911 } | 3911 } |
| 3912 VisitDeclarations(scope->declarations()); | 3912 VisitDeclarations(scope->declarations()); |
| 3913 AddSimulate(BailoutId::Declarations()); | 3913 AddSimulate(BailoutId::Declarations()); |
| 3914 | 3914 |
| 3915 HValue* context = environment()->LookupContext(); | 3915 HValue* context = environment()->LookupContext(); |
| 3916 AddInstruction( | 3916 AddInstruction( |
| 3917 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); | 3917 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); |
| 3918 | 3918 |
| 3919 VisitStatements(info()->function()->body()); | 3919 VisitStatements(current_info()->function()->body()); |
| 3920 if (HasStackOverflow()) return false; | 3920 if (HasStackOverflow()) return false; |
| 3921 | 3921 |
| 3922 if (current_block() != NULL) { | 3922 if (current_block() != NULL) { |
| 3923 AddReturn(graph()->GetConstantUndefined()); | 3923 AddReturn(graph()->GetConstantUndefined()); |
| 3924 set_current_block(NULL); | 3924 set_current_block(NULL); |
| 3925 } | 3925 } |
| 3926 | 3926 |
| 3927 // If the checksum of the number of type info changes is the same as the | 3927 // If the checksum of the number of type info changes is the same as the |
| 3928 // last time this function was compiled, then this recompile is likely not | 3928 // last time this function was compiled, then this recompile is likely not |
| 3929 // due to missing/inadequate type feedback, but rather too aggressive | 3929 // due to missing/inadequate type feedback, but rather too aggressive |
| 3930 // optimization. Disable optimistic LICM in that case. | 3930 // optimization. Disable optimistic LICM in that case. |
| 3931 Handle<Code> unoptimized_code(info()->shared_info()->code()); | 3931 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
| 3932 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 3932 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 3933 Handle<TypeFeedbackInfo> type_info( | 3933 Handle<TypeFeedbackInfo> type_info( |
| 3934 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 3934 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
| 3935 int checksum = type_info->own_type_change_checksum(); | 3935 int checksum = type_info->own_type_change_checksum(); |
| 3936 int composite_checksum = graph()->update_type_change_checksum(checksum); | 3936 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3937 graph()->set_use_optimistic_licm( | 3937 graph()->set_use_optimistic_licm( |
| 3938 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 3938 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3939 type_info->set_inlined_type_change_checksum(composite_checksum); | 3939 type_info->set_inlined_type_change_checksum(composite_checksum); |
| 3940 | 3940 |
| 3941 return true; | 3941 return true; |
| (...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5110 } else { | 5110 } else { |
| 5111 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 5111 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
| 5112 if (last_block != NULL) last_block->Goto(break_block); | 5112 if (last_block != NULL) last_block->Goto(break_block); |
| 5113 break_block->SetJoinId(stmt->ExitId()); | 5113 break_block->SetJoinId(stmt->ExitId()); |
| 5114 set_current_block(break_block); | 5114 set_current_block(break_block); |
| 5115 } | 5115 } |
| 5116 } | 5116 } |
| 5117 | 5117 |
| 5118 | 5118 |
| 5119 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | 5119 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { |
| 5120 return statement->OsrEntryId() == info()->osr_ast_id(); | 5120 return statement->OsrEntryId() == current_info()->osr_ast_id(); |
| 5121 } | 5121 } |
| 5122 | 5122 |
| 5123 | 5123 |
| 5124 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 5124 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
| 5125 if (!HasOsrEntryAt(statement)) return false; | 5125 if (!HasOsrEntryAt(statement)) return false; |
| 5126 | 5126 |
| 5127 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 5127 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
| 5128 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 5128 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
| 5129 HValue* true_value = graph()->GetConstantTrue(); | 5129 HValue* true_value = graph()->GetConstantTrue(); |
| 5130 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | 5130 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... |
| 5497 | 5497 |
| 5498 return Handle<SharedFunctionInfo>(); | 5498 return Handle<SharedFunctionInfo>(); |
| 5499 } | 5499 } |
| 5500 | 5500 |
| 5501 | 5501 |
| 5502 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 5502 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 5503 ASSERT(!HasStackOverflow()); | 5503 ASSERT(!HasStackOverflow()); |
| 5504 ASSERT(current_block() != NULL); | 5504 ASSERT(current_block() != NULL); |
| 5505 ASSERT(current_block()->HasPredecessor()); | 5505 ASSERT(current_block()->HasPredecessor()); |
| 5506 Handle<SharedFunctionInfo> shared_info = | 5506 Handle<SharedFunctionInfo> shared_info = |
| 5507 SearchSharedFunctionInfo(info()->shared_info()->code(), expr); | 5507 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); |
| 5508 if (shared_info.is_null()) { | 5508 if (shared_info.is_null()) { |
| 5509 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 5509 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); |
| 5510 } | 5510 } |
| 5511 // We also have a stack overflow if the recursive compilation did. | 5511 // We also have a stack overflow if the recursive compilation did. |
| 5512 if (HasStackOverflow()) return; | 5512 if (HasStackOverflow()) return; |
| 5513 HValue* context = environment()->LookupContext(); | 5513 HValue* context = environment()->LookupContext(); |
| 5514 HFunctionLiteral* instr = | 5514 HFunctionLiteral* instr = |
| 5515 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 5515 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
| 5516 return ast_context()->ReturnInstruction(instr, expr->id()); | 5516 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5517 } | 5517 } |
| 5518 | 5518 |
| 5519 | 5519 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5560 if (join != NULL && !ast_context()->IsEffect()) { | 5560 if (join != NULL && !ast_context()->IsEffect()) { |
| 5561 return ast_context()->ReturnValue(Pop()); | 5561 return ast_context()->ReturnValue(Pop()); |
| 5562 } | 5562 } |
| 5563 } | 5563 } |
| 5564 } | 5564 } |
| 5565 | 5565 |
| 5566 | 5566 |
| 5567 HOptimizedGraphBuilder::GlobalPropertyAccess | 5567 HOptimizedGraphBuilder::GlobalPropertyAccess |
| 5568 HOptimizedGraphBuilder::LookupGlobalProperty( | 5568 HOptimizedGraphBuilder::LookupGlobalProperty( |
| 5569 Variable* var, LookupResult* lookup, bool is_store) { | 5569 Variable* var, LookupResult* lookup, bool is_store) { |
| 5570 if (var->is_this() || !info()->has_global_object()) { | 5570 if (var->is_this() || !current_info()->has_global_object()) { |
| 5571 return kUseGeneric; | 5571 return kUseGeneric; |
| 5572 } | 5572 } |
| 5573 Handle<GlobalObject> global(info()->global_object()); | 5573 Handle<GlobalObject> global(current_info()->global_object()); |
| 5574 global->Lookup(*var->name(), lookup); | 5574 global->Lookup(*var->name(), lookup); |
| 5575 if (!lookup->IsNormal() || | 5575 if (!lookup->IsNormal() || |
| 5576 (is_store && lookup->IsReadOnly()) || | 5576 (is_store && lookup->IsReadOnly()) || |
| 5577 lookup->holder() != *global) { | 5577 lookup->holder() != *global) { |
| 5578 return kUseGeneric; | 5578 return kUseGeneric; |
| 5579 } | 5579 } |
| 5580 | 5580 |
| 5581 return kUseCell; | 5581 return kUseCell; |
| 5582 } | 5582 } |
| 5583 | 5583 |
| 5584 | 5584 |
| 5585 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5585 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 5586 ASSERT(var->IsContextSlot()); | 5586 ASSERT(var->IsContextSlot()); |
| 5587 HValue* context = environment()->LookupContext(); | 5587 HValue* context = environment()->LookupContext(); |
| 5588 int length = info()->scope()->ContextChainLength(var->scope()); | 5588 int length = current_info()->scope()->ContextChainLength(var->scope()); |
| 5589 while (length-- > 0) { | 5589 while (length-- > 0) { |
| 5590 HInstruction* context_instruction = new(zone()) HOuterContext(context); | 5590 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
| 5591 AddInstruction(context_instruction); | 5591 AddInstruction(context_instruction); |
| 5592 context = context_instruction; | 5592 context = context_instruction; |
| 5593 } | 5593 } |
| 5594 return context; | 5594 return context; |
| 5595 } | 5595 } |
| 5596 | 5596 |
| 5597 | 5597 |
| 5598 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5598 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5614 HConstant* instr = | 5614 HConstant* instr = |
| 5615 new(zone()) HConstant(constant_value, Representation::Tagged()); | 5615 new(zone()) HConstant(constant_value, Representation::Tagged()); |
| 5616 return ast_context()->ReturnInstruction(instr, expr->id()); | 5616 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5617 } | 5617 } |
| 5618 | 5618 |
| 5619 LookupResult lookup(isolate()); | 5619 LookupResult lookup(isolate()); |
| 5620 GlobalPropertyAccess type = | 5620 GlobalPropertyAccess type = |
| 5621 LookupGlobalProperty(variable, &lookup, false); | 5621 LookupGlobalProperty(variable, &lookup, false); |
| 5622 | 5622 |
| 5623 if (type == kUseCell && | 5623 if (type == kUseCell && |
| 5624 info()->global_object()->IsAccessCheckNeeded()) { | 5624 current_info()->global_object()->IsAccessCheckNeeded()) { |
| 5625 type = kUseGeneric; | 5625 type = kUseGeneric; |
| 5626 } | 5626 } |
| 5627 | 5627 |
| 5628 if (type == kUseCell) { | 5628 if (type == kUseCell) { |
| 5629 Handle<GlobalObject> global(info()->global_object()); | 5629 Handle<GlobalObject> global(current_info()->global_object()); |
| 5630 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 5630 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5631 HLoadGlobalCell* instr = | 5631 HLoadGlobalCell* instr = |
| 5632 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); | 5632 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); |
| 5633 return ast_context()->ReturnInstruction(instr, expr->id()); | 5633 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5634 } else { | 5634 } else { |
| 5635 HValue* context = environment()->LookupContext(); | 5635 HValue* context = environment()->LookupContext(); |
| 5636 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5636 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 5637 AddInstruction(global_object); | 5637 AddInstruction(global_object); |
| 5638 HLoadGlobalGeneric* instr = | 5638 HLoadGlobalGeneric* instr = |
| 5639 new(zone()) HLoadGlobalGeneric(context, | 5639 new(zone()) HLoadGlobalGeneric(context, |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6210 // Otherwise, find the top prototype. | 6210 // Otherwise, find the top prototype. |
| 6211 while (proto->GetPrototype(isolate())->IsJSObject()) { | 6211 while (proto->GetPrototype(isolate())->IsJSObject()) { |
| 6212 proto = proto->GetPrototype(isolate()); | 6212 proto = proto->GetPrototype(isolate()); |
| 6213 } | 6213 } |
| 6214 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 6214 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
| 6215 } | 6215 } |
| 6216 ASSERT(proto->IsJSObject()); | 6216 ASSERT(proto->IsJSObject()); |
| 6217 AddInstruction(new(zone()) HCheckPrototypeMaps( | 6217 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 6218 Handle<JSObject>(JSObject::cast(map->prototype())), | 6218 Handle<JSObject>(JSObject::cast(map->prototype())), |
| 6219 Handle<JSObject>(JSObject::cast(proto)), | 6219 Handle<JSObject>(JSObject::cast(proto)), |
| 6220 zone())); | 6220 zone(), |
| 6221 top_info())); |
| 6221 } | 6222 } |
| 6222 | 6223 |
| 6223 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 6224 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
| 6224 Representation representation = ComputeLoadStoreRepresentation(map, lookup); | 6225 Representation representation = ComputeLoadStoreRepresentation(map, lookup); |
| 6225 bool transition_to_field = lookup->IsTransitionToField(*map); | 6226 bool transition_to_field = lookup->IsTransitionToField(*map); |
| 6226 | 6227 |
| 6227 HStoreNamedField *instr; | 6228 HStoreNamedField *instr; |
| 6228 if (FLAG_track_double_fields && representation.IsDouble()) { | 6229 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 6229 if (transition_to_field) { | 6230 if (transition_to_field) { |
| 6230 // The store requires a mutable HeapNumber to be allocated. | 6231 // The store requires a mutable HeapNumber to be allocated. |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6549 // superclass of Assignment and CountOperation, we cannot just pass the | 6550 // superclass of Assignment and CountOperation, we cannot just pass the |
| 6550 // owning expression instead of position and ast_id separately. | 6551 // owning expression instead of position and ast_id separately. |
| 6551 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6552 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6552 Variable* var, | 6553 Variable* var, |
| 6553 HValue* value, | 6554 HValue* value, |
| 6554 int position, | 6555 int position, |
| 6555 BailoutId ast_id) { | 6556 BailoutId ast_id) { |
| 6556 LookupResult lookup(isolate()); | 6557 LookupResult lookup(isolate()); |
| 6557 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 6558 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 6558 if (type == kUseCell) { | 6559 if (type == kUseCell) { |
| 6559 Handle<GlobalObject> global(info()->global_object()); | 6560 Handle<GlobalObject> global(current_info()->global_object()); |
| 6560 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 6561 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 6561 HInstruction* instr = | 6562 HInstruction* instr = |
| 6562 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); | 6563 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); |
| 6563 instr->set_position(position); | 6564 instr->set_position(position); |
| 6564 AddInstruction(instr); | 6565 AddInstruction(instr); |
| 6565 if (instr->HasObservableSideEffects()) { | 6566 if (instr->HasObservableSideEffects()) { |
| 6566 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 6567 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 6567 } | 6568 } |
| 6568 } else { | 6569 } else { |
| 6569 HValue* context = environment()->LookupContext(); | 6570 HValue* context = environment()->LookupContext(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6614 if (var->mode() == CONST) { | 6615 if (var->mode() == CONST) { |
| 6615 return Bailout("unsupported const compound assignment"); | 6616 return Bailout("unsupported const compound assignment"); |
| 6616 } | 6617 } |
| 6617 BindIfLive(var, Top()); | 6618 BindIfLive(var, Top()); |
| 6618 break; | 6619 break; |
| 6619 | 6620 |
| 6620 case Variable::CONTEXT: { | 6621 case Variable::CONTEXT: { |
| 6621 // Bail out if we try to mutate a parameter value in a function | 6622 // Bail out if we try to mutate a parameter value in a function |
| 6622 // using the arguments object. We do not (yet) correctly handle the | 6623 // using the arguments object. We do not (yet) correctly handle the |
| 6623 // arguments property of the function. | 6624 // arguments property of the function. |
| 6624 if (info()->scope()->arguments() != NULL) { | 6625 if (current_info()->scope()->arguments() != NULL) { |
| 6625 // Parameters will be allocated to context slots. We have no | 6626 // Parameters will be allocated to context slots. We have no |
| 6626 // direct way to detect that the variable is a parameter so we do | 6627 // direct way to detect that the variable is a parameter so we do |
| 6627 // a linear search of the parameter variables. | 6628 // a linear search of the parameter variables. |
| 6628 int count = info()->scope()->num_parameters(); | 6629 int count = current_info()->scope()->num_parameters(); |
| 6629 for (int i = 0; i < count; ++i) { | 6630 for (int i = 0; i < count; ++i) { |
| 6630 if (var == info()->scope()->parameter(i)) { | 6631 if (var == current_info()->scope()->parameter(i)) { |
| 6631 Bailout( | 6632 Bailout( |
| 6632 "assignment to parameter, function uses arguments object"); | 6633 "assignment to parameter, function uses arguments object"); |
| 6633 } | 6634 } |
| 6634 } | 6635 } |
| 6635 } | 6636 } |
| 6636 | 6637 |
| 6637 HStoreContextSlot::Mode mode; | 6638 HStoreContextSlot::Mode mode; |
| 6638 | 6639 |
| 6639 switch (var->mode()) { | 6640 switch (var->mode()) { |
| 6640 case LET: | 6641 case LET: |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6840 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 6841 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
| 6841 HValue* value = Pop(); | 6842 HValue* value = Pop(); |
| 6842 BindIfLive(var, value); | 6843 BindIfLive(var, value); |
| 6843 return ast_context()->ReturnValue(value); | 6844 return ast_context()->ReturnValue(value); |
| 6844 } | 6845 } |
| 6845 | 6846 |
| 6846 case Variable::CONTEXT: { | 6847 case Variable::CONTEXT: { |
| 6847 // Bail out if we try to mutate a parameter value in a function using | 6848 // Bail out if we try to mutate a parameter value in a function using |
| 6848 // the arguments object. We do not (yet) correctly handle the | 6849 // the arguments object. We do not (yet) correctly handle the |
| 6849 // arguments property of the function. | 6850 // arguments property of the function. |
| 6850 if (info()->scope()->arguments() != NULL) { | 6851 if (current_info()->scope()->arguments() != NULL) { |
| 6851 // Parameters will rewrite to context slots. We have no direct way | 6852 // Parameters will rewrite to context slots. We have no direct way |
| 6852 // to detect that the variable is a parameter. | 6853 // to detect that the variable is a parameter. |
| 6853 int count = info()->scope()->num_parameters(); | 6854 int count = current_info()->scope()->num_parameters(); |
| 6854 for (int i = 0; i < count; ++i) { | 6855 for (int i = 0; i < count; ++i) { |
| 6855 if (var == info()->scope()->parameter(i)) { | 6856 if (var == current_info()->scope()->parameter(i)) { |
| 6856 return Bailout("assignment to parameter in arguments object"); | 6857 return Bailout("assignment to parameter in arguments object"); |
| 6857 } | 6858 } |
| 6858 } | 6859 } |
| 6859 } | 6860 } |
| 6860 | 6861 |
| 6861 CHECK_ALIVE(VisitForValue(expr->value())); | 6862 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6862 HStoreContextSlot::Mode mode; | 6863 HStoreContextSlot::Mode mode; |
| 6863 if (expr->op() == Token::ASSIGN) { | 6864 if (expr->op() == Token::ASSIGN) { |
| 6864 switch (var->mode()) { | 6865 switch (var->mode()) { |
| 6865 case LET: | 6866 case LET: |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7007 return new(zone()) HConstant(function, Representation::Tagged()); | 7008 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7008 } | 7009 } |
| 7009 | 7010 |
| 7010 // Handle a load from a known field somewhere in the prototype chain. | 7011 // Handle a load from a known field somewhere in the prototype chain. |
| 7011 LookupInPrototypes(map, name, &lookup); | 7012 LookupInPrototypes(map, name, &lookup); |
| 7012 if (lookup.IsField()) { | 7013 if (lookup.IsField()) { |
| 7013 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7014 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7014 Handle<JSObject> holder(lookup.holder()); | 7015 Handle<JSObject> holder(lookup.holder()); |
| 7015 Handle<Map> holder_map(holder->map()); | 7016 Handle<Map> holder_map(holder->map()); |
| 7016 AddCheckMap(object, map); | 7017 AddCheckMap(object, map); |
| 7017 AddInstruction( | 7018 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7018 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7019 prototype, holder, zone(), top_info())); |
| 7019 HValue* holder_value = AddInstruction(new(zone()) | 7020 HValue* holder_value = AddInstruction(new(zone()) |
| 7020 HConstant(holder, Representation::Tagged())); | 7021 HConstant(holder, Representation::Tagged())); |
| 7021 return BuildLoadNamedField(holder_value, | 7022 return BuildLoadNamedField(holder_value, |
| 7022 HObjectAccess::ForField(holder_map, &lookup, name), | 7023 HObjectAccess::ForField(holder_map, &lookup, name), |
| 7023 ComputeLoadStoreRepresentation(map, &lookup)); | 7024 ComputeLoadStoreRepresentation(map, &lookup)); |
| 7024 } | 7025 } |
| 7025 | 7026 |
| 7026 // Handle a load of a constant function somewhere in the prototype chain. | 7027 // Handle a load of a constant function somewhere in the prototype chain. |
| 7027 if (lookup.IsConstantFunction()) { | 7028 if (lookup.IsConstantFunction()) { |
| 7028 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 7029 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 7029 Handle<JSObject> holder(lookup.holder()); | 7030 Handle<JSObject> holder(lookup.holder()); |
| 7030 Handle<Map> holder_map(holder->map()); | 7031 Handle<Map> holder_map(holder->map()); |
| 7031 AddCheckMap(object, map); | 7032 AddCheckMap(object, map); |
| 7032 AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7033 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7034 prototype, holder, zone(), top_info())); |
| 7033 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); | 7035 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| 7034 return new(zone()) HConstant(function, Representation::Tagged()); | 7036 return new(zone()) HConstant(function, Representation::Tagged()); |
| 7035 } | 7037 } |
| 7036 | 7038 |
| 7037 // No luck, do a generic load. | 7039 // No luck, do a generic load. |
| 7038 return BuildLoadNamedGeneric(object, name, expr); | 7040 return BuildLoadNamedGeneric(object, name, expr); |
| 7039 } | 7041 } |
| 7040 | 7042 |
| 7041 | 7043 |
| 7042 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 7044 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 7059 if (dependency) { | 7061 if (dependency) { |
| 7060 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 7062 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
| 7061 } | 7063 } |
| 7062 | 7064 |
| 7063 // Loads from a "stock" fast holey double arrays can elide the hole check. | 7065 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 7064 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 7066 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 7065 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 7067 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 7066 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 7068 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 7067 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 7069 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| 7068 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 7070 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
| 7069 AddInstruction( | 7071 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7070 new(zone()) HCheckPrototypeMaps(prototype, object_prototype, zone())); | 7072 prototype, object_prototype, zone(), top_info())); |
| 7071 load_mode = ALLOW_RETURN_HOLE; | 7073 load_mode = ALLOW_RETURN_HOLE; |
| 7072 graph()->MarkDependsOnEmptyArrayProtoElements(); | 7074 graph()->MarkDependsOnEmptyArrayProtoElements(); |
| 7073 } | 7075 } |
| 7074 | 7076 |
| 7075 return BuildUncheckedMonomorphicElementAccess( | 7077 return BuildUncheckedMonomorphicElementAccess( |
| 7076 object, key, val, | 7078 object, key, val, |
| 7077 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 7079 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
| 7078 map->elements_kind(), is_store, load_mode, store_mode); | 7080 map->elements_kind(), is_store, load_mode, store_mode); |
| 7079 } | 7081 } |
| 7080 | 7082 |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7575 } | 7577 } |
| 7576 instr->set_position(expr->position()); | 7578 instr->set_position(expr->position()); |
| 7577 return ast_context()->ReturnInstruction(instr, expr->id()); | 7579 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7578 } | 7580 } |
| 7579 | 7581 |
| 7580 | 7582 |
| 7581 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7583 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 7582 Handle<Map> receiver_map) { | 7584 Handle<Map> receiver_map) { |
| 7583 if (!holder.is_null()) { | 7585 if (!holder.is_null()) { |
| 7584 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7586 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 7585 AddInstruction( | 7587 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 7586 new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); | 7588 prototype, holder, zone(), top_info())); |
| 7587 } | 7589 } |
| 7588 } | 7590 } |
| 7589 | 7591 |
| 7590 | 7592 |
| 7591 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 7593 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
| 7592 Handle<JSObject> holder, | 7594 Handle<JSObject> holder, |
| 7593 HValue* receiver, | 7595 HValue* receiver, |
| 7594 Handle<Map> receiver_map) { | 7596 Handle<Map> receiver_map) { |
| 7595 // Constant functions have the nice property that the map will change if they | 7597 // Constant functions have the nice property that the map will change if they |
| 7596 // are overwritten. Therefore it is enough to check the map of the holder and | 7598 // 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... |
| 7721 if (expr->check_type() == NUMBER_CHECK) { | 7723 if (expr->check_type() == NUMBER_CHECK) { |
| 7722 if_true->Goto(number_block); | 7724 if_true->Goto(number_block); |
| 7723 if_true = number_block; | 7725 if_true = number_block; |
| 7724 number_block->SetJoinId(expr->id()); | 7726 number_block->SetJoinId(expr->id()); |
| 7725 } | 7727 } |
| 7726 set_current_block(if_true); | 7728 set_current_block(if_true); |
| 7727 | 7729 |
| 7728 expr->ComputeTarget(map, name); | 7730 expr->ComputeTarget(map, name); |
| 7729 AddCheckPrototypeMaps(expr->holder(), map); | 7731 AddCheckPrototypeMaps(expr->holder(), map); |
| 7730 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 7732 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 7731 Handle<JSFunction> caller = info()->closure(); | 7733 Handle<JSFunction> caller = current_info()->closure(); |
| 7732 SmartArrayPointer<char> caller_name = | 7734 SmartArrayPointer<char> caller_name = |
| 7733 caller->shared()->DebugName()->ToCString(); | 7735 caller->shared()->DebugName()->ToCString(); |
| 7734 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 7736 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 7735 *name->ToCString(), | 7737 *name->ToCString(), |
| 7736 *caller_name); | 7738 *caller_name); |
| 7737 } | 7739 } |
| 7738 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 7740 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
| 7739 // Trying to inline will signal that we should bailout from the | 7741 // Trying to inline will signal that we should bailout from the |
| 7740 // entire compilation by setting stack overflow on the visitor. | 7742 // entire compilation by setting stack overflow on the visitor. |
| 7741 if (HasStackOverflow()) return; | 7743 if (HasStackOverflow()) return; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7805 | 7807 |
| 7806 | 7808 |
| 7807 static const int kNotInlinable = 1000000000; | 7809 static const int kNotInlinable = 1000000000; |
| 7808 | 7810 |
| 7809 | 7811 |
| 7810 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { | 7812 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) { |
| 7811 if (!FLAG_use_inlining) return kNotInlinable; | 7813 if (!FLAG_use_inlining) return kNotInlinable; |
| 7812 | 7814 |
| 7813 // Precondition: call is monomorphic and we have found a target with the | 7815 // Precondition: call is monomorphic and we have found a target with the |
| 7814 // appropriate arity. | 7816 // appropriate arity. |
| 7815 Handle<JSFunction> caller = info()->closure(); | 7817 Handle<JSFunction> caller = current_info()->closure(); |
| 7816 Handle<SharedFunctionInfo> target_shared(target->shared()); | 7818 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 7817 | 7819 |
| 7818 // Do a quick check on source code length to avoid parsing large | 7820 // Do a quick check on source code length to avoid parsing large |
| 7819 // inlining candidates. | 7821 // inlining candidates. |
| 7820 if (target_shared->SourceSize() > | 7822 if (target_shared->SourceSize() > |
| 7821 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { | 7823 Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) { |
| 7822 TraceInline(target, caller, "target text too big"); | 7824 TraceInline(target, caller, "target text too big"); |
| 7823 return kNotInlinable; | 7825 return kNotInlinable; |
| 7824 } | 7826 } |
| 7825 | 7827 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7841 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, | 7843 bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, |
| 7842 Handle<JSFunction> target, | 7844 Handle<JSFunction> target, |
| 7843 int arguments_count, | 7845 int arguments_count, |
| 7844 HValue* implicit_return_value, | 7846 HValue* implicit_return_value, |
| 7845 BailoutId ast_id, | 7847 BailoutId ast_id, |
| 7846 BailoutId return_id, | 7848 BailoutId return_id, |
| 7847 InliningKind inlining_kind) { | 7849 InliningKind inlining_kind) { |
| 7848 int nodes_added = InliningAstSize(target); | 7850 int nodes_added = InliningAstSize(target); |
| 7849 if (nodes_added == kNotInlinable) return false; | 7851 if (nodes_added == kNotInlinable) return false; |
| 7850 | 7852 |
| 7851 Handle<JSFunction> caller = info()->closure(); | 7853 Handle<JSFunction> caller = current_info()->closure(); |
| 7852 | 7854 |
| 7853 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 7855 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 7854 TraceInline(target, caller, "target AST is too large [early]"); | 7856 TraceInline(target, caller, "target AST is too large [early]"); |
| 7855 return false; | 7857 return false; |
| 7856 } | 7858 } |
| 7857 | 7859 |
| 7858 #if !defined(V8_TARGET_ARCH_IA32) | 7860 #if !defined(V8_TARGET_ARCH_IA32) |
| 7859 // Target must be able to use caller's context. | 7861 // Target must be able to use caller's context. |
| 7860 CompilationInfo* outer_info = info(); | 7862 CompilationInfo* outer_info = current_info(); |
| 7861 if (target->context() != outer_info->closure()->context() || | 7863 if (target->context() != outer_info->closure()->context() || |
| 7862 outer_info->scope()->contains_with() || | 7864 outer_info->scope()->contains_with() || |
| 7863 outer_info->scope()->num_heap_slots() > 0) { | 7865 outer_info->scope()->num_heap_slots() > 0) { |
| 7864 TraceInline(target, caller, "target requires context change"); | 7866 TraceInline(target, caller, "target requires context change"); |
| 7865 return false; | 7867 return false; |
| 7866 } | 7868 } |
| 7867 #endif | 7869 #endif |
| 7868 | 7870 |
| 7869 | 7871 |
| 7870 // Don't inline deeper than kMaxInliningLevels calls. | 7872 // Don't inline deeper than kMaxInliningLevels calls. |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8285 case kStringCharAt: | 8287 case kStringCharAt: |
| 8286 if (argument_count == 2 && check_type == STRING_CHECK) { | 8288 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 8287 HValue* index = Pop(); | 8289 HValue* index = Pop(); |
| 8288 HValue* string = Pop(); | 8290 HValue* string = Pop(); |
| 8289 HValue* context = environment()->LookupContext(); | 8291 HValue* context = environment()->LookupContext(); |
| 8290 ASSERT(!expr->holder().is_null()); | 8292 ASSERT(!expr->holder().is_null()); |
| 8291 AddInstruction(new(zone()) HCheckPrototypeMaps( | 8293 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 8292 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, | 8294 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, |
| 8293 expr->holder()->GetIsolate()), | 8295 expr->holder()->GetIsolate()), |
| 8294 expr->holder(), | 8296 expr->holder(), |
| 8295 zone())); | 8297 zone(), |
| 8298 top_info())); |
| 8296 HInstruction* char_code = | 8299 HInstruction* char_code = |
| 8297 BuildStringCharCodeAt(context, string, index); | 8300 BuildStringCharCodeAt(context, string, index); |
| 8298 if (id == kStringCharCodeAt) { | 8301 if (id == kStringCharCodeAt) { |
| 8299 ast_context()->ReturnInstruction(char_code, expr->id()); | 8302 ast_context()->ReturnInstruction(char_code, expr->id()); |
| 8300 return true; | 8303 return true; |
| 8301 } | 8304 } |
| 8302 AddInstruction(char_code); | 8305 AddInstruction(char_code); |
| 8303 HInstruction* result = | 8306 HInstruction* result = |
| 8304 HStringCharFromCode::New(zone(), context, char_code); | 8307 HStringCharFromCode::New(zone(), context, char_code); |
| 8305 ast_context()->ReturnInstruction(result, expr->id()); | 8308 ast_context()->ReturnInstruction(result, expr->id()); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8436 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { | 8439 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 8437 return false; | 8440 return false; |
| 8438 } | 8441 } |
| 8439 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 8442 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 8440 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 8443 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 8441 !expr->target()->shared()->HasBuiltinFunctionId() || | 8444 !expr->target()->shared()->HasBuiltinFunctionId() || |
| 8442 expr->target()->shared()->builtin_function_id() != kFunctionApply) { | 8445 expr->target()->shared()->builtin_function_id() != kFunctionApply) { |
| 8443 return false; | 8446 return false; |
| 8444 } | 8447 } |
| 8445 | 8448 |
| 8446 if (info()->scope()->arguments() == NULL) return false; | 8449 if (current_info()->scope()->arguments() == NULL) return false; |
| 8447 | 8450 |
| 8448 ZoneList<Expression*>* args = expr->arguments(); | 8451 ZoneList<Expression*>* args = expr->arguments(); |
| 8449 if (args->length() != 2) return false; | 8452 if (args->length() != 2) return false; |
| 8450 | 8453 |
| 8451 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 8454 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 8452 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 8455 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 8453 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | 8456 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 8454 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 8457 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 8455 | 8458 |
| 8456 // Found pattern f.apply(receiver, arguments). | 8459 // Found pattern f.apply(receiver, arguments). |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8677 | 8680 |
| 8678 if (global_call) { | 8681 if (global_call) { |
| 8679 Variable* var = proxy->var(); | 8682 Variable* var = proxy->var(); |
| 8680 bool known_global_function = false; | 8683 bool known_global_function = false; |
| 8681 // If there is a global property cell for the name at compile time and | 8684 // If there is a global property cell for the name at compile time and |
| 8682 // access check is not enabled we assume that the function will not change | 8685 // access check is not enabled we assume that the function will not change |
| 8683 // and generate optimized code for calling the function. | 8686 // and generate optimized code for calling the function. |
| 8684 LookupResult lookup(isolate()); | 8687 LookupResult lookup(isolate()); |
| 8685 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 8688 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 8686 if (type == kUseCell && | 8689 if (type == kUseCell && |
| 8687 !info()->global_object()->IsAccessCheckNeeded()) { | 8690 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 8688 Handle<GlobalObject> global(info()->global_object()); | 8691 Handle<GlobalObject> global(current_info()->global_object()); |
| 8689 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 8692 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 8690 } | 8693 } |
| 8691 if (known_global_function) { | 8694 if (known_global_function) { |
| 8692 // Push the global object instead of the global receiver because | 8695 // Push the global object instead of the global receiver because |
| 8693 // code generated by the full code generator expects it. | 8696 // code generated by the full code generator expects it. |
| 8694 HValue* context = environment()->LookupContext(); | 8697 HValue* context = environment()->LookupContext(); |
| 8695 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 8698 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 8696 PushAndAdd(global_object); | 8699 PushAndAdd(global_object); |
| 8697 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8700 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8698 | 8701 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 8713 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. | 8716 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. |
| 8714 if (FLAG_trace_inlining) { | 8717 if (FLAG_trace_inlining) { |
| 8715 PrintF("Inlining builtin "); | 8718 PrintF("Inlining builtin "); |
| 8716 expr->target()->ShortPrint(); | 8719 expr->target()->ShortPrint(); |
| 8717 PrintF("\n"); | 8720 PrintF("\n"); |
| 8718 } | 8721 } |
| 8719 return; | 8722 return; |
| 8720 } | 8723 } |
| 8721 if (TryInlineCall(expr)) return; | 8724 if (TryInlineCall(expr)) return; |
| 8722 | 8725 |
| 8723 if (expr->target().is_identical_to(info()->closure())) { | 8726 if (expr->target().is_identical_to(current_info()->closure())) { |
| 8724 graph()->MarkRecursive(); | 8727 graph()->MarkRecursive(); |
| 8725 } | 8728 } |
| 8726 | 8729 |
| 8727 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 8730 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 8728 argument_count)); | 8731 argument_count)); |
| 8729 } else { | 8732 } else { |
| 8730 HValue* context = environment()->LookupContext(); | 8733 HValue* context = environment()->LookupContext(); |
| 8731 HGlobalObject* receiver = new(zone()) HGlobalObject(context); | 8734 HGlobalObject* receiver = new(zone()) HGlobalObject(context); |
| 8732 AddInstruction(receiver); | 8735 AddInstruction(receiver); |
| 8733 PushAndAdd(new(zone()) HPushArgument(receiver)); | 8736 PushAndAdd(new(zone()) HPushArgument(receiver)); |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9223 | 9226 |
| 9224 case Variable::PARAMETER: | 9227 case Variable::PARAMETER: |
| 9225 case Variable::LOCAL: | 9228 case Variable::LOCAL: |
| 9226 BindIfLive(var, after); | 9229 BindIfLive(var, after); |
| 9227 break; | 9230 break; |
| 9228 | 9231 |
| 9229 case Variable::CONTEXT: { | 9232 case Variable::CONTEXT: { |
| 9230 // Bail out if we try to mutate a parameter value in a function | 9233 // Bail out if we try to mutate a parameter value in a function |
| 9231 // using the arguments object. We do not (yet) correctly handle the | 9234 // using the arguments object. We do not (yet) correctly handle the |
| 9232 // arguments property of the function. | 9235 // arguments property of the function. |
| 9233 if (info()->scope()->arguments() != NULL) { | 9236 if (current_info()->scope()->arguments() != NULL) { |
| 9234 // Parameters will rewrite to context slots. We have no direct | 9237 // Parameters will rewrite to context slots. We have no direct |
| 9235 // way to detect that the variable is a parameter so we use a | 9238 // way to detect that the variable is a parameter so we use a |
| 9236 // linear search of the parameter list. | 9239 // linear search of the parameter list. |
| 9237 int count = info()->scope()->num_parameters(); | 9240 int count = current_info()->scope()->num_parameters(); |
| 9238 for (int i = 0; i < count; ++i) { | 9241 for (int i = 0; i < count; ++i) { |
| 9239 if (var == info()->scope()->parameter(i)) { | 9242 if (var == current_info()->scope()->parameter(i)) { |
| 9240 return Bailout("assignment to parameter in arguments object"); | 9243 return Bailout("assignment to parameter in arguments object"); |
| 9241 } | 9244 } |
| 9242 } | 9245 } |
| 9243 } | 9246 } |
| 9244 | 9247 |
| 9245 HValue* context = BuildContextChainWalk(var); | 9248 HValue* context = BuildContextChainWalk(var); |
| 9246 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 9249 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
| 9247 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 9250 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
| 9248 HStoreContextSlot* instr = | 9251 HStoreContextSlot* instr = |
| 9249 new(zone()) HStoreContextSlot(context, var->index(), mode, after); | 9252 new(zone()) HStoreContextSlot(context, var->index(), mode, after); |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9828 } | 9831 } |
| 9829 | 9832 |
| 9830 if (op == Token::INSTANCEOF) { | 9833 if (op == Token::INSTANCEOF) { |
| 9831 // Check to see if the rhs of the instanceof is a global function not | 9834 // Check to see if the rhs of the instanceof is a global function not |
| 9832 // residing in new space. If it is we assume that the function will stay the | 9835 // residing in new space. If it is we assume that the function will stay the |
| 9833 // same. | 9836 // same. |
| 9834 Handle<JSFunction> target = Handle<JSFunction>::null(); | 9837 Handle<JSFunction> target = Handle<JSFunction>::null(); |
| 9835 VariableProxy* proxy = expr->right()->AsVariableProxy(); | 9838 VariableProxy* proxy = expr->right()->AsVariableProxy(); |
| 9836 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); | 9839 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); |
| 9837 if (global_function && | 9840 if (global_function && |
| 9838 info()->has_global_object() && | 9841 current_info()->has_global_object() && |
| 9839 !info()->global_object()->IsAccessCheckNeeded()) { | 9842 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 9840 Handle<String> name = proxy->name(); | 9843 Handle<String> name = proxy->name(); |
| 9841 Handle<GlobalObject> global(info()->global_object()); | 9844 Handle<GlobalObject> global(current_info()->global_object()); |
| 9842 LookupResult lookup(isolate()); | 9845 LookupResult lookup(isolate()); |
| 9843 global->Lookup(*name, &lookup); | 9846 global->Lookup(*name, &lookup); |
| 9844 if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) { | 9847 if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) { |
| 9845 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); | 9848 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); |
| 9846 // If the function is in new space we assume it's more likely to | 9849 // If the function is in new space we assume it's more likely to |
| 9847 // change and thus prefer the general IC code. | 9850 // change and thus prefer the general IC code. |
| 9848 if (!isolate()->heap()->InNewSpace(*candidate)) { | 9851 if (!isolate()->heap()->InNewSpace(*candidate)) { |
| 9849 target = candidate; | 9852 target = candidate; |
| 9850 } | 9853 } |
| 9851 } | 9854 } |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10271 | 10274 |
| 10272 | 10275 |
| 10273 void HOptimizedGraphBuilder::VisitDeclarations( | 10276 void HOptimizedGraphBuilder::VisitDeclarations( |
| 10274 ZoneList<Declaration*>* declarations) { | 10277 ZoneList<Declaration*>* declarations) { |
| 10275 ASSERT(globals_.is_empty()); | 10278 ASSERT(globals_.is_empty()); |
| 10276 AstVisitor::VisitDeclarations(declarations); | 10279 AstVisitor::VisitDeclarations(declarations); |
| 10277 if (!globals_.is_empty()) { | 10280 if (!globals_.is_empty()) { |
| 10278 Handle<FixedArray> array = | 10281 Handle<FixedArray> array = |
| 10279 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 10282 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
| 10280 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 10283 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
| 10281 int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 10284 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | |
| 10282 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 10285 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | |
| 10283 DeclareGlobalsLanguageMode::encode(info()->language_mode()); | 10286 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); |
| 10284 HInstruction* result = new(zone()) HDeclareGlobals( | 10287 HInstruction* result = new(zone()) HDeclareGlobals( |
| 10285 environment()->LookupContext(), array, flags); | 10288 environment()->LookupContext(), array, flags); |
| 10286 AddInstruction(result); | 10289 AddInstruction(result); |
| 10287 globals_.Clear(); | 10290 globals_.Clear(); |
| 10288 } | 10291 } |
| 10289 } | 10292 } |
| 10290 | 10293 |
| 10291 | 10294 |
| 10292 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 10295 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
| 10293 VariableDeclaration* declaration) { | 10296 VariableDeclaration* declaration) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10327 } | 10330 } |
| 10328 | 10331 |
| 10329 | 10332 |
| 10330 void HOptimizedGraphBuilder::VisitFunctionDeclaration( | 10333 void HOptimizedGraphBuilder::VisitFunctionDeclaration( |
| 10331 FunctionDeclaration* declaration) { | 10334 FunctionDeclaration* declaration) { |
| 10332 VariableProxy* proxy = declaration->proxy(); | 10335 VariableProxy* proxy = declaration->proxy(); |
| 10333 Variable* variable = proxy->var(); | 10336 Variable* variable = proxy->var(); |
| 10334 switch (variable->location()) { | 10337 switch (variable->location()) { |
| 10335 case Variable::UNALLOCATED: { | 10338 case Variable::UNALLOCATED: { |
| 10336 globals_.Add(variable->name(), zone()); | 10339 globals_.Add(variable->name(), zone()); |
| 10337 Handle<SharedFunctionInfo> function = | 10340 Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo( |
| 10338 Compiler::BuildFunctionInfo(declaration->fun(), info()->script()); | 10341 declaration->fun(), current_info()->script()); |
| 10339 // Check for stack-overflow exception. | 10342 // Check for stack-overflow exception. |
| 10340 if (function.is_null()) return SetStackOverflow(); | 10343 if (function.is_null()) return SetStackOverflow(); |
| 10341 globals_.Add(function, zone()); | 10344 globals_.Add(function, zone()); |
| 10342 return; | 10345 return; |
| 10343 } | 10346 } |
| 10344 case Variable::PARAMETER: | 10347 case Variable::PARAMETER: |
| 10345 case Variable::LOCAL: { | 10348 case Variable::LOCAL: { |
| 10346 CHECK_ALIVE(VisitForValue(declaration->fun())); | 10349 CHECK_ALIVE(VisitForValue(declaration->fun())); |
| 10347 HValue* value = Pop(); | 10350 HValue* value = Pop(); |
| 10348 BindIfLive(variable, value); | 10351 BindIfLive(variable, value); |
| (...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11609 } | 11612 } |
| 11610 } | 11613 } |
| 11611 | 11614 |
| 11612 #ifdef DEBUG | 11615 #ifdef DEBUG |
| 11613 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11616 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11614 if (allocator_ != NULL) allocator_->Verify(); | 11617 if (allocator_ != NULL) allocator_->Verify(); |
| 11615 #endif | 11618 #endif |
| 11616 } | 11619 } |
| 11617 | 11620 |
| 11618 } } // namespace v8::internal | 11621 } } // namespace v8::internal |
| OLD | NEW |