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 LookupIterator TryReadingFromCache(Isolate* isolate, LookupIterator* it) { |
| 5496 if (it->state() != LookupIterator::ACCESSOR) return *it; |
| 5497 |
| 5498 Handle<Object> accessors = it->GetAccessors(); |
| 5499 if (!accessors->IsAccessorPair()) return *it; |
| 5500 |
| 5501 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
| 5502 isolate); |
| 5503 |
| 5504 MaybeHandle<Name> maybe_name = |
| 5505 FunctionTemplateInfo::TryGetCachePropertyName(isolate, getter); |
| 5506 if (maybe_name.is_null()) return *it; |
| 5507 |
| 5508 Handle<Name> name = maybe_name.ToHandleChecked(); |
| 5509 LookupIterator cache_it(it->GetReceiver(), name, it->GetHolder<JSObject>()); |
| 5510 CHECK_EQ(cache_it.state(), LookupIterator::DATA); |
| 5511 return cache_it; |
| 5512 } |
| 5513 |
| 5514 void HOptimizedGraphBuilder::InlineGlobalPropertyLoad(LookupIterator* it, |
| 5515 BailoutId ast_id) { |
| 5516 Handle<PropertyCell> cell = it->GetPropertyCell(); |
| 5517 top_info()->dependencies()->AssumePropertyCell(cell); |
| 5518 auto cell_type = it->property_details().cell_type(); |
| 5519 if (cell_type == PropertyCellType::kConstant || |
| 5520 cell_type == PropertyCellType::kUndefined) { |
| 5521 Handle<Object> constant_object(cell->value(), isolate()); |
| 5522 if (constant_object->IsConsString()) { |
| 5523 constant_object = String::Flatten(Handle<String>::cast(constant_object)); |
| 5524 } |
| 5525 HConstant* constant = New<HConstant>(constant_object); |
| 5526 return ast_context()->ReturnInstruction(constant, ast_id); |
| 5527 } else { |
| 5528 auto access = HObjectAccess::ForPropertyCellValue(); |
| 5529 UniqueSet<Map>* field_maps = nullptr; |
| 5530 if (cell_type == PropertyCellType::kConstantType) { |
| 5531 switch (cell->GetConstantType()) { |
| 5532 case PropertyCellConstantType::kSmi: |
| 5533 access = access.WithRepresentation(Representation::Smi()); |
| 5534 break; |
| 5535 case PropertyCellConstantType::kStableMap: { |
| 5536 // Check that the map really is stable. The heap object could |
| 5537 // have mutated without the cell updating state. In that case, |
| 5538 // make no promises about the loaded value except that it's a |
| 5539 // heap object. |
| 5540 access = access.WithRepresentation(Representation::HeapObject()); |
| 5541 Handle<Map> map(HeapObject::cast(cell->value())->map()); |
| 5542 if (map->is_stable()) { |
| 5543 field_maps = new (zone()) |
| 5544 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone()); |
| 5545 } |
| 5546 break; |
| 5547 } |
| 5548 } |
| 5549 } |
| 5550 HConstant* cell_constant = Add<HConstant>(cell); |
| 5551 HLoadNamedField* instr; |
| 5552 if (field_maps == nullptr) { |
| 5553 instr = New<HLoadNamedField>(cell_constant, nullptr, access); |
| 5554 } else { |
| 5555 instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps, |
| 5556 HType::HeapObject()); |
| 5557 } |
| 5558 instr->ClearDependsOnFlag(kInobjectFields); |
| 5559 instr->SetDependsOnFlag(kGlobalVars); |
| 5560 return ast_context()->ReturnInstruction(instr, ast_id); |
| 5561 } |
| 5562 } |
5491 | 5563 |
5492 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5564 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
5493 DCHECK(!HasStackOverflow()); | 5565 DCHECK(!HasStackOverflow()); |
5494 DCHECK(current_block() != NULL); | 5566 DCHECK(current_block() != NULL); |
5495 DCHECK(current_block()->HasPredecessor()); | 5567 DCHECK(current_block()->HasPredecessor()); |
5496 Variable* variable = expr->var(); | 5568 Variable* variable = expr->var(); |
5497 switch (variable->location()) { | 5569 switch (variable->location()) { |
5498 case VariableLocation::UNALLOCATED: { | 5570 case VariableLocation::UNALLOCATED: { |
5499 if (IsLexicalVariableMode(variable->mode())) { | 5571 if (IsLexicalVariableMode(variable->mode())) { |
5500 // TODO(rossberg): should this be an DCHECK? | 5572 // TODO(rossberg): should this be an DCHECK? |
(...skipping 27 matching lines...) Expand all Loading... |
5528 if (current_value->IsTheHole(isolate())) { | 5600 if (current_value->IsTheHole(isolate())) { |
5529 return Bailout(kReferenceToUninitializedVariable); | 5601 return Bailout(kReferenceToUninitializedVariable); |
5530 } | 5602 } |
5531 HInstruction* result = New<HLoadNamedField>( | 5603 HInstruction* result = New<HLoadNamedField>( |
5532 Add<HConstant>(script_context), nullptr, | 5604 Add<HConstant>(script_context), nullptr, |
5533 HObjectAccess::ForContextSlot(lookup.slot_index)); | 5605 HObjectAccess::ForContextSlot(lookup.slot_index)); |
5534 return ast_context()->ReturnInstruction(result, expr->id()); | 5606 return ast_context()->ReturnInstruction(result, expr->id()); |
5535 } | 5607 } |
5536 } | 5608 } |
5537 | 5609 |
5538 LookupIterator it(global, variable->name(), LookupIterator::OWN); | 5610 LookupIterator default_it(global, variable->name(), LookupIterator::OWN); |
5539 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); | 5611 LookupIterator it = TryReadingFromCache(isolate(), &default_it); |
5540 | 5612 if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) { |
5541 if (type == kUseCell) { | 5613 InlineGlobalPropertyLoad(&it, expr->id()); |
5542 Handle<PropertyCell> cell = it.GetPropertyCell(); | 5614 return; |
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 { | 5615 } else { |
5591 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 5616 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
5592 HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>( | 5617 HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>( |
5593 variable->name(), ast_context()->typeof_mode(), vector, | 5618 variable->name(), ast_context()->typeof_mode(), vector, |
5594 expr->VariableFeedbackSlot()); | 5619 expr->VariableFeedbackSlot()); |
5595 return ast_context()->ReturnInstruction(instr, expr->id()); | 5620 return ast_context()->ReturnInstruction(instr, expr->id()); |
5596 } | 5621 } |
5597 } | 5622 } |
5598 | 5623 |
5599 case VariableLocation::PARAMETER: | 5624 case VariableLocation::PARAMETER: |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6380 return BuildStoreNamedField(info, checked_object, value); | 6405 return BuildStoreNamedField(info, checked_object, value); |
6381 } | 6406 } |
6382 } | 6407 } |
6383 | 6408 |
6384 if (info->IsTransition()) { | 6409 if (info->IsTransition()) { |
6385 DCHECK(!info->IsLoad()); | 6410 DCHECK(!info->IsLoad()); |
6386 return BuildStoreNamedField(info, checked_object, value); | 6411 return BuildStoreNamedField(info, checked_object, value); |
6387 } | 6412 } |
6388 | 6413 |
6389 if (info->IsAccessorConstant()) { | 6414 if (info->IsAccessorConstant()) { |
| 6415 MaybeHandle<Name> maybe_name = |
| 6416 FunctionTemplateInfo::TryGetCachePropertyName(isolate(), |
| 6417 info->accessor()); |
| 6418 if (!maybe_name.is_null()) { |
| 6419 Handle<Name> name = maybe_name.ToHandleChecked(); |
| 6420 PropertyAccessInfo cache_info(this, LOAD, info->map(), name); |
| 6421 // Load new target. |
| 6422 if (cache_info.CanAccessMonomorphic()) |
| 6423 return BuildLoadNamedField(&cache_info, checked_object); |
| 6424 } |
| 6425 |
6390 Push(checked_object); | 6426 Push(checked_object); |
6391 int argument_count = 1; | 6427 int argument_count = 1; |
6392 if (!info->IsLoad()) { | 6428 if (!info->IsLoad()) { |
6393 argument_count = 2; | 6429 argument_count = 2; |
6394 Push(value); | 6430 Push(value); |
6395 } | 6431 } |
6396 | 6432 |
6397 if (info->accessor()->IsJSFunction() && | 6433 if (info->accessor()->IsJSFunction() && |
6398 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { | 6434 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { |
6399 HValue* function = Add<HConstant>(info->accessor()); | 6435 HValue* function = Add<HConstant>(info->accessor()); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6675 DCHECK(prop != NULL); | 6711 DCHECK(prop != NULL); |
6676 CHECK_ALIVE(VisitForValue(prop->obj())); | 6712 CHECK_ALIVE(VisitForValue(prop->obj())); |
6677 if (!prop->key()->IsPropertyName()) { | 6713 if (!prop->key()->IsPropertyName()) { |
6678 CHECK_ALIVE(VisitForValue(prop->key())); | 6714 CHECK_ALIVE(VisitForValue(prop->key())); |
6679 } | 6715 } |
6680 CHECK_ALIVE(VisitForValue(expr->value())); | 6716 CHECK_ALIVE(VisitForValue(expr->value())); |
6681 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), | 6717 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(), |
6682 expr->AssignmentId(), expr->IsUninitialized()); | 6718 expr->AssignmentId(), expr->IsUninitialized()); |
6683 } | 6719 } |
6684 | 6720 |
| 6721 void HOptimizedGraphBuilder::InlineGlobalPropertyStore(LookupIterator* it, |
| 6722 HValue* value, |
| 6723 BailoutId ast_id) { |
| 6724 Handle<PropertyCell> cell = it->GetPropertyCell(); |
| 6725 top_info()->dependencies()->AssumePropertyCell(cell); |
| 6726 auto cell_type = it->property_details().cell_type(); |
| 6727 if (cell_type == PropertyCellType::kConstant || |
| 6728 cell_type == PropertyCellType::kUndefined) { |
| 6729 Handle<Object> constant(cell->value(), isolate()); |
| 6730 if (value->IsConstant()) { |
| 6731 HConstant* c_value = HConstant::cast(value); |
| 6732 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
| 6733 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6734 Deoptimizer::EAGER); |
| 6735 } |
| 6736 } else { |
| 6737 HValue* c_constant = Add<HConstant>(constant); |
| 6738 IfBuilder builder(this); |
| 6739 if (constant->IsNumber()) { |
| 6740 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); |
| 6741 } else { |
| 6742 builder.If<HCompareObjectEqAndBranch>(value, c_constant); |
| 6743 } |
| 6744 builder.Then(); |
| 6745 builder.Else(); |
| 6746 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
| 6747 Deoptimizer::EAGER); |
| 6748 builder.End(); |
| 6749 } |
| 6750 } |
| 6751 HConstant* cell_constant = Add<HConstant>(cell); |
| 6752 auto access = HObjectAccess::ForPropertyCellValue(); |
| 6753 if (cell_type == PropertyCellType::kConstantType) { |
| 6754 switch (cell->GetConstantType()) { |
| 6755 case PropertyCellConstantType::kSmi: |
| 6756 access = access.WithRepresentation(Representation::Smi()); |
| 6757 break; |
| 6758 case PropertyCellConstantType::kStableMap: { |
| 6759 // The map may no longer be stable, deopt if it's ever different from |
| 6760 // what is currently there, which will allow for restablization. |
| 6761 Handle<Map> map(HeapObject::cast(cell->value())->map()); |
| 6762 Add<HCheckHeapObject>(value); |
| 6763 value = Add<HCheckMaps>(value, map); |
| 6764 access = access.WithRepresentation(Representation::HeapObject()); |
| 6765 break; |
| 6766 } |
| 6767 } |
| 6768 } |
| 6769 HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value); |
| 6770 instr->ClearChangesFlag(kInobjectFields); |
| 6771 instr->SetChangesFlag(kGlobalVars); |
| 6772 if (instr->HasObservableSideEffects()) { |
| 6773 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6774 } |
| 6775 } |
6685 | 6776 |
6686 // Because not every expression has a position and there is not common | 6777 // Because not every expression has a position and there is not common |
6687 // superclass of Assignment and CountOperation, we cannot just pass the | 6778 // superclass of Assignment and CountOperation, we cannot just pass the |
6688 // owning expression instead of position and ast_id separately. | 6779 // owning expression instead of position and ast_id separately. |
6689 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 6780 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
6690 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { | 6781 Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) { |
6691 Handle<JSGlobalObject> global(current_info()->global_object()); | 6782 Handle<JSGlobalObject> global(current_info()->global_object()); |
6692 | 6783 |
6693 // Lookup in script contexts. | 6784 // Lookup in script contexts. |
6694 { | 6785 { |
(...skipping 20 matching lines...) Expand all Loading... |
6715 Add<HConstant>(script_context), | 6806 Add<HConstant>(script_context), |
6716 HObjectAccess::ForContextSlot(lookup.slot_index), value); | 6807 HObjectAccess::ForContextSlot(lookup.slot_index), value); |
6717 USE(instr); | 6808 USE(instr); |
6718 DCHECK(instr->HasObservableSideEffects()); | 6809 DCHECK(instr->HasObservableSideEffects()); |
6719 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6810 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6720 return; | 6811 return; |
6721 } | 6812 } |
6722 } | 6813 } |
6723 | 6814 |
6724 LookupIterator it(global, var->name(), LookupIterator::OWN); | 6815 LookupIterator it(global, var->name(), LookupIterator::OWN); |
6725 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6816 if (CanInlineGlobalPropertyAccess(var, &it, STORE)) { |
6726 if (type == kUseCell) { | 6817 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 { | 6818 } else { |
6779 HValue* global_object = Add<HLoadNamedField>( | 6819 HValue* global_object = Add<HLoadNamedField>( |
6780 BuildGetNativeContext(), nullptr, | 6820 BuildGetNativeContext(), nullptr, |
6781 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); | 6821 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX)); |
6782 Handle<TypeFeedbackVector> vector = | 6822 Handle<TypeFeedbackVector> vector = |
6783 handle(current_feedback_vector(), isolate()); | 6823 handle(current_feedback_vector(), isolate()); |
6784 HValue* name = Add<HConstant>(var->name()); | 6824 HValue* name = Add<HConstant>(var->name()); |
6785 HValue* vector_value = Add<HConstant>(vector); | 6825 HValue* vector_value = Add<HConstant>(vector); |
6786 HValue* slot_value = Add<HConstant>(vector->GetIndex(slot)); | 6826 HValue* slot_value = Add<HConstant>(vector->GetIndex(slot)); |
6787 Callable callable = CodeFactory::StoreICInOptimizedCode( | 6827 Callable callable = CodeFactory::StoreICInOptimizedCode( |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7683 | 7723 |
7684 HValue* HOptimizedGraphBuilder::BuildNamedAccess( | 7724 HValue* HOptimizedGraphBuilder::BuildNamedAccess( |
7685 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, | 7725 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, |
7686 Expression* expr, FeedbackVectorSlot slot, HValue* object, | 7726 Expression* expr, FeedbackVectorSlot slot, HValue* object, |
7687 Handle<Name> name, HValue* value, bool is_uninitialized) { | 7727 Handle<Name> name, HValue* value, bool is_uninitialized) { |
7688 SmallMapList* maps; | 7728 SmallMapList* maps; |
7689 ComputeReceiverTypes(expr, object, &maps, this); | 7729 ComputeReceiverTypes(expr, object, &maps, this); |
7690 DCHECK(maps != NULL); | 7730 DCHECK(maps != NULL); |
7691 | 7731 |
7692 if (maps->length() > 0) { | 7732 if (maps->length() > 0) { |
| 7733 Handle<JSGlobalObject> global_object(current_info()->global_object()); |
| 7734 Handle<Context> current_context(current_info()->context()); |
| 7735 Handle<JSObject> global_proxy(current_context->global_proxy()); |
| 7736 |
| 7737 // Check for special case: Access via a single map to the global proxy |
| 7738 // can also be handled monomorphically. |
| 7739 Handle<Object> map_constructor = |
| 7740 handle(maps->first()->GetConstructor(), isolate()); |
| 7741 if (map_constructor->IsJSFunction()) { |
| 7742 Handle<Context> map_context = |
| 7743 handle(Handle<JSFunction>::cast(map_constructor)->context()); |
| 7744 bool is_global_proxy_access = |
| 7745 maps->length() == 1 // More than one map, fallback to polymorphic?. |
| 7746 && maps->first()->IsJSGlobalProxyMap() && |
| 7747 isolate()->MayAccess(map_context, global_proxy); |
| 7748 |
| 7749 if (is_global_proxy_access) { |
| 7750 LookupIterator default_it(global_object, name, LookupIterator::OWN); |
| 7751 // TODO(peterssen): Inline LOADS only?. |
| 7752 LookupIterator it = (access == LOAD) |
| 7753 ? TryReadingFromCache(isolate(), &default_it) |
| 7754 : default_it; |
| 7755 |
| 7756 if (CanInlineGlobalPropertyAccess(&it, access)) { |
| 7757 BuildCheckHeapObject(object); |
| 7758 Add<HCheckMaps>(object, maps); |
| 7759 if (access == LOAD) { |
| 7760 InlineGlobalPropertyLoad(&it, expr->id()); |
| 7761 } else { |
| 7762 InlineGlobalPropertyStore(&it, value, expr->id()); |
| 7763 } |
| 7764 return nullptr; |
| 7765 } |
| 7766 } |
| 7767 } |
| 7768 |
7693 PropertyAccessInfo info(this, access, maps->first(), name); | 7769 PropertyAccessInfo info(this, access, maps->first(), name); |
7694 if (!info.CanAccessAsMonomorphic(maps)) { | 7770 if (!info.CanAccessAsMonomorphic(maps)) { |
7695 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, | 7771 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, |
7696 object, value, maps, name); | 7772 object, value, maps, name); |
7697 return NULL; | 7773 return NULL; |
7698 } | 7774 } |
7699 | 7775 |
7700 HValue* checked_object; | 7776 HValue* checked_object; |
7701 // AstType::Number() is only supported by polymorphic load/call handling. | 7777 // AstType::Number() is only supported by polymorphic load/call handling. |
7702 DCHECK(!info.IsNumberType()); | 7778 DCHECK(!info.IsNumberType()); |
(...skipping 5585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13288 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13364 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13289 } | 13365 } |
13290 | 13366 |
13291 #ifdef DEBUG | 13367 #ifdef DEBUG |
13292 graph_->Verify(false); // No full verify. | 13368 graph_->Verify(false); // No full verify. |
13293 #endif | 13369 #endif |
13294 } | 13370 } |
13295 | 13371 |
13296 } // namespace internal | 13372 } // namespace internal |
13297 } // namespace v8 | 13373 } // namespace v8 |
OLD | NEW |