Chromium Code Reviews| 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 } | |
| 5451 | 5456 |
| 5452 HOptimizedGraphBuilder::GlobalPropertyAccess | 5457 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess( |
| 5453 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it, | 5458 LookupIterator* it, PropertyAccessType access_type) { |
| 5454 PropertyAccessType access_type) { | 5459 if (!current_info()->has_global_object()) { |
| 5455 if (var->is_this() || !current_info()->has_global_object()) { | 5460 return false; |
| 5456 return kUseGeneric; | |
| 5457 } | 5461 } |
| 5458 | 5462 |
| 5459 switch (it->state()) { | 5463 switch (it->state()) { |
| 5460 case LookupIterator::ACCESSOR: | 5464 case LookupIterator::ACCESSOR: |
| 5461 case LookupIterator::ACCESS_CHECK: | 5465 case LookupIterator::ACCESS_CHECK: |
| 5462 case LookupIterator::INTERCEPTOR: | 5466 case LookupIterator::INTERCEPTOR: |
| 5463 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5467 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| 5464 case LookupIterator::NOT_FOUND: | 5468 case LookupIterator::NOT_FOUND: |
| 5465 return kUseGeneric; | 5469 return false; |
| 5466 case LookupIterator::DATA: | 5470 case LookupIterator::DATA: |
| 5467 if (access_type == STORE && it->IsReadOnly()) return kUseGeneric; | 5471 if (access_type == STORE && it->IsReadOnly()) return false; |
| 5468 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return kUseGeneric; | 5472 if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return false; |
| 5469 return kUseCell; | 5473 return true; |
| 5470 case LookupIterator::JSPROXY: | 5474 case LookupIterator::JSPROXY: |
| 5471 case LookupIterator::TRANSITION: | 5475 case LookupIterator::TRANSITION: |
| 5472 UNREACHABLE(); | 5476 UNREACHABLE(); |
| 5473 } | 5477 } |
| 5474 UNREACHABLE(); | 5478 UNREACHABLE(); |
| 5475 return kUseGeneric; | 5479 return false; |
| 5476 } | 5480 } |
| 5477 | 5481 |
| 5478 | 5482 |
| 5479 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5483 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 5480 DCHECK(var->IsContextSlot()); | 5484 DCHECK(var->IsContextSlot()); |
| 5481 HValue* context = environment()->context(); | 5485 HValue* context = environment()->context(); |
| 5482 int length = scope()->ContextChainLength(var->scope()); | 5486 int length = scope()->ContextChainLength(var->scope()); |
| 5483 while (length-- > 0) { | 5487 while (length-- > 0) { |
| 5484 context = Add<HLoadNamedField>( | 5488 context = Add<HLoadNamedField>( |
| 5485 context, nullptr, | 5489 context, nullptr, |
| 5486 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | 5490 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); |
| 5487 } | 5491 } |
| 5488 return context; | 5492 return context; |
| 5489 } | 5493 } |
| 5490 | 5494 |
| 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 } | |
| 5491 | 5544 |
| 5492 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5545 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 5493 DCHECK(!HasStackOverflow()); | 5546 DCHECK(!HasStackOverflow()); |
| 5494 DCHECK(current_block() != NULL); | 5547 DCHECK(current_block() != NULL); |
| 5495 DCHECK(current_block()->HasPredecessor()); | 5548 DCHECK(current_block()->HasPredecessor()); |
| 5496 Variable* variable = expr->var(); | 5549 Variable* variable = expr->var(); |
| 5497 switch (variable->location()) { | 5550 switch (variable->location()) { |
| 5498 case VariableLocation::UNALLOCATED: { | 5551 case VariableLocation::UNALLOCATED: { |
| 5499 if (IsLexicalVariableMode(variable->mode())) { | 5552 if (IsLexicalVariableMode(variable->mode())) { |
| 5500 // TODO(rossberg): should this be an DCHECK? | 5553 // TODO(rossberg): should this be an DCHECK? |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 5529 return Bailout(kReferenceToUninitializedVariable); | 5582 return Bailout(kReferenceToUninitializedVariable); |
| 5530 } | 5583 } |
| 5531 HInstruction* result = New<HLoadNamedField>( | 5584 HInstruction* result = New<HLoadNamedField>( |
| 5532 Add<HConstant>(script_context), nullptr, | 5585 Add<HConstant>(script_context), nullptr, |
| 5533 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5586 HObjectAccess::ForContextSlot(lookup.slot_index)); |
| 5534 return ast_context()->ReturnInstruction(result, expr->id()); | 5587 return ast_context()->ReturnInstruction(result, expr->id()); |
| 5535 } | 5588 } |
| 5536 } | 5589 } |
| 5537 | 5590 |
| 5538 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5591 LookupIterator it(global, variable->name(), LookupIterator::OWN); |
| 5539 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); | 5592 if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) { |
| 5540 | 5593 InlineGlobalPropertyLoad(&it, expr->id()); |
| 5541 if (type == kUseCell) { | 5594 return; |
| 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 } | |
| 5590 } else { | 5595 } else { |
| 5591 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 5596 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
| 5592 HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>( | 5597 HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>( |
| 5593 variable->name(), ast_context()->typeof_mode(), vector, | 5598 variable->name(), ast_context()->typeof_mode(), vector, |
| 5594 expr->VariableFeedbackSlot()); | 5599 expr->VariableFeedbackSlot()); |
| 5595 return ast_context()->ReturnInstruction(instr, expr->id()); | 5600 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5596 } | 5601 } |
| 5597 } | 5602 } |
| 5598 | 5603 |
| 5599 case VariableLocation::PARAMETER: | 5604 case VariableLocation::PARAMETER: |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6675 DCHECK(prop != NULL); | 6680 DCHECK(prop != NULL); |
| 6676 CHECK_ALIVE(VisitForValue(prop->obj())); | 6681 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 6677 if (!prop->key()->IsPropertyName()) { | 6682 if (!prop->key()->IsPropertyName()) { |
| 6678 CHECK_ALIVE(VisitForValue(prop->key())); | 6683 CHECK_ALIVE(VisitForValue(prop->key())); |
| 6679 } | 6684 } |
| 6680 CHECK_ALIVE(VisitForValue(expr->value())); | 6685 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6681 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), | 6686 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), |
| 6682 expr->AssignmentId(), expr->IsUninitialized()); | 6687 expr->AssignmentId(), expr->IsUninitialized()); |
| 6683 } | 6688 } |
| 6684 | 6689 |
| 6690 void HOptimizedGraphBuilder::InlineGlobalPropertyStore(LookupIterator* it, | |
| 6691 HValue* value, | |
| 6692 BailoutId ast_id) { | |
| 6693 Handle<PropertyCell> cell = it->GetPropertyCell(); | |
| 6694 top_info()->dependencies()->AssumePropertyCell(cell); | |
| 6695 auto cell_type = it->property_details().cell_type(); | |
| 6696 if (cell_type == PropertyCellType::kConstant || | |
| 6697 cell_type == PropertyCellType::kUndefined) { | |
| 6698 Handle<Object> constant(cell->value(), isolate()); | |
| 6699 if (value->IsConstant()) { | |
| 6700 HConstant* c_value = HConstant::cast(value); | |
| 6701 if (!constant.is_identical_to(c_value->handle(isolate()))) { | |
| 6702 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
| 6703 Deoptimizer::EAGER); | |
| 6704 } | |
| 6705 } else { | |
| 6706 HValue* c_constant = Add<HConstant>(constant); | |
| 6707 IfBuilder builder(this); | |
| 6708 if (constant->IsNumber()) { | |
| 6709 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | |
| 6710 } else { | |
| 6711 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | |
| 6712 } | |
| 6713 builder.Then(); | |
| 6714 builder.Else(); | |
| 6715 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
| 6716 Deoptimizer::EAGER); | |
| 6717 builder.End(); | |
| 6718 } | |
| 6719 } | |
| 6720 HConstant* cell_constant = Add<HConstant>(cell); | |
| 6721 auto access = HObjectAccess::ForPropertyCellValue(); | |
| 6722 if (cell_type == PropertyCellType::kConstantType) { | |
| 6723 switch (cell->GetConstantType()) { | |
| 6724 case PropertyCellConstantType::kSmi: | |
| 6725 access = access.WithRepresentation(Representation::Smi()); | |
| 6726 break; | |
| 6727 case PropertyCellConstantType::kStableMap: { | |
| 6728 // The map may no longer be stable, deopt if it's ever different from | |
| 6729 // what is currently there, which will allow for restablization. | |
| 6730 Handle<Map> map(HeapObject::cast(cell->value())->map()); | |
| 6731 Add<HCheckHeapObject>(value); | |
| 6732 value = Add<HCheckMaps>(value, map); | |
| 6733 access = access.WithRepresentation(Representation::HeapObject()); | |
| 6734 break; | |
| 6735 } | |
| 6736 } | |
| 6737 } | |
| 6738 HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value); | |
| 6739 instr->ClearChangesFlag(kInobjectFields); | |
| 6740 instr->SetChangesFlag(kGlobalVars); | |
| 6741 if (instr->HasObservableSideEffects()) { | |
| 6742 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | |
| 6743 } | |
| 6744 } | |
| 6685 | 6745 |
| 6686 // Because not every expression has a position and there is not common | 6746 // Because not every expression has a position and there is not common |
| 6687 // superclass of Assignment and CountOperation, we cannot just pass the | 6747 // superclass of Assignment and CountOperation, we cannot just pass the |
| 6688 // owning expression instead of position and ast_id separately. | 6748 // owning expression instead of position and ast_id separately. |
| 6689 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6749 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 6690 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { | 6750 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { |
| 6691 Handle<JSGlobalObject> global(current_info()->global_object()); | 6751 Handle<JSGlobalObject> global(current_info()->global_object()); |
| 6692 | 6752 |
| 6693 // Lookup in script contexts. | 6753 // Lookup in script contexts. |
| 6694 { | 6754 { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 6715 Add<HConstant>(script_context), | 6775 Add<HConstant>(script_context), |
| 6716 HObjectAccess::ForContextSlot(lookup.slot_index), value); | 6776 HObjectAccess::ForContextSlot(lookup.slot_index), value); |
| 6717 USE(instr); | 6777 USE(instr); |
| 6718 DCHECK(instr->HasObservableSideEffects()); | 6778 DCHECK(instr->HasObservableSideEffects()); |
| 6719 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6779 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6720 return; | 6780 return; |
| 6721 } | 6781 } |
| 6722 } | 6782 } |
| 6723 | 6783 |
| 6724 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6784 LookupIterator it(global, var->name(), LookupIterator::OWN); |
| 6725 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6785 if (CanInlineGlobalPropertyAccess(var, &it, STORE)) { |
| 6726 if (type == kUseCell) { | 6786 InlineGlobalPropertyStore(&it, value, ast_id); |
| 6727 Handle<PropertyCell> cell = it.GetPropertyCell(); | |
| 6728 top_info()->dependencies()->AssumePropertyCell(cell); | |
| 6729 auto cell_type = it.property_details().cell_type(); | |
| 6730 if (cell_type == PropertyCellType::kConstant || | |
| 6731 cell_type == PropertyCellType::kUndefined) { | |
| 6732 Handle<Object> constant(cell->value(), isolate()); | |
| 6733 if (value->IsConstant()) { | |
| 6734 HConstant* c_value = HConstant::cast(value); | |
| 6735 if (!constant.is_identical_to(c_value->handle(isolate()))) { | |
| 6736 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
| 6737 Deoptimizer::EAGER); | |
| 6738 } | |
| 6739 } else { | |
| 6740 HValue* c_constant = Add<HConstant>(constant); | |
| 6741 IfBuilder builder(this); | |
| 6742 if (constant->IsNumber()) { | |
| 6743 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | |
| 6744 } else { | |
| 6745 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | |
| 6746 } | |
| 6747 builder.Then(); | |
| 6748 builder.Else(); | |
| 6749 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, | |
| 6750 Deoptimizer::EAGER); | |
| 6751 builder.End(); | |
| 6752 } | |
| 6753 } | |
| 6754 HConstant* cell_constant = Add<HConstant>(cell); | |
| 6755 auto access = HObjectAccess::ForPropertyCellValue(); | |
| 6756 if (cell_type == PropertyCellType::kConstantType) { | |
| 6757 switch (cell->GetConstantType()) { | |
| 6758 case PropertyCellConstantType::kSmi: | |
| 6759 access = access.WithRepresentation(Representation::Smi()); | |
| 6760 break; | |
| 6761 case PropertyCellConstantType::kStableMap: { | |
| 6762 // The map may no longer be stable, deopt if it's ever different from | |
| 6763 // what is currently there, which will allow for restablization. | |
| 6764 Handle<Map> map(HeapObject::cast(cell->value())->map()); | |
| 6765 Add<HCheckHeapObject>(value); | |
| 6766 value = Add<HCheckMaps>(value, map); | |
| 6767 access = access.WithRepresentation(Representation::HeapObject()); | |
| 6768 break; | |
| 6769 } | |
| 6770 } | |
| 6771 } | |
| 6772 HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value); | |
| 6773 instr->ClearChangesFlag(kInobjectFields); | |
| 6774 instr->SetChangesFlag(kGlobalVars); | |
| 6775 if (instr->HasObservableSideEffects()) { | |
| 6776 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | |
| 6777 } | |
| 6778 } else { | 6787 } else { |
| 6779 HValue* global_object = Add<HLoadNamedField>( | 6788 HValue* global_object = Add<HLoadNamedField>( |
| 6780 BuildGetNativeContext(), nullptr, | 6789 BuildGetNativeContext(), nullptr, |
| 6781 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); | 6790 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); |
| 6782 Handle<TypeFeedbackVector> vector = | 6791 Handle<TypeFeedbackVector> vector = |
| 6783 handle(current_feedback_vector(), isolate()); | 6792 handle(current_feedback_vector(), isolate()); |
| 6784 HValue* name = Add<HConstant>(var->name()); | 6793 HValue* name = Add<HConstant>(var->name()); |
| 6785 HValue* vector_value = Add<HConstant>(vector); | 6794 HValue* vector_value = Add<HConstant>(vector); |
| 6786 HValue* slot_value = Add<HConstant>(vector->GetIndex(slot)); | 6795 HValue* slot_value = Add<HConstant>(vector->GetIndex(slot)); |
| 6787 Callable callable = CodeFactory::StoreICInOptimizedCode( | 6796 Callable callable = CodeFactory::StoreICInOptimizedCode( |
| (...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7683 | 7692 |
| 7684 HValue* HOptimizedGraphBuilder::BuildNamedAccess( | 7693 HValue* HOptimizedGraphBuilder::BuildNamedAccess( |
| 7685 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, | 7694 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, |
| 7686 Expression* expr, FeedbackVectorSlot slot, HValue* object, | 7695 Expression* expr, FeedbackVectorSlot slot, HValue* object, |
| 7687 Handle<Name> name, HValue* value, bool is_uninitialized) { | 7696 Handle<Name> name, HValue* value, bool is_uninitialized) { |
| 7688 SmallMapList* maps; | 7697 SmallMapList* maps; |
| 7689 ComputeReceiverTypes(expr, object, &maps, this); | 7698 ComputeReceiverTypes(expr, object, &maps, this); |
| 7690 DCHECK(maps != NULL); | 7699 DCHECK(maps != NULL); |
| 7691 | 7700 |
| 7692 if (maps->length() > 0) { | 7701 if (maps->length() > 0) { |
| 7702 Handle<JSGlobalObject> global_object(current_info()->global_object()); | |
| 7703 Handle<Context> current_context(current_info()->context()); | |
| 7704 Handle<JSObject> global_proxy(current_context->global_proxy()); | |
| 7705 | |
| 7706 // Check for special case: Access via a single map to the global proxy | |
| 7707 // can also be handled monomorphically. | |
| 7708 Handle<Object> map_constructor = | |
| 7709 handle(maps->first()->GetConstructor(), isolate()); | |
| 7710 if (map_constructor->IsJSFunction()) { | |
| 7711 Handle<Context> map_context = | |
| 7712 handle(Handle<JSFunction>::cast(map_constructor)->context()); | |
| 7713 bool is_global_proxy_access = | |
| 7714 maps->length() == 1 // More than one map, fallback to polymorphic?. | |
| 7715 && maps->first()->IsJSGlobalProxyMap() && | |
| 7716 isolate()->MayAccess(map_context, global_proxy); | |
| 7717 | |
| 7718 if (is_global_proxy_access) { | |
| 7719 LookupIterator it(global_object, name, LookupIterator::OWN); | |
| 7720 if (CanInlineGlobalPropertyAccess(&it, access)) { | |
| 7721 BuildCheckHeapObject(object); | |
| 7722 Add<HCheckMaps>(object, maps); | |
| 7723 if (access == LOAD) { | |
| 7724 InlineGlobalPropertyLoad(&it, expr->id()); | |
| 7725 } else { | |
| 7726 InlineGlobalPropertyStore(&it, value, expr->id()); | |
| 7727 } | |
| 7728 return NULL; | |
|
jochen (gone - plz use gerrit)
2016/09/30 10:49:25
nit. nullptr
| |
| 7729 } | |
| 7730 } | |
| 7731 } | |
| 7732 | |
| 7693 PropertyAccessInfo info(this, access, maps->first(), name); | 7733 PropertyAccessInfo info(this, access, maps->first(), name); |
| 7694 if (!info.CanAccessAsMonomorphic(maps)) { | 7734 if (!info.CanAccessAsMonomorphic(maps)) { |
| 7695 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, | 7735 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, |
| 7696 object, value, maps, name); | 7736 object, value, maps, name); |
| 7697 return NULL; | 7737 return NULL; |
| 7698 } | 7738 } |
| 7699 | 7739 |
| 7700 HValue* checked_object; | 7740 HValue* checked_object; |
| 7701 // AstType::Number() is only supported by polymorphic load/call handling. | 7741 // AstType::Number() is only supported by polymorphic load/call handling. |
| 7702 DCHECK(!info.IsNumberType()); | 7742 DCHECK(!info.IsNumberType()); |
| 7703 BuildCheckHeapObject(object); | 7743 BuildCheckHeapObject(object); |
| 7704 if (AreStringTypes(maps)) { | 7744 if (AreStringTypes(maps)) { |
| 7705 checked_object = | 7745 checked_object = |
| 7706 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 7746 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
| 7707 } else { | 7747 } else { |
| 7708 checked_object = Add<HCheckMaps>(object, maps); | 7748 checked_object = Add<HCheckMaps>(object, maps); |
| 7709 } | 7749 } |
| 7750 | |
|
jochen (gone - plz use gerrit)
2016/09/30 10:49:25
unrelated?
| |
| 7710 return BuildMonomorphicAccess( | 7751 return BuildMonomorphicAccess( |
| 7711 &info, object, checked_object, value, ast_id, return_id); | 7752 &info, object, checked_object, value, ast_id, return_id); |
| 7712 } | 7753 } |
| 7713 | 7754 |
| 7714 return BuildNamedGeneric(access, expr, slot, object, name, value, | 7755 return BuildNamedGeneric(access, expr, slot, object, name, value, |
| 7715 is_uninitialized); | 7756 is_uninitialized); |
| 7716 } | 7757 } |
| 7717 | 7758 |
| 7718 | 7759 |
| 7719 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 7760 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
| (...skipping 5568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13288 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13329 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13289 } | 13330 } |
| 13290 | 13331 |
| 13291 #ifdef DEBUG | 13332 #ifdef DEBUG |
| 13292 graph_->Verify(false); // No full verify. | 13333 graph_->Verify(false); // No full verify. |
| 13293 #endif | 13334 #endif |
| 13294 } | 13335 } |
| 13295 | 13336 |
| 13296 } // namespace internal | 13337 } // namespace internal |
| 13297 } // namespace v8 | 13338 } // namespace v8 |
| OLD | NEW |