| 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 |