Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: src/crankshaft/hydrogen.cc

Issue 2369933005: Speedup global_proxy.* attributes/accessors (specialize GlobalProxy access). (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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::LookupGlobalPropertyCell(
5452 Variable* var, LookupIterator* it, PropertyAccessType access_type) {
5453 if (var->is_this()) return false;
5454 return LookupGlobalPropertyCell(it, access_type);
5455 }
5451 5456
5452 HOptimizedGraphBuilder::GlobalPropertyAccess 5457 bool HOptimizedGraphBuilder::LookupGlobalPropertyCell(
Toon Verwaest 2016/09/27 14:57:12 This should probably be called "CanInlineGlobalPro
Alfonso 2016/09/29 09:36:39 Done.
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
5479 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { 5482 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
5480 DCHECK(var->IsContextSlot()); 5483 DCHECK(var->IsContextSlot());
5481 HValue* context = environment()->context(); 5484 HValue* context = environment()->context();
5482 int length = scope()->ContextChainLength(var->scope()); 5485 int length = scope()->ContextChainLength(var->scope());
5483 while (length-- > 0) { 5486 while (length-- > 0) {
5484 context = Add<HLoadNamedField>( 5487 context = Add<HLoadNamedField>(
5485 context, nullptr, 5488 context, nullptr,
5486 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); 5489 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
5487 } 5490 }
5488 return context; 5491 return context;
5489 } 5492 }
5490 5493
5494 void HOptimizedGraphBuilder::LoadFromCell(LookupIterator* it,
Toon Verwaest 2016/09/27 14:57:11 And InlineGlobalPropertyAccess
Alfonso 2016/09/29 09:36:40 Done.
5495 BailoutId ast_id) {
5496 Handle<PropertyCell> cell = it->GetPropertyCell();
5497 top_info()->dependencies()->AssumePropertyCell(cell);
5498 auto cell_type = it->property_details().cell_type();
5499 if (cell_type == PropertyCellType::kConstant ||
5500 cell_type == PropertyCellType::kUndefined) {
5501 Handle<Object> constant_object(cell->value(), isolate());
5502 if (constant_object->IsConsString()) {
5503 constant_object = String::Flatten(Handle<String>::cast(constant_object));
5504 }
5505 HConstant* constant = New<HConstant>(constant_object);
5506 return ast_context()->ReturnInstruction(constant, ast_id);
5507 } else {
5508 auto access = HObjectAccess::ForPropertyCellValue();
5509 UniqueSet<Map>* field_maps = nullptr;
5510 if (cell_type == PropertyCellType::kConstantType) {
5511 switch (cell->GetConstantType()) {
5512 case PropertyCellConstantType::kSmi:
5513 access = access.WithRepresentation(Representation::Smi());
5514 break;
5515 case PropertyCellConstantType::kStableMap: {
5516 // Check that the map really is stable. The heap object could
5517 // have mutated without the cell updating state. In that case,
5518 // make no promises about the loaded value except that it's a
5519 // heap object.
5520 access = access.WithRepresentation(Representation::HeapObject());
5521 Handle<Map> map(HeapObject::cast(cell->value())->map());
5522 if (map->is_stable()) {
5523 field_maps = new (zone())
5524 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
5525 }
5526 break;
5527 }
5528 }
5529 }
5530 HConstant* cell_constant = Add<HConstant>(cell);
5531 HLoadNamedField* instr;
5532 if (field_maps == nullptr) {
5533 instr = New<HLoadNamedField>(cell_constant, nullptr, access);
5534 } else {
5535 instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps,
5536 HType::HeapObject());
5537 }
5538 instr->ClearDependsOnFlag(kInobjectFields);
5539 instr->SetDependsOnFlag(kGlobalVars);
5540 return ast_context()->ReturnInstruction(instr, ast_id);
5541 }
5542 }
5491 5543
5492 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 5544 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
5493 DCHECK(!HasStackOverflow()); 5545 DCHECK(!HasStackOverflow());
5494 DCHECK(current_block() != NULL); 5546 DCHECK(current_block() != NULL);
5495 DCHECK(current_block()->HasPredecessor()); 5547 DCHECK(current_block()->HasPredecessor());
5496 Variable* variable = expr->var(); 5548 Variable* variable = expr->var();
5497 switch (variable->location()) { 5549 switch (variable->location()) {
5498 case VariableLocation::UNALLOCATED: { 5550 case VariableLocation::UNALLOCATED: {
5499 if (IsLexicalVariableMode(variable->mode())) { 5551 if (IsLexicalVariableMode(variable->mode())) {
5500 // TODO(rossberg): should this be an DCHECK? 5552 // TODO(rossberg): should this be an DCHECK?
(...skipping 28 matching lines...) Expand all
5529 return Bailout(kReferenceToUninitializedVariable); 5581 return Bailout(kReferenceToUninitializedVariable);
5530 } 5582 }
5531 HInstruction* result = New<HLoadNamedField>( 5583 HInstruction* result = New<HLoadNamedField>(
5532 Add<HConstant>(script_context), nullptr, 5584 Add<HConstant>(script_context), nullptr,
5533 HObjectAccess::ForContextSlot(lookup.slot_index)); 5585 HObjectAccess::ForContextSlot(lookup.slot_index));
5534 return ast_context()->ReturnInstruction(result, expr->id()); 5586 return ast_context()->ReturnInstruction(result, expr->id());
5535 } 5587 }
5536 } 5588 }
5537 5589
5538 LookupIterator it(global, variable->name(), LookupIterator::OWN); 5590 LookupIterator it(global, variable->name(), LookupIterator::OWN);
5539 GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD); 5591 if (LookupGlobalPropertyCell(variable, &it, LOAD)) {
5540 5592 return LoadFromCell(&it, expr->id());
vogelheim 2016/09/27 13:36:54 LoadFromCell returns void. You *can* return a void
Alfonso 2016/09/29 09:36:40 Done.
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 }
5590 } else { 5593 } else {
5591 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); 5594 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
5592 HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>( 5595 HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>(
5593 variable->name(), ast_context()->typeof_mode(), vector, 5596 variable->name(), ast_context()->typeof_mode(), vector,
5594 expr->VariableFeedbackSlot()); 5597 expr->VariableFeedbackSlot());
5595 return ast_context()->ReturnInstruction(instr, expr->id()); 5598 return ast_context()->ReturnInstruction(instr, expr->id());
5596 } 5599 }
5597 } 5600 }
5598 5601
5599 case VariableLocation::PARAMETER: 5602 case VariableLocation::PARAMETER:
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
6254 6257
6255 6258
6256 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { 6259 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
6257 if (!CanInlinePropertyAccess(map_)) return false; 6260 if (!CanInlinePropertyAccess(map_)) return false;
6258 if (IsJSObjectFieldAccessor()) return IsLoad(); 6261 if (IsJSObjectFieldAccessor()) return IsLoad();
6259 if (map_->IsJSFunctionMap() && map_->is_constructor() && 6262 if (map_->IsJSFunctionMap() && map_->is_constructor() &&
6260 !map_->has_non_instance_prototype() && 6263 !map_->has_non_instance_prototype() &&
6261 name_.is_identical_to(isolate()->factory()->prototype_string())) { 6264 name_.is_identical_to(isolate()->factory()->prototype_string())) {
6262 return IsLoad(); 6265 return IsLoad();
6263 } 6266 }
6267
6264 if (!LookupDescriptor()) return false; 6268 if (!LookupDescriptor()) return false;
6265 if (IsFound()) return IsLoad() || !IsReadOnly(); 6269 if (IsFound()) return IsLoad() || !IsReadOnly();
6266 if (IsIntegerIndexedExotic()) return false; 6270 if (IsIntegerIndexedExotic()) return false;
6267 if (!LookupInPrototypes()) return false; 6271 if (!LookupInPrototypes()) return false;
6268 if (IsLoad()) return true; 6272 if (IsLoad()) return true;
6269 6273
6270 if (IsAccessorConstant()) return true; 6274 if (IsAccessorConstant()) return true;
6271 LookupTransition(*map_, *name_, NONE); 6275 LookupTransition(*map_, *name_, NONE);
6272 if (IsTransitionToData() && map_->unused_property_fields() > 0) { 6276 if (IsTransitionToData() && map_->unused_property_fields() > 0) {
6273 // Construct the object field access. 6277 // Construct the object field access.
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
6715 Add<HConstant>(script_context), 6719 Add<HConstant>(script_context),
6716 HObjectAccess::ForContextSlot(lookup.slot_index), value); 6720 HObjectAccess::ForContextSlot(lookup.slot_index), value);
6717 USE(instr); 6721 USE(instr);
6718 DCHECK(instr->HasObservableSideEffects()); 6722 DCHECK(instr->HasObservableSideEffects());
6719 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6723 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6720 return; 6724 return;
6721 } 6725 }
6722 } 6726 }
6723 6727
6724 LookupIterator it(global, var->name(), LookupIterator::OWN); 6728 LookupIterator it(global, var->name(), LookupIterator::OWN);
6725 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); 6729 if (LookupGlobalPropertyCell(var, &it, STORE)) {
6726 if (type == kUseCell) {
6727 Handle<PropertyCell> cell = it.GetPropertyCell(); 6730 Handle<PropertyCell> cell = it.GetPropertyCell();
6728 top_info()->dependencies()->AssumePropertyCell(cell); 6731 top_info()->dependencies()->AssumePropertyCell(cell);
6729 auto cell_type = it.property_details().cell_type(); 6732 auto cell_type = it.property_details().cell_type();
6730 if (cell_type == PropertyCellType::kConstant || 6733 if (cell_type == PropertyCellType::kConstant ||
6731 cell_type == PropertyCellType::kUndefined) { 6734 cell_type == PropertyCellType::kUndefined) {
6732 Handle<Object> constant(cell->value(), isolate()); 6735 Handle<Object> constant(cell->value(), isolate());
6733 if (value->IsConstant()) { 6736 if (value->IsConstant()) {
6734 HConstant* c_value = HConstant::cast(value); 6737 HConstant* c_value = HConstant::cast(value);
6735 if (!constant.is_identical_to(c_value->handle(isolate()))) { 6738 if (!constant.is_identical_to(c_value->handle(isolate()))) {
6736 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, 6739 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment,
(...skipping 947 matching lines...) Expand 10 before | Expand all | Expand 10 after
7684 HValue* HOptimizedGraphBuilder::BuildNamedAccess( 7687 HValue* HOptimizedGraphBuilder::BuildNamedAccess(
7685 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, 7688 PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
7686 Expression* expr, FeedbackVectorSlot slot, HValue* object, 7689 Expression* expr, FeedbackVectorSlot slot, HValue* object,
7687 Handle<Name> name, HValue* value, bool is_uninitialized) { 7690 Handle<Name> name, HValue* value, bool is_uninitialized) {
7688 SmallMapList* maps; 7691 SmallMapList* maps;
7689 ComputeReceiverTypes(expr, object, &maps, this); 7692 ComputeReceiverTypes(expr, object, &maps, this);
7690 DCHECK(maps != NULL); 7693 DCHECK(maps != NULL);
7691 7694
7692 if (maps->length() > 0) { 7695 if (maps->length() > 0) {
7693 PropertyAccessInfo info(this, access, maps->first(), name); 7696 PropertyAccessInfo info(this, access, maps->first(), name);
7694 if (!info.CanAccessAsMonomorphic(maps)) { 7697 bool can_access_mono = info.CanAccessAsMonomorphic(maps);
vogelheim 2016/09/27 13:36:54 can_access_monomorphic
Alfonso 2016/09/29 09:36:40 Done.
7698 // TODO(peterssen): Add context access check.
7699 // More than one map? Polymorphic.
vogelheim 2016/09/27 13:36:54 This comment comments on one of the sub-clauses in
Alfonso 2016/09/29 09:36:40 Done.
7700 bool is_global_proxy = maps->length() == 1 && !can_access_mono &&
Toon Verwaest 2016/09/27 14:57:11 Why doesn't CanAccessMonomorphic just return true
Alfonso 2016/09/29 09:36:39 CanAccessMonomorphic has many checks and some of t
7701 maps->first()->IsJSGlobalProxyMap();
7702 if (!can_access_mono && !is_global_proxy) {
7695 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id, 7703 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
7696 object, value, maps, name); 7704 object, value, maps, name);
7697 return NULL; 7705 return NULL;
7698 } 7706 }
7699 7707
7700 HValue* checked_object; 7708 HValue* checked_object;
7701 // AstType::Number() is only supported by polymorphic load/call handling. 7709 // AstType::Number() is only supported by polymorphic load/call handling.
7702 DCHECK(!info.IsNumberType()); 7710 DCHECK(!info.IsNumberType());
7703 BuildCheckHeapObject(object); 7711 BuildCheckHeapObject(object);
7704 if (AreStringTypes(maps)) { 7712 if (AreStringTypes(maps)) {
7705 checked_object = 7713 checked_object =
7706 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); 7714 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
7707 } else { 7715 } else {
7708 checked_object = Add<HCheckMaps>(object, maps); 7716 checked_object = Add<HCheckMaps>(object, maps);
7709 } 7717 }
7718
7719 if (is_global_proxy) {
7720 Handle<JSGlobalObject> global(current_info()->global_object());
7721 LookupIterator it(global, name, LookupIterator::OWN);
7722 if (LookupGlobalPropertyCell(&it, LOAD)) {
7723 LoadFromCell(&it, expr->id());
7724 return NULL;
vogelheim 2016/09/27 13:36:54 [I don't understand Crankshaft at all, and am mere
Alfonso 2016/09/29 09:36:40 To my understanding, returning NULL means that the
7725 }
7726 }
Toon Verwaest 2016/09/27 14:57:11 Doesn't this fall-through mean that you'll try to
Alfonso 2016/09/29 09:36:40 Done.
7727
7710 return BuildMonomorphicAccess( 7728 return BuildMonomorphicAccess(
7711 &info, object, checked_object, value, ast_id, return_id); 7729 &info, object, checked_object, value, ast_id, return_id);
7712 } 7730 }
7713 7731
7714 return BuildNamedGeneric(access, expr, slot, object, name, value, 7732 return BuildNamedGeneric(access, expr, slot, object, name, value,
7715 is_uninitialized); 7733 is_uninitialized);
7716 } 7734 }
7717 7735
7718 7736
7719 void HOptimizedGraphBuilder::PushLoad(Property* expr, 7737 void HOptimizedGraphBuilder::PushLoad(Property* expr,
(...skipping 5568 matching lines...) Expand 10 before | Expand all | Expand 10 after
13288 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 13306 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
13289 } 13307 }
13290 13308
13291 #ifdef DEBUG 13309 #ifdef DEBUG
13292 graph_->Verify(false); // No full verify. 13310 graph_->Verify(false); // No full verify.
13293 #endif 13311 #endif
13294 } 13312 }
13295 13313
13296 } // namespace internal 13314 } // namespace internal
13297 } // namespace v8 13315 } // namespace v8
OLDNEW
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698