| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 4637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4648 if (lookup.IsFound()) return false; | 4648 if (lookup.IsFound()) return false; |
| 4649 if (!lookup.IsCacheable()) return false; | 4649 if (!lookup.IsCacheable()) return false; |
| 4650 current = JSObject::cast(current)->GetPrototype(); | 4650 current = JSObject::cast(current)->GetPrototype(); |
| 4651 } | 4651 } |
| 4652 return true; | 4652 return true; |
| 4653 } | 4653 } |
| 4654 | 4654 |
| 4655 | 4655 |
| 4656 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4656 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 4657 int position, | 4657 int position, |
| 4658 BailoutId return_id, | 4658 BailoutId ast_id, |
| 4659 HValue* object, | 4659 HValue* object, |
| 4660 SmallMapList* types, | 4660 SmallMapList* types, |
| 4661 Handle<String> name) { | 4661 Handle<String> name) { |
| 4662 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(object, types, name); | 4662 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(object, types, name); |
| 4663 if (instr != NULL) { | 4663 if (instr != NULL) { |
| 4664 instr->set_position(position); | 4664 instr->set_position(position); |
| 4665 return ast_context()->ReturnInstruction(instr, return_id); | 4665 return ast_context()->ReturnInstruction(instr, ast_id); |
| 4666 } | 4666 } |
| 4667 | 4667 |
| 4668 // Something did not match; must use a polymorphic load. | 4668 // Something did not match; must use a polymorphic load. |
| 4669 int count = 0; | 4669 int count = 0; |
| 4670 HBasicBlock* join = NULL; | 4670 HBasicBlock* join = NULL; |
| 4671 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 4671 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 4672 Handle<Map> map = types->at(i); | 4672 Handle<Map> map = types->at(i); |
| 4673 LookupResult lookup(isolate()); | 4673 LookupResult lookup(isolate()); |
| 4674 if (ComputeLoadStoreField(map, name, &lookup, false) || | 4674 if (ComputeLoadStoreField(map, name, &lookup, false) || |
| 4675 (lookup.IsCacheable() && | 4675 (lookup.IsCacheable() && |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4727 } else { | 4727 } else { |
| 4728 HValue* context = environment()->context(); | 4728 HValue* context = environment()->context(); |
| 4729 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); | 4729 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); |
| 4730 load->set_position(position); | 4730 load->set_position(position); |
| 4731 AddInstruction(load); | 4731 AddInstruction(load); |
| 4732 if (!ast_context()->IsEffect()) Push(load); | 4732 if (!ast_context()->IsEffect()) Push(load); |
| 4733 | 4733 |
| 4734 if (join != NULL) { | 4734 if (join != NULL) { |
| 4735 current_block()->Goto(join); | 4735 current_block()->Goto(join); |
| 4736 } else { | 4736 } else { |
| 4737 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 4737 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 4738 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4738 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 4739 return; | 4739 return; |
| 4740 } | 4740 } |
| 4741 } | 4741 } |
| 4742 | 4742 |
| 4743 ASSERT(join != NULL); | 4743 ASSERT(join != NULL); |
| 4744 join->SetJoinId(return_id); | 4744 join->SetJoinId(ast_id); |
| 4745 set_current_block(join); | 4745 set_current_block(join); |
| 4746 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4746 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 4747 } | 4747 } |
| 4748 | 4748 |
| 4749 | 4749 |
| 4750 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 4750 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
| 4751 int position, | 4751 int position, |
| 4752 BailoutId assignment_id, | 4752 BailoutId assignment_id, |
| 4753 HValue* object, | 4753 HValue* object, |
| 4754 HValue* value, | 4754 HValue* value, |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5115 case Variable::LOOKUP: | 5115 case Variable::LOOKUP: |
| 5116 return Bailout(kCompoundAssignmentToLookupSlot); | 5116 return Bailout(kCompoundAssignmentToLookupSlot); |
| 5117 } | 5117 } |
| 5118 return ast_context()->ReturnValue(Pop()); | 5118 return ast_context()->ReturnValue(Pop()); |
| 5119 | 5119 |
| 5120 } else if (prop != NULL) { | 5120 } else if (prop != NULL) { |
| 5121 if (prop->key()->IsPropertyName()) { | 5121 if (prop->key()->IsPropertyName()) { |
| 5122 // Named property. | 5122 // Named property. |
| 5123 CHECK_ALIVE(VisitForValue(prop->obj())); | 5123 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5124 HValue* object = Top(); | 5124 HValue* object = Top(); |
| 5125 PushLoad(prop, object, expr->position(), expr->id(), prop->LoadId()); | 5125 PushLoad(prop, object, expr->position()); |
| 5126 | 5126 |
| 5127 CHECK_ALIVE(VisitForValue(expr->value())); | 5127 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5128 HValue* right = Pop(); | 5128 HValue* right = Pop(); |
| 5129 HValue* left = Pop(); | 5129 HValue* left = Pop(); |
| 5130 | 5130 |
| 5131 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5131 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5132 PushAndAdd(instr); | 5132 PushAndAdd(instr); |
| 5133 if (instr->HasObservableSideEffects()) { | 5133 if (instr->HasObservableSideEffects()) { |
| 5134 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); | 5134 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
| 5135 } | 5135 } |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5818 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 5818 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
| 5819 } | 5819 } |
| 5820 } | 5820 } |
| 5821 ast_context()->ReturnInstruction(result, expr->id()); | 5821 ast_context()->ReturnInstruction(result, expr->id()); |
| 5822 return true; | 5822 return true; |
| 5823 } | 5823 } |
| 5824 | 5824 |
| 5825 | 5825 |
| 5826 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 5826 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
| 5827 HValue* object, | 5827 HValue* object, |
| 5828 int position, | 5828 int position) { |
| 5829 BailoutId ast_id, | |
| 5830 BailoutId return_id) { | |
| 5831 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 5829 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
| 5832 Push(object); | 5830 Push(object); |
| 5833 BuildLoad(expr, position, ast_id, return_id); | 5831 BuildLoad(expr, position, expr->LoadId()); |
| 5834 } | 5832 } |
| 5835 | 5833 |
| 5836 | 5834 |
| 5837 void HOptimizedGraphBuilder::BuildLoad(Property* expr, | 5835 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
| 5838 int position, | 5836 int position, |
| 5839 BailoutId ast_id, | 5837 BailoutId ast_id) { |
| 5840 BailoutId return_id) { | |
| 5841 HInstruction* instr = NULL; | 5838 HInstruction* instr = NULL; |
| 5842 if (expr->IsStringLength()) { | 5839 if (expr->IsStringLength()) { |
| 5843 HValue* string = Pop(); | 5840 HValue* string = Pop(); |
| 5844 BuildCheckHeapObject(string); | 5841 BuildCheckHeapObject(string); |
| 5845 HInstruction* checkstring = | 5842 HInstruction* checkstring = |
| 5846 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 5843 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 5847 instr = BuildLoadStringLength(string, checkstring); | 5844 instr = BuildLoadStringLength(string, checkstring); |
| 5848 } else if (expr->IsStringAccess()) { | 5845 } else if (expr->IsStringAccess()) { |
| 5849 CHECK_ALIVE(VisitForValue(expr->key())); | 5846 CHECK_ALIVE(VisitForValue(expr->key())); |
| 5850 HValue* index = Pop(); | 5847 HValue* index = Pop(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 5872 monomorphic = CanInlinePropertyAccess(*map); | 5869 monomorphic = CanInlinePropertyAccess(*map); |
| 5873 } else if (object->HasMonomorphicJSObjectType()) { | 5870 } else if (object->HasMonomorphicJSObjectType()) { |
| 5874 map = object->GetMonomorphicJSObjectMap(); | 5871 map = object->GetMonomorphicJSObjectMap(); |
| 5875 monomorphic = CanInlinePropertyAccess(*map); | 5872 monomorphic = CanInlinePropertyAccess(*map); |
| 5876 } | 5873 } |
| 5877 if (monomorphic) { | 5874 if (monomorphic) { |
| 5878 Handle<JSFunction> getter; | 5875 Handle<JSFunction> getter; |
| 5879 Handle<JSObject> holder; | 5876 Handle<JSObject> holder; |
| 5880 if (LookupGetter(map, name, &getter, &holder)) { | 5877 if (LookupGetter(map, name, &getter, &holder)) { |
| 5881 AddCheckConstantFunction(holder, Top(), map); | 5878 AddCheckConstantFunction(holder, Top(), map); |
| 5882 if (FLAG_inline_accessors && TryInlineGetter(getter, return_id)) return; | 5879 if (FLAG_inline_accessors && |
| 5880 TryInlineGetter(getter, ast_id, expr->LoadId())) { |
| 5881 return; |
| 5882 } |
| 5883 Add<HPushArgument>(Pop()); | 5883 Add<HPushArgument>(Pop()); |
| 5884 instr = new(zone()) HCallConstantFunction(getter, 1); | 5884 instr = new(zone()) HCallConstantFunction(getter, 1); |
| 5885 } else { | 5885 } else { |
| 5886 instr = BuildLoadNamedMonomorphic(Pop(), name, map); | 5886 instr = BuildLoadNamedMonomorphic(Pop(), name, map); |
| 5887 } | 5887 } |
| 5888 } else if (types != NULL && types->length() > 1) { | 5888 } else if (types != NULL && types->length() > 1) { |
| 5889 return HandlePolymorphicLoadNamedField( | 5889 return HandlePolymorphicLoadNamedField( |
| 5890 position, return_id, Pop(), types, name); | 5890 position, ast_id, Pop(), types, name); |
| 5891 } else { | 5891 } else { |
| 5892 instr = BuildLoadNamedGeneric(Pop(), name, expr); | 5892 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
| 5893 } | 5893 } |
| 5894 | 5894 |
| 5895 } else { | 5895 } else { |
| 5896 CHECK_ALIVE(VisitForValue(expr->key())); | 5896 CHECK_ALIVE(VisitForValue(expr->key())); |
| 5897 | 5897 |
| 5898 HValue* key = Pop(); | 5898 HValue* key = Pop(); |
| 5899 HValue* obj = Pop(); | 5899 HValue* obj = Pop(); |
| 5900 | 5900 |
| 5901 bool has_side_effects = false; | 5901 bool has_side_effects = false; |
| 5902 HValue* load = HandleKeyedElementAccess( | 5902 HValue* load = HandleKeyedElementAccess( |
| 5903 obj, key, NULL, expr, return_id, position, | 5903 obj, key, NULL, expr, ast_id, position, |
| 5904 false, // is_store | 5904 false, // is_store |
| 5905 &has_side_effects); | 5905 &has_side_effects); |
| 5906 if (has_side_effects) { | 5906 if (has_side_effects) { |
| 5907 if (ast_context()->IsEffect()) { | 5907 if (ast_context()->IsEffect()) { |
| 5908 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 5908 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5909 } else { | 5909 } else { |
| 5910 Push(load); | 5910 Push(load); |
| 5911 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 5911 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5912 Drop(1); | 5912 Drop(1); |
| 5913 } | 5913 } |
| 5914 } | 5914 } |
| 5915 return ast_context()->ReturnValue(load); | 5915 return ast_context()->ReturnValue(load); |
| 5916 } | 5916 } |
| 5917 instr->set_position(position); | 5917 instr->set_position(position); |
| 5918 return ast_context()->ReturnInstruction(instr, return_id); | 5918 return ast_context()->ReturnInstruction(instr, ast_id); |
| 5919 } | 5919 } |
| 5920 | 5920 |
| 5921 | 5921 |
| 5922 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 5922 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
| 5923 ASSERT(!HasStackOverflow()); | 5923 ASSERT(!HasStackOverflow()); |
| 5924 ASSERT(current_block() != NULL); | 5924 ASSERT(current_block() != NULL); |
| 5925 ASSERT(current_block()->HasPredecessor()); | 5925 ASSERT(current_block()->HasPredecessor()); |
| 5926 | 5926 |
| 5927 if (TryArgumentsAccess(expr)) return; | 5927 if (TryArgumentsAccess(expr)) return; |
| 5928 | 5928 |
| 5929 CHECK_ALIVE(VisitForValue(expr->obj())); | 5929 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 5930 BuildLoad(expr, expr->position(), expr->id(), expr->id()); | 5930 BuildLoad(expr, expr->position(), expr->id()); |
| 5931 } | 5931 } |
| 5932 | 5932 |
| 5933 | 5933 |
| 5934 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 5934 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
| 5935 CompilationInfo* info) { | 5935 CompilationInfo* info) { |
| 5936 HConstant* constant_value = New<HConstant>(constant); | 5936 HConstant* constant_value = New<HConstant>(constant); |
| 5937 | 5937 |
| 5938 if (constant->map()->CanOmitMapChecks()) { | 5938 if (constant->map()->CanOmitMapChecks()) { |
| 5939 constant->map()->AddDependentCompilationInfo( | 5939 constant->map()->AddDependentCompilationInfo( |
| 5940 DependentCode::kPrototypeCheckGroup, info); | 5940 DependentCode::kPrototypeCheckGroup, info); |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6597 expr->target(), | 6597 expr->target(), |
| 6598 expr->arguments()->length(), | 6598 expr->arguments()->length(), |
| 6599 implicit_return_value, | 6599 implicit_return_value, |
| 6600 expr->id(), | 6600 expr->id(), |
| 6601 expr->ReturnId(), | 6601 expr->ReturnId(), |
| 6602 CONSTRUCT_CALL_RETURN); | 6602 CONSTRUCT_CALL_RETURN); |
| 6603 } | 6603 } |
| 6604 | 6604 |
| 6605 | 6605 |
| 6606 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 6606 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
| 6607 BailoutId ast_id, |
| 6607 BailoutId return_id) { | 6608 BailoutId return_id) { |
| 6608 return TryInline(CALL_AS_METHOD, | 6609 return TryInline(CALL_AS_METHOD, |
| 6609 getter, | 6610 getter, |
| 6610 0, | 6611 0, |
| 6611 NULL, | 6612 NULL, |
| 6612 return_id, | 6613 ast_id, |
| 6613 return_id, | 6614 return_id, |
| 6614 GETTER_CALL_RETURN); | 6615 GETTER_CALL_RETURN); |
| 6615 } | 6616 } |
| 6616 | 6617 |
| 6617 | 6618 |
| 6618 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 6619 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
| 6619 BailoutId id, | 6620 BailoutId id, |
| 6620 BailoutId assignment_id, | 6621 BailoutId assignment_id, |
| 6621 HValue* implicit_return_value) { | 6622 HValue* implicit_return_value) { |
| 6622 return TryInline(CALL_AS_METHOD, | 6623 return TryInline(CALL_AS_METHOD, |
| (...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7553 } else { | 7554 } else { |
| 7554 // Argument of the count operation is a property. | 7555 // Argument of the count operation is a property. |
| 7555 ASSERT(prop != NULL); | 7556 ASSERT(prop != NULL); |
| 7556 | 7557 |
| 7557 if (prop->key()->IsPropertyName()) { | 7558 if (prop->key()->IsPropertyName()) { |
| 7558 // Named property. | 7559 // Named property. |
| 7559 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7560 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 7560 | 7561 |
| 7561 CHECK_ALIVE(VisitForValue(prop->obj())); | 7562 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7562 HValue* object = Top(); | 7563 HValue* object = Top(); |
| 7563 PushLoad(prop, object, expr->position(), expr->id(), prop->LoadId()); | 7564 PushLoad(prop, object, expr->position()); |
| 7564 | 7565 |
| 7565 after = BuildIncrement(returns_original_input, expr); | 7566 after = BuildIncrement(returns_original_input, expr); |
| 7566 | 7567 |
| 7567 if (returns_original_input) { | 7568 if (returns_original_input) { |
| 7568 HValue* result = Pop(); | 7569 HValue* result = Pop(); |
| 7569 HValue* object = Pop(); | 7570 HValue* object = Pop(); |
| 7570 environment()->SetExpressionStackAt(0, result); | 7571 environment()->SetExpressionStackAt(0, result); |
| 7571 { | 7572 { |
| 7572 EffectContext for_effect(this); | 7573 EffectContext for_effect(this); |
| 7573 Push(object); | 7574 Push(object); |
| (...skipping 2139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9713 if (ShouldProduceTraceOutput()) { | 9714 if (ShouldProduceTraceOutput()) { |
| 9714 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9715 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9715 } | 9716 } |
| 9716 | 9717 |
| 9717 #ifdef DEBUG | 9718 #ifdef DEBUG |
| 9718 graph_->Verify(false); // No full verify. | 9719 graph_->Verify(false); // No full verify. |
| 9719 #endif | 9720 #endif |
| 9720 } | 9721 } |
| 9721 | 9722 |
| 9722 } } // namespace v8::internal | 9723 } } // namespace v8::internal |
| OLD | NEW |