OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 5430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5441 | 5441 |
5442 if (!ast_context()->IsTest()) { | 5442 if (!ast_context()->IsTest()) { |
5443 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); | 5443 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
5444 set_current_block(join); | 5444 set_current_block(join); |
5445 if (join != NULL && !ast_context()->IsEffect()) { | 5445 if (join != NULL && !ast_context()->IsEffect()) { |
5446 return ast_context()->ReturnValue(Pop()); | 5446 return ast_context()->ReturnValue(Pop()); |
5447 } | 5447 } |
5448 } | 5448 } |
5449 } | 5449 } |
5450 | 5450 |
5451 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess( | |
5452 Variable* var, LookupIterator* it, PropertyAccessType access_type) { | |
5453 if (var->is_this()) return false; | |
5454 return CanInlineGlobalPropertyAccess(it, access_type); | |
5455 } | |
5456 | 5451 |
5457 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess( | 5452 HOptimizedGraphBuilder::GlobalPropertyAccess |
5458 LookupIterator* it, PropertyAccessType access_type) { | 5453 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it, |
5459 if (!current_info()->has_global_object()) { | 5454 PropertyAccessType access_type) { |
5460 return false; | 5455 if (var->is_this() || !current_info()->has_global_object()) { |
| 5456 return kUseGeneric; |
5461 } | 5457 } |
5462 | 5458 |
5463 switch (it->state()) { | 5459 switch (it->state()) { |
5464 case LookupIterator::ACCESSOR: | 5460 case LookupIterator::ACCESSOR: |
5465 case LookupIterator::ACCESS_CHECK: | 5461 case LookupIterator::ACCESS_CHECK: |
5466 case LookupIterator::INTERCEPTOR: | 5462 case LookupIterator::INTERCEPTOR: |
5467 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5463 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
5468 case LookupIterator::NOT_FOUND: | 5464 case LookupIterator::NOT_FOUND: |
5469 return false; | 5465 return kUseGeneric; |
5470 case LookupIterator::DATA: | 5466 case LookupIterator::DATA: |
5471 if (access_type == STORE && it->IsReadOnly()) return false; | 5467 if (access_type == STORE && it->IsReadOnly()) return kUseGeneric; |
5472 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return false; | 5468 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return kUseGeneric; |
5473 return true; | 5469 return kUseCell; |
5474 case LookupIterator::JSPROXY: | 5470 case LookupIterator::JSPROXY: |
5475 case LookupIterator::TRANSITION: | 5471 case LookupIterator::TRANSITION: |
5476 UNREACHABLE(); | 5472 UNREACHABLE(); |
5477 } | 5473 } |
5478 UNREACHABLE(); | 5474 UNREACHABLE(); |
5479 return false; | 5475 return kUseGeneric; |
5480 } | 5476 } |
5481 | 5477 |
5482 | 5478 |
5483 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5479 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
5484 DCHECK(var->IsContextSlot()); | 5480 DCHECK(var->IsContextSlot()); |
5485 HValue* context = environment()->context(); | 5481 HValue* context = environment()->context(); |
5486 int length = scope()->ContextChainLength(var->scope()); | 5482 int length = scope()->ContextChainLength(var->scope()); |
5487 while (length-- > 0) { | 5483 while (length-- > 0) { |
5488 context = Add<HLoadNamedField>( | 5484 context = Add<HLoadNamedField>( |
5489 context, nullptr, | 5485 context, nullptr, |
5490 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | 5486 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); |
5491 } | 5487 } |
5492 return context; | 5488 return context; |
5493 } | 5489 } |
5494 | 5490 |
5495 void HOptimizedGraphBuilder::InlineGlobalPropertyLoad(LookupIterator* it, | |
5496 BailoutId ast_id) { | |
5497 Handle<PropertyCell> cell = it->GetPropertyCell(); | |
5498 top_info()->dependencies()->AssumePropertyCell(cell); | |
5499 auto cell_type = it->property_details().cell_type(); | |
5500 if (cell_type == PropertyCellType::kConstant || | |
5501 cell_type == PropertyCellType::kUndefined) { | |
5502 Handle<Object> constant_object(cell->value(), isolate()); | |
5503 if (constant_object->IsConsString()) { | |
5504 constant_object = String::Flatten(Handle<String>::cast(constant_object)); | |
5505 } | |
5506 HConstant* constant = New<HConstant>(constant_object); | |
5507 return ast_context()->ReturnInstruction(constant, ast_id); | |
5508 } else { | |
5509 auto access = HObjectAccess::ForPropertyCellValue(); | |
5510 UniqueSet<Map>* field_maps = nullptr; | |
5511 if (cell_type == PropertyCellType::kConstantType) { | |
5512 switch (cell->GetConstantType()) { | |
5513 case PropertyCellConstantType::kSmi: | |
5514 access = access.WithRepresentation(Representation::Smi()); | |
5515 break; | |
5516 case PropertyCellConstantType::kStableMap: { | |
5517 // Check that the map really is stable. The heap object could | |
5518 // have mutated without the cell updating state. In that case, | |
5519 // make no promises about the loaded value except that it's a | |
5520 // heap object. | |
5521 access = access.WithRepresentation(Representation::HeapObject()); | |
5522 Handle<Map> map(HeapObject::cast(cell->value())->map()); | |
5523 if (map->is_stable()) { | |
5524 field_maps = new (zone()) | |
5525 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone()); | |
5526 } | |
5527 break; | |
5528 } | |
5529 } | |
5530 } | |
5531 HConstant* cell_constant = Add<HConstant>(cell); | |
5532 HLoadNamedField* instr; | |
5533 if (field_maps == nullptr) { | |
5534 instr = New<HLoadNamedField>(cell_constant, nullptr, access); | |
5535 } else { | |
5536 instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps, | |
5537 HType::HeapObject()); | |
5538 } | |
5539 instr->ClearDependsOnFlag(kInobjectFields); | |
5540 instr->SetDependsOnFlag(kGlobalVars); | |
5541 return ast_context()->ReturnInstruction(instr, ast_id); | |
5542 } | |
5543 } | |
5544 | 5491 |
5545 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5492 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
5546 DCHECK(!HasStackOverflow()); | 5493 DCHECK(!HasStackOverflow()); |
5547 DCHECK(current_block() != NULL); | 5494 DCHECK(current_block() != NULL); |
5548 DCHECK(current_block()->HasPredecessor()); | 5495 DCHECK(current_block()->HasPredecessor()); |
5549 Variable* variable = expr->var(); | 5496 Variable* variable = expr->var(); |
5550 switch (variable->location()) { | 5497 switch (variable->location()) { |
5551 case VariableLocation::UNALLOCATED: { | 5498 case VariableLocation::UNALLOCATED: { |
5552 if (IsLexicalVariableMode(variable->mode())) { | 5499 if (IsLexicalVariableMode(variable->mode())) { |
5553 // TODO(rossberg): should this be an DCHECK? | 5500 // TODO(rossberg): should this be an DCHECK? |
(...skipping 28 matching lines...) Expand all Loading... |
5582 return Bailout(kReferenceToUninitializedVariable); | 5529 return Bailout(kReferenceToUninitializedVariable); |
5583 } | 5530 } |
5584 HInstruction* result = New<HLoadNamedField>( | 5531 HInstruction* result = New<HLoadNamedField>( |
5585 Add<HConstant>(script_context), nullptr, | 5532 Add<HConstant>(script_context), nullptr, |
5586 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5533 HObjectAccess::ForContextSlot(lookup.slot_index)); |
5587 return ast_context()->ReturnInstruction(result, expr->id()); | 5534 return ast_context()->ReturnInstruction(result, expr->id()); |
5588 } | 5535 } |
5589 } | 5536 } |
5590 | 5537 |
5591 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5538 LookupIterator it(global, variable->name(), LookupIterator::OWN); |
5592 if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) { | 5539 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); |
5593 InlineGlobalPropertyLoad(&it, expr->id()); | 5540 |
5594 return; | 5541 if (type == kUseCell) { |
| 5542 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 5543 top_info()->dependencies()->AssumePropertyCell(cell); |
| 5544 auto cell_type = it.property_details().cell_type(); |
| 5545 if (cell_type == PropertyCellType::kConstant || |
| 5546 cell_type == PropertyCellType::kUndefined) { |
| 5547 Handle<Object> constant_object(cell->value(), isolate()); |
| 5548 if (constant_object->IsConsString()) { |
| 5549 constant_object = |
| 5550 String::Flatten(Handle<String>::cast(constant_object)); |
| 5551 } |
| 5552 HConstant* constant = New<HConstant>(constant_object); |
| 5553 return ast_context()->ReturnInstruction(constant, expr->id()); |
| 5554 } else { |
| 5555 auto access = HObjectAccess::ForPropertyCellValue(); |
| 5556 UniqueSet<Map>* field_maps = nullptr; |
| 5557 if (cell_type == PropertyCellType::kConstantType) { |
| 5558 switch (cell->GetConstantType()) { |
| 5559 case PropertyCellConstantType::kSmi: |
| 5560 access = access.WithRepresentation(Representation::Smi()); |
| 5561 break; |
| 5562 case PropertyCellConstantType::kStableMap: { |
| 5563 // Check that the map really is stable. The heap object could |
| 5564 // have mutated without the cell updating state. In that case, |
| 5565 // make no promises about the loaded value except that it's a |
| 5566 // heap object. |
| 5567 access = |
| 5568 access.WithRepresentation(Representation::HeapObject()); |
| 5569 Handle<Map> map(HeapObject::cast(cell->value())->map()); |
| 5570 if (map->is_stable()) { |
| 5571 field_maps = new (zone()) |
| 5572 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone()); |
| 5573 } |
| 5574 break; |
| 5575 } |
| 5576 } |
| 5577 } |
| 5578 HConstant* cell_constant = Add<HConstant>(cell); |
| 5579 HLoadNamedField* instr; |
| 5580 if (field_maps == nullptr) { |
| 5581 instr = New<HLoadNamedField>(cell_constant, nullptr, access); |
| 5582 } else { |
| 5583 instr = New<HLoadNamedField>(cell_constant, nullptr, access, |
| 5584 field_maps, HType::HeapObject()); |
| 5585 } |
| 5586 instr->ClearDependsOnFlag(kInobjectFields); |
| 5587 instr->SetDependsOnFlag(kGlobalVars); |
| 5588 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5589 } |
5595 } else { | 5590 } else { |
5596 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 5591 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
5597 | 5592 |
5598 HValue* vector_value = Add<HConstant>(vector); | 5593 HValue* vector_value = Add<HConstant>(vector); |
5599 HValue* slot_value = | 5594 HValue* slot_value = |
5600 Add<HConstant>(vector->GetIndex(expr->VariableFeedbackSlot())); | 5595 Add<HConstant>(vector->GetIndex(expr->VariableFeedbackSlot())); |
5601 Callable callable = CodeFactory::LoadGlobalICInOptimizedCode( | 5596 Callable callable = CodeFactory::LoadGlobalICInOptimizedCode( |
5602 isolate(), ast_context()->typeof_mode()); | 5597 isolate(), ast_context()->typeof_mode()); |
5603 HValue* stub = Add<HConstant>(callable.code()); | 5598 HValue* stub = Add<HConstant>(callable.code()); |
5604 HValue* values[] = {context(), slot_value, vector_value}; | 5599 HValue* values[] = {context(), slot_value, vector_value}; |
(...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6687 DCHECK(prop != NULL); | 6682 DCHECK(prop != NULL); |
6688 CHECK_ALIVE(VisitForValue(prop->obj())); | 6683 CHECK_ALIVE(VisitForValue(prop->obj())); |
6689 if (!prop->key()->IsPropertyName()) { | 6684 if (!prop->key()->IsPropertyName()) { |
6690 CHECK_ALIVE(VisitForValue(prop->key())); | 6685 CHECK_ALIVE(VisitForValue(prop->key())); |
6691 } | 6686 } |
6692 CHECK_ALIVE(VisitForValue(expr->value())); | 6687 CHECK_ALIVE(VisitForValue(expr->value())); |
6693 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), | 6688 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), |
6694 expr->AssignmentId(), expr->IsUninitialized()); | 6689 expr->AssignmentId(), expr->IsUninitialized()); |
6695 } | 6690 } |
6696 | 6691 |
6697 void HOptimizedGraphBuilder::InlineGlobalPropertyStore(LookupIterator* it, | |
6698 HValue* value, | |
6699 BailoutId ast_id) { | |
6700 Handle<PropertyCell> cell = it->GetPropertyCell(); | |
6701 top_info()->dependencies()->AssumePropertyCell(cell); | |
6702 auto cell_type = it->property_details().cell_type(); | |
6703 if (cell_type == PropertyCellType::kConstant || | |
6704 cell_type == PropertyCellType::kUndefined) { | |
6705 Handle<Object> constant(cell->value(), isolate()); | |
6706 if (value->IsConstant()) { | |
6707 HConstant* c_value = HConstant::cast(value); | |
6708 if (!constant.is_identical_to(c_value->handle(isolate()))) { | |
6709 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
6710 Deoptimizer::EAGER); | |
6711 } | |
6712 } else { | |
6713 HValue* c_constant = Add<HConstant>(constant); | |
6714 IfBuilder builder(this); | |
6715 if (constant->IsNumber()) { | |
6716 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | |
6717 } else { | |
6718 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | |
6719 } | |
6720 builder.Then(); | |
6721 builder.Else(); | |
6722 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
6723 Deoptimizer::EAGER); | |
6724 builder.End(); | |
6725 } | |
6726 } | |
6727 HConstant* cell_constant = Add<HConstant>(cell); | |
6728 auto access = HObjectAccess::ForPropertyCellValue(); | |
6729 if (cell_type == PropertyCellType::kConstantType) { | |
6730 switch (cell->GetConstantType()) { | |
6731 case PropertyCellConstantType::kSmi: | |
6732 access = access.WithRepresentation(Representation::Smi()); | |
6733 break; | |
6734 case PropertyCellConstantType::kStableMap: { | |
6735 // The map may no longer be stable, deopt if it's ever different from | |
6736 // what is currently there, which will allow for restablization. | |
6737 Handle<Map> map(HeapObject::cast(cell->value())->map()); | |
6738 Add<HCheckHeapObject>(value); | |
6739 value = Add<HCheckMaps>(value, map); | |
6740 access = access.WithRepresentation(Representation::HeapObject()); | |
6741 break; | |
6742 } | |
6743 } | |
6744 } | |
6745 HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value); | |
6746 instr->ClearChangesFlag(kInobjectFields); | |
6747 instr->SetChangesFlag(kGlobalVars); | |
6748 if (instr->HasObservableSideEffects()) { | |
6749 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | |
6750 } | |
6751 } | |
6752 | 6692 |
6753 // Because not every expression has a position and there is not common | 6693 // Because not every expression has a position and there is not common |
6754 // superclass of Assignment and CountOperation, we cannot just pass the | 6694 // superclass of Assignment and CountOperation, we cannot just pass the |
6755 // owning expression instead of position and ast_id separately. | 6695 // owning expression instead of position and ast_id separately. |
6756 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6696 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
6757 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { | 6697 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { |
6758 Handle<JSGlobalObject> global(current_info()->global_object()); | 6698 Handle<JSGlobalObject> global(current_info()->global_object()); |
6759 | 6699 |
6760 // Lookup in script contexts. | 6700 // Lookup in script contexts. |
6761 { | 6701 { |
(...skipping 20 matching lines...) Expand all Loading... |
6782 Add<HConstant>(script_context), | 6722 Add<HConstant>(script_context), |
6783 HObjectAccess::ForContextSlot(lookup.slot_index), value); | 6723 HObjectAccess::ForContextSlot(lookup.slot_index), value); |
6784 USE(instr); | 6724 USE(instr); |
6785 DCHECK(instr->HasObservableSideEffects()); | 6725 DCHECK(instr->HasObservableSideEffects()); |
6786 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6726 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6787 return; | 6727 return; |
6788 } | 6728 } |
6789 } | 6729 } |
6790 | 6730 |
6791 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6731 LookupIterator it(global, var->name(), LookupIterator::OWN); |
6792 if (CanInlineGlobalPropertyAccess(var, &it, STORE)) { | 6732 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); |
6793 InlineGlobalPropertyStore(&it, value, ast_id); | 6733 if (type == kUseCell) { |
| 6734 Handle<PropertyCell> cell = it.GetPropertyCell(); |
| 6735 top_info()->dependencies()->AssumePropertyCell(cell); |
| 6736 auto cell_type = it.property_details().cell_type(); |
| 6737 if (cell_type == PropertyCellType::kConstant || |
| 6738 cell_type == PropertyCellType::kUndefined) { |
| 6739 Handle<Object> constant(cell->value(), isolate()); |
| 6740 if (value->IsConstant()) { |
| 6741 HConstant* c_value = HConstant::cast(value); |
| 6742 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
| 6743 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6744 Deoptimizer::EAGER); |
| 6745 } |
| 6746 } else { |
| 6747 HValue* c_constant = Add<HConstant>(constant); |
| 6748 IfBuilder builder(this); |
| 6749 if (constant->IsNumber()) { |
| 6750 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); |
| 6751 } else { |
| 6752 builder.If<HCompareObjectEqAndBranch>(value, c_constant); |
| 6753 } |
| 6754 builder.Then(); |
| 6755 builder.Else(); |
| 6756 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6757 Deoptimizer::EAGER); |
| 6758 builder.End(); |
| 6759 } |
| 6760 } |
| 6761 HConstant* cell_constant = Add<HConstant>(cell); |
| 6762 auto access = HObjectAccess::ForPropertyCellValue(); |
| 6763 if (cell_type == PropertyCellType::kConstantType) { |
| 6764 switch (cell->GetConstantType()) { |
| 6765 case PropertyCellConstantType::kSmi: |
| 6766 access = access.WithRepresentation(Representation::Smi()); |
| 6767 break; |
| 6768 case PropertyCellConstantType::kStableMap: { |
| 6769 // The map may no longer be stable, deopt if it's ever different from |
| 6770 // what is currently there, which will allow for restablization. |
| 6771 Handle<Map> map(HeapObject::cast(cell->value())->map()); |
| 6772 Add<HCheckHeapObject>(value); |
| 6773 value = Add<HCheckMaps>(value, map); |
| 6774 access = access.WithRepresentation(Representation::HeapObject()); |
| 6775 break; |
| 6776 } |
| 6777 } |
| 6778 } |
| 6779 HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value); |
| 6780 instr->ClearChangesFlag(kInobjectFields); |
| 6781 instr->SetChangesFlag(kGlobalVars); |
| 6782 if (instr->HasObservableSideEffects()) { |
| 6783 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6784 } |
6794 } else { | 6785 } else { |
6795 HValue* global_object = Add<HLoadNamedField>( | 6786 HValue* global_object = Add<HLoadNamedField>( |
6796 BuildGetNativeContext(), nullptr, | 6787 BuildGetNativeContext(), nullptr, |
6797 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); | 6788 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); |
6798 Handle<TypeFeedbackVector> vector = | 6789 Handle<TypeFeedbackVector> vector = |
6799 handle(current_feedback_vector(), isolate()); | 6790 handle(current_feedback_vector(), isolate()); |
6800 HValue* name = Add<HConstant>(var->name()); | 6791 HValue* name = Add<HConstant>(var->name()); |
6801 HValue* vector_value = Add<HConstant>(vector); | 6792 HValue* vector_value = Add<HConstant>(vector); |
6802 HValue* slot_value = Add<HConstant>(vector->GetIndex(slot)); | 6793 HValue* slot_value = Add<HConstant>(vector->GetIndex(slot)); |
6803 Callable callable = CodeFactory::StoreICInOptimizedCode( | 6794 Callable callable = CodeFactory::StoreICInOptimizedCode( |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7698 | 7689 |
7699 HValue* HOptimizedGraphBuilder::BuildNamedAccess( | 7690 HValue* HOptimizedGraphBuilder::BuildNamedAccess( |
7700 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, | 7691 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, |
7701 Expression* expr, FeedbackVectorSlot slot, HValue* object, | 7692 Expression* expr, FeedbackVectorSlot slot, HValue* object, |
7702 Handle<Name> name, HValue* value, bool is_uninitialized) { | 7693 Handle<Name> name, HValue* value, bool is_uninitialized) { |
7703 SmallMapList* maps; | 7694 SmallMapList* maps; |
7704 ComputeReceiverTypes(expr, object, &maps, this); | 7695 ComputeReceiverTypes(expr, object, &maps, this); |
7705 DCHECK(maps != NULL); | 7696 DCHECK(maps != NULL); |
7706 | 7697 |
7707 if (maps->length() > 0) { | 7698 if (maps->length() > 0) { |
7708 Handle<JSGlobalObject> global_object(current_info()->global_object()); | |
7709 Handle<Context> current_context(current_info()->context()); | |
7710 Handle<JSObject> global_proxy(current_context->global_proxy()); | |
7711 | |
7712 // Check for special case: Access via a single map to the global proxy | |
7713 // can also be handled monomorphically. | |
7714 Handle<Object> map_constructor = | |
7715 handle(maps->first()->GetConstructor(), isolate()); | |
7716 if (map_constructor->IsJSFunction()) { | |
7717 Handle<Context> map_context = | |
7718 handle(Handle<JSFunction>::cast(map_constructor)->context()); | |
7719 bool is_global_proxy_access = | |
7720 maps->length() == 1 && // More than one map, fallback to polymorphic? | |
7721 maps->first()->IsJSGlobalProxyMap() && | |
7722 isolate()->MayAccess(map_context, global_proxy); | |
7723 | |
7724 if (is_global_proxy_access) { | |
7725 LookupIterator it(global_object, name, LookupIterator::OWN); | |
7726 if (CanInlineGlobalPropertyAccess(&it, access)) { | |
7727 BuildCheckHeapObject(object); | |
7728 Add<HCheckMaps>(object, maps); | |
7729 if (access == LOAD) { | |
7730 InlineGlobalPropertyLoad(&it, expr->id()); | |
7731 } else { | |
7732 InlineGlobalPropertyStore(&it, value, expr->id()); | |
7733 } | |
7734 return nullptr; | |
7735 } | |
7736 } | |
7737 } | |
7738 | |
7739 PropertyAccessInfo info(this, access, maps->first(), name); | 7699 PropertyAccessInfo info(this, access, maps->first(), name); |
7740 if (!info.CanAccessAsMonomorphic(maps)) { | 7700 if (!info.CanAccessAsMonomorphic(maps)) { |
7741 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, | 7701 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, |
7742 object, value, maps, name); | 7702 object, value, maps, name); |
7743 return NULL; | 7703 return NULL; |
7744 } | 7704 } |
7745 | 7705 |
7746 HValue* checked_object; | 7706 HValue* checked_object; |
7747 // AstType::Number() is only supported by polymorphic load/call handling. | 7707 // AstType::Number() is only supported by polymorphic load/call handling. |
7748 DCHECK(!info.IsNumberType()); | 7708 DCHECK(!info.IsNumberType()); |
(...skipping 5574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13323 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13283 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13324 } | 13284 } |
13325 | 13285 |
13326 #ifdef DEBUG | 13286 #ifdef DEBUG |
13327 graph_->Verify(false); // No full verify. | 13287 graph_->Verify(false); // No full verify. |
13328 #endif | 13288 #endif |
13329 } | 13289 } |
13330 | 13290 |
13331 } // namespace internal | 13291 } // namespace internal |
13332 } // namespace v8 | 13292 } // namespace v8 |
OLD | NEW |