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 5059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5070 Handle<String> name = property->key()->AsPropertyName(); | 5070 Handle<String> name = property->key()->AsPropertyName(); |
5071 HInstruction* store; | 5071 HInstruction* store; |
5072 if (map.is_null()) { | 5072 if (map.is_null()) { |
5073 // If we don't know the monomorphic type, do a generic store. | 5073 // If we don't know the monomorphic type, do a generic store. |
5074 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); | 5074 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); |
5075 } else { | 5075 } else { |
5076 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5076 PropertyAccessInfo info(this, STORE, ToType(map), name); |
5077 if (info.CanAccessMonomorphic()) { | 5077 if (info.CanAccessMonomorphic()) { |
5078 HValue* checked_literal = BuildCheckMap(literal, map); | 5078 HValue* checked_literal = BuildCheckMap(literal, map); |
5079 ASSERT(!info.lookup()->IsPropertyCallbacks()); | 5079 ASSERT(!info.lookup()->IsPropertyCallbacks()); |
5080 store = BuildStoreMonomorphic( | 5080 store = BuildMonomorphicAccess( |
5081 &info, checked_literal, value, | 5081 &info, literal, checked_literal, value, |
5082 BailoutId::None(), BailoutId::None()); | 5082 BailoutId::None(), BailoutId::None()); |
5083 } else { | 5083 } else { |
5084 CHECK_ALIVE( | 5084 CHECK_ALIVE( |
5085 store = BuildStoreNamedGeneric(literal, name, value)); | 5085 store = BuildStoreNamedGeneric(literal, name, value)); |
5086 } | 5086 } |
5087 } | 5087 } |
5088 AddInstruction(store); | 5088 AddInstruction(store); |
5089 if (store->HasObservableSideEffects()) { | 5089 if (store->HasObservableSideEffects()) { |
5090 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5090 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
5091 } | 5091 } |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5512 } | 5512 } |
5513 | 5513 |
5514 | 5514 |
5515 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { | 5515 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) { |
5516 return type->Is(Type::NumberOrString()) && | 5516 return type->Is(Type::NumberOrString()) && |
5517 target->shared()->is_classic_mode() && | 5517 target->shared()->is_classic_mode() && |
5518 !target->shared()->native(); | 5518 !target->shared()->native(); |
5519 } | 5519 } |
5520 | 5520 |
5521 | 5521 |
5522 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( | 5522 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( |
5523 PropertyAccessInfo* info, | 5523 PropertyAccessInfo* info, |
5524 HValue* object, | 5524 HValue* object, |
5525 HValue* checked_object, | 5525 HValue* checked_object, |
| 5526 HValue* value, |
5526 BailoutId ast_id, | 5527 BailoutId ast_id, |
5527 BailoutId return_id, | 5528 BailoutId return_id, |
5528 bool can_inline_accessor) { | 5529 bool can_inline_accessor) { |
5529 | 5530 |
5530 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 5531 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
5531 if (info->GetJSObjectFieldAccess(&access)) { | 5532 if (info->GetJSObjectFieldAccess(&access)) { |
5532 return New<HLoadNamedField>( | 5533 ASSERT(info->IsLoad()); |
5533 checked_object, static_cast<HValue*>(NULL), access); | 5534 return New<HLoadNamedField>(object, checked_object, access); |
5534 } | 5535 } |
5535 | 5536 |
5536 HValue* checked_holder = checked_object; | 5537 HValue* checked_holder = checked_object; |
5537 if (info->has_holder()) { | 5538 if (info->has_holder()) { |
5538 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 5539 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
5539 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 5540 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
5540 } | 5541 } |
5541 | 5542 |
5542 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); | 5543 if (!info->lookup()->IsFound()) { |
| 5544 ASSERT(info->IsLoad()); |
| 5545 return graph()->GetConstantUndefined(); |
| 5546 } |
5543 | 5547 |
5544 if (info->lookup()->IsField()) { | 5548 if (info->lookup()->IsField()) { |
5545 return BuildLoadNamedField(checked_holder, info->access()); | 5549 if (info->IsLoad()) { |
| 5550 return BuildLoadNamedField(checked_holder, info->access()); |
| 5551 } else { |
| 5552 return BuildStoreNamedField(info, checked_object, value); |
| 5553 } |
| 5554 } |
| 5555 |
| 5556 if (info->lookup()->IsTransition()) { |
| 5557 ASSERT(!info->IsLoad()); |
| 5558 return BuildStoreNamedField(info, checked_object, value); |
5546 } | 5559 } |
5547 | 5560 |
5548 if (info->lookup()->IsPropertyCallbacks()) { | 5561 if (info->lookup()->IsPropertyCallbacks()) { |
| 5562 Push(checked_object); |
| 5563 int argument_count = 1; |
| 5564 if (!info->IsLoad()) { |
| 5565 argument_count = 2; |
| 5566 Push(value); |
| 5567 } |
| 5568 |
5549 if (NeedsWrappingFor(info->type(), info->accessor())) { | 5569 if (NeedsWrappingFor(info->type(), info->accessor())) { |
5550 HValue* function = Add<HConstant>(info->accessor()); | 5570 HValue* function = Add<HConstant>(info->accessor()); |
5551 Add<HPushArgument>(checked_object); | 5571 PushArgumentsFromEnvironment(argument_count); |
5552 return New<HCallFunction>(function, 1, WRAP_AND_CALL); | 5572 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); |
5553 } else { | 5573 } else if (FLAG_inline_accessors && can_inline_accessor) { |
5554 Push(checked_object); | 5574 bool success = info->IsLoad() |
5555 if (FLAG_inline_accessors && | 5575 ? TryInlineGetter(info->accessor(), ast_id, return_id) |
5556 can_inline_accessor && | 5576 : TryInlineSetter(info->accessor(), ast_id, return_id, value); |
5557 TryInlineGetter(info->accessor(), ast_id, return_id)) { | 5577 if (success) return NULL; |
5558 return NULL; | |
5559 } | |
5560 Add<HPushArgument>(Pop()); | |
5561 return BuildCallConstantFunction(info->accessor(), 1); | |
5562 } | 5578 } |
| 5579 |
| 5580 PushArgumentsFromEnvironment(argument_count); |
| 5581 return BuildCallConstantFunction(info->accessor(), argument_count); |
5563 } | 5582 } |
5564 | 5583 |
5565 ASSERT(info->lookup()->IsConstant()); | 5584 ASSERT(info->lookup()->IsConstant()); |
5566 return New<HConstant>(info->constant()); | 5585 if (info->IsLoad()) { |
| 5586 return New<HConstant>(info->constant()); |
| 5587 } else { |
| 5588 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
| 5589 } |
5567 } | 5590 } |
5568 | 5591 |
5569 | 5592 |
5570 HInstruction* HOptimizedGraphBuilder::BuildStoreMonomorphic( | |
5571 PropertyAccessInfo* info, | |
5572 HValue* checked_object, | |
5573 HValue* value, | |
5574 BailoutId ast_id, | |
5575 BailoutId return_id, | |
5576 bool can_inline_accessor) { | |
5577 ASSERT(!info->IsJSObjectFieldAccessor()); | |
5578 | |
5579 if (info->has_holder()) { | |
5580 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | |
5581 BuildCheckPrototypeMaps(prototype, info->holder()); | |
5582 } | |
5583 | |
5584 if (info->lookup()->IsPropertyCallbacks()) { | |
5585 if (NeedsWrappingFor(info->type(), info->accessor())) { | |
5586 HValue* function = Add<HConstant>(info->accessor()); | |
5587 Add<HPushArgument>(checked_object); | |
5588 Add<HPushArgument>(value); | |
5589 return New<HCallFunction>(function, 2, WRAP_AND_CALL); | |
5590 } else { | |
5591 Push(checked_object); | |
5592 Push(value); | |
5593 if (FLAG_inline_accessors && | |
5594 can_inline_accessor && | |
5595 TryInlineSetter(info->accessor(), ast_id, return_id, value)) { | |
5596 return NULL; | |
5597 } | |
5598 PushArgumentsFromEnvironment(2); | |
5599 return BuildCallConstantFunction(info->accessor(), 2); | |
5600 } | |
5601 } | |
5602 | |
5603 if (info->lookup()->IsConstant()) { | |
5604 // Check whether we are trying to store the same constant. | |
5605 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | |
5606 } | |
5607 | |
5608 ASSERT(info->lookup()->IsField() || info->lookup()->IsTransition()); | |
5609 return BuildStoreNamedField(info, checked_object, value); | |
5610 } | |
5611 | |
5612 | |
5613 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( | 5593 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
5614 PropertyAccessType access_type, | 5594 PropertyAccessType access_type, |
5615 BailoutId ast_id, | 5595 BailoutId ast_id, |
5616 BailoutId return_id, | 5596 BailoutId return_id, |
5617 HValue* object, | 5597 HValue* object, |
5618 HValue* value, | 5598 HValue* value, |
5619 SmallMapList* types, | 5599 SmallMapList* types, |
5620 Handle<String> name) { | 5600 Handle<String> name) { |
5621 // Something did not match; must use a polymorphic load. | 5601 // Something did not match; must use a polymorphic load. |
5622 int count = 0; | 5602 int count = 0; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5688 FinishCurrentBlock(compare); | 5668 FinishCurrentBlock(compare); |
5689 | 5669 |
5690 if (info.type()->Is(Type::Number())) { | 5670 if (info.type()->Is(Type::Number())) { |
5691 Goto(if_true, number_block); | 5671 Goto(if_true, number_block); |
5692 if_true = number_block; | 5672 if_true = number_block; |
5693 number_block->SetJoinId(ast_id); | 5673 number_block->SetJoinId(ast_id); |
5694 } | 5674 } |
5695 | 5675 |
5696 set_current_block(if_true); | 5676 set_current_block(if_true); |
5697 | 5677 |
5698 HInstruction* access = NULL; | 5678 HInstruction* access = BuildMonomorphicAccess( |
| 5679 &info, object, dependency, value, ast_id, |
| 5680 return_id, FLAG_polymorphic_inlining); |
| 5681 |
5699 HValue* result = NULL; | 5682 HValue* result = NULL; |
5700 switch (access_type) { | 5683 switch (access_type) { |
5701 case LOAD: | 5684 case LOAD: |
5702 access = BuildLoadMonomorphic( | |
5703 &info, object, dependency, ast_id, | |
5704 return_id, FLAG_polymorphic_inlining); | |
5705 result = access; | 5685 result = access; |
5706 break; | 5686 break; |
5707 case STORE: | 5687 case STORE: |
5708 access = BuildStoreMonomorphic( | |
5709 &info, dependency, value, ast_id, return_id, | |
5710 FLAG_polymorphic_inlining); | |
5711 result = value; | 5688 result = value; |
5712 break; | 5689 break; |
5713 } | 5690 } |
5714 | 5691 |
5715 if (access == NULL) { | 5692 if (access == NULL) { |
5716 if (HasStackOverflow()) return; | 5693 if (HasStackOverflow()) return; |
5717 } else { | 5694 } else { |
5718 if (!access->IsLinked()) AddInstruction(access); | 5695 if (!access->IsLinked()) AddInstruction(access); |
5719 if (!ast_context()->IsEffect()) Push(result); | 5696 if (!ast_context()->IsEffect()) Push(result); |
5720 } | 5697 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5837 | 5814 |
5838 ASSERT(!info.type()->Is(Type::Number())); | 5815 ASSERT(!info.type()->Is(Type::Number())); |
5839 BuildCheckHeapObject(object); | 5816 BuildCheckHeapObject(object); |
5840 HValue* checked_object; | 5817 HValue* checked_object; |
5841 if (AreStringTypes(types)) { | 5818 if (AreStringTypes(types)) { |
5842 checked_object = Add<HCheckInstanceType>( | 5819 checked_object = Add<HCheckInstanceType>( |
5843 object, HCheckInstanceType::IS_STRING); | 5820 object, HCheckInstanceType::IS_STRING); |
5844 } else { | 5821 } else { |
5845 checked_object = Add<HCheckMaps>(object, types); | 5822 checked_object = Add<HCheckMaps>(object, types); |
5846 } | 5823 } |
5847 instr = BuildStoreMonomorphic( | 5824 instr = BuildMonomorphicAccess( |
5848 &info, checked_object, value, ast_id, return_id); | 5825 &info, object, checked_object, value, ast_id, return_id); |
5849 if (instr == NULL) return; | 5826 if (instr == NULL) return; |
5850 ASSERT(!instr->IsLinked()); | 5827 ASSERT(!instr->IsLinked()); |
5851 } else { | 5828 } else { |
5852 instr = BuildStoreNamedGeneric(object, name, value, is_uninitialized); | 5829 instr = BuildStoreNamedGeneric(object, name, value, is_uninitialized); |
5853 } | 5830 } |
5854 | 5831 |
5855 if (!ast_context()->IsEffect()) Push(value); | 5832 if (!ast_context()->IsEffect()) Push(value); |
5856 AddInstruction(instr); | 5833 AddInstruction(instr); |
5857 if (instr->HasObservableSideEffects()) { | 5834 if (instr->HasObservableSideEffects()) { |
5858 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5835 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
(...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6690 HValue* checked_object; | 6667 HValue* checked_object; |
6691 // Type::Number() is only supported by polymorphic load/call handling. | 6668 // Type::Number() is only supported by polymorphic load/call handling. |
6692 ASSERT(!info.type()->Is(Type::Number())); | 6669 ASSERT(!info.type()->Is(Type::Number())); |
6693 BuildCheckHeapObject(object); | 6670 BuildCheckHeapObject(object); |
6694 if (AreStringTypes(types)) { | 6671 if (AreStringTypes(types)) { |
6695 checked_object = | 6672 checked_object = |
6696 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 6673 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
6697 } else { | 6674 } else { |
6698 checked_object = Add<HCheckMaps>(object, types); | 6675 checked_object = Add<HCheckMaps>(object, types); |
6699 } | 6676 } |
6700 instr = BuildLoadMonomorphic( | 6677 instr = BuildMonomorphicAccess( |
6701 &info, object, checked_object, ast_id, expr->LoadId()); | 6678 &info, object, checked_object, NULL, ast_id, expr->LoadId()); |
6702 if (instr == NULL) return; | 6679 if (instr == NULL) return; |
6703 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | 6680 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
6704 } else { | 6681 } else { |
6705 instr = BuildLoadNamedGeneric(object, name, expr); | 6682 instr = BuildLoadNamedGeneric(object, name, expr); |
6706 } | 6683 } |
6707 | 6684 |
6708 } else { | 6685 } else { |
6709 HValue* key = Pop(); | 6686 HValue* key = Pop(); |
6710 HValue* obj = Pop(); | 6687 HValue* obj = Pop(); |
6711 | 6688 |
(...skipping 4459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11171 if (ShouldProduceTraceOutput()) { | 11148 if (ShouldProduceTraceOutput()) { |
11172 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11149 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11173 } | 11150 } |
11174 | 11151 |
11175 #ifdef DEBUG | 11152 #ifdef DEBUG |
11176 graph_->Verify(false); // No full verify. | 11153 graph_->Verify(false); // No full verify. |
11177 #endif | 11154 #endif |
11178 } | 11155 } |
11179 | 11156 |
11180 } } // namespace v8::internal | 11157 } } // namespace v8::internal |
OLD | NEW |