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

Side by Side Diff: src/hydrogen.cc

Issue 147763006: Support loads from primitive values. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | 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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4906 matching lines...) Expand 10 before | Expand all | Expand 10 after
4917 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 4917 Handle<JSFunction> closure = function_state()->compilation_info()->closure();
4918 Handle<FixedArray> literals(closure->literals()); 4918 Handle<FixedArray> literals(closure->literals());
4919 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, 4919 HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
4920 expr->pattern(), 4920 expr->pattern(),
4921 expr->flags(), 4921 expr->flags(),
4922 expr->literal_index()); 4922 expr->literal_index());
4923 return ast_context()->ReturnInstruction(instr, expr->id()); 4923 return ast_context()->ReturnInstruction(instr, expr->id());
4924 } 4924 }
4925 4925
4926 4926
4927 static bool CanInlinePropertyAccess(Map* type) { 4927 static bool CanInlinePropertyAccess(Handle<HeapType> type) {
4928 return type->IsJSObjectMap() && 4928 if (type->Is(HeapType::NumberOrString())) return true;
4929 !type->is_dictionary_map() && 4929 if (!type->IsClass()) return false;
4930 !type->has_named_interceptor(); 4930 Handle<Map> map = type->AsClass();
4931 return map->IsJSObjectMap() &&
4932 !map->is_dictionary_map() &&
4933 !map->has_named_interceptor();
4931 } 4934 }
4932 4935
4933 4936
4934 static void LookupInPrototypes(Handle<Map> map, 4937 static void LookupInPrototypes(Handle<Map> map,
4935 Handle<String> name, 4938 Handle<String> name,
4936 LookupResult* lookup) { 4939 LookupResult* lookup) {
4937 while (map->prototype()->IsJSObject()) { 4940 while (map->prototype()->IsJSObject()) {
4938 Handle<JSObject> holder(JSObject::cast(map->prototype())); 4941 Handle<JSObject> holder(JSObject::cast(map->prototype()));
4939 map = Handle<Map>(holder->map()); 4942 map = handle(holder->map());
4940 if (!CanInlinePropertyAccess(*map)) break; 4943 if (!CanInlinePropertyAccess(IC::MapToType(map))) break;
4941 map->LookupDescriptor(*holder, *name, lookup); 4944 map->LookupDescriptor(*holder, *name, lookup);
4942 if (lookup->IsFound()) return; 4945 if (lookup->IsFound()) return;
4943 } 4946 }
4944 lookup->NotFound(); 4947 lookup->NotFound();
4945 } 4948 }
4946 4949
4947 4950
4948 // Tries to find a JavaScript accessor of the given name in the prototype chain 4951 // Tries to find a JavaScript accessor of the given name in the prototype chain
4949 // starting at the given map. Return true iff there is one, including the 4952 // starting at the given map. Return true iff there is one, including the
4950 // corresponding AccessorPair plus its holder (which could be null when the 4953 // corresponding AccessorPair plus its holder (which could be null when the
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
5431 function_strict_mode_flag()); 5434 function_strict_mode_flag());
5432 } 5435 }
5433 5436
5434 5437
5435 // Sets the lookup result and returns true if the load/store can be inlined. 5438 // Sets the lookup result and returns true if the load/store can be inlined.
5436 static bool ComputeStoreField(Handle<Map> type, 5439 static bool ComputeStoreField(Handle<Map> type,
5437 Handle<String> name, 5440 Handle<String> name,
5438 LookupResult* lookup, 5441 LookupResult* lookup,
5439 bool lookup_transition = true) { 5442 bool lookup_transition = true) {
5440 ASSERT(!type->is_observed()); 5443 ASSERT(!type->is_observed());
5441 if (!CanInlinePropertyAccess(*type)) { 5444 if (!CanInlinePropertyAccess(IC::MapToType(type))) {
5442 lookup->NotFound(); 5445 lookup->NotFound();
5443 return false; 5446 return false;
5444 } 5447 }
5445 // If we directly find a field, the access can be inlined. 5448 // If we directly find a field, the access can be inlined.
5446 type->LookupDescriptor(NULL, *name, lookup); 5449 type->LookupDescriptor(NULL, *name, lookup);
5447 if (lookup->IsField()) return true; 5450 if (lookup->IsField()) return true;
5448 5451
5449 if (!lookup_transition) return false; 5452 if (!lookup_transition) return false;
5450 5453
5451 type->LookupTransition(NULL, *name, lookup); 5454 type->LookupTransition(NULL, *name, lookup);
(...skipping 14 matching lines...) Expand all
5466 return BuildStoreNamedField(checked_object, name, value, map, &lookup); 5469 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
5467 } 5470 }
5468 5471
5469 // No luck, do a generic store. 5472 // No luck, do a generic store.
5470 return BuildStoreNamedGeneric(object, name, value); 5473 return BuildStoreNamedGeneric(object, name, value);
5471 } 5474 }
5472 5475
5473 5476
5474 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad( 5477 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad(
5475 PropertyAccessInfo* info) { 5478 PropertyAccessInfo* info) {
5476 if (!CanInlinePropertyAccess(*map_)) return false; 5479 if (!CanInlinePropertyAccess(type_)) return false;
5480
5481 // Currently only handle HeapType::Number as a polymorphic case.
5482 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5483 // instruction.
5484 if (type_->Is(HeapType::Number())) return false;
5485
5486 // Values are only compatible for monomorphic load if they all behave the same
5487 // regarding value wrappers.
5488 if (type_->Is(HeapType::NumberOrString())) {
5489 if (!info->type_->Is(HeapType::NumberOrString())) return false;
5490 } else {
5491 if (info->type_->Is(HeapType::NumberOrString())) return false;
5492 }
5477 5493
5478 if (!LookupDescriptor()) return false; 5494 if (!LookupDescriptor()) return false;
5479 5495
5480 if (!lookup_.IsFound()) { 5496 if (!lookup_.IsFound()) {
5481 return (!info->lookup_.IsFound() || info->has_holder()) && 5497 return (!info->lookup_.IsFound() || info->has_holder()) &&
5482 map_->prototype() == info->map_->prototype(); 5498 map()->prototype() == info->map()->prototype();
5483 } 5499 }
5484 5500
5485 // Mismatch if the other access info found the property in the prototype 5501 // Mismatch if the other access info found the property in the prototype
5486 // chain. 5502 // chain.
5487 if (info->has_holder()) return false; 5503 if (info->has_holder()) return false;
5488 5504
5489 if (lookup_.IsPropertyCallbacks()) { 5505 if (lookup_.IsPropertyCallbacks()) {
5490 return accessor_.is_identical_to(info->accessor_); 5506 return accessor_.is_identical_to(info->accessor_);
5491 } 5507 }
5492 5508
5493 if (lookup_.IsConstant()) { 5509 if (lookup_.IsConstant()) {
5494 return constant_.is_identical_to(info->constant_); 5510 return constant_.is_identical_to(info->constant_);
5495 } 5511 }
5496 5512
5497 ASSERT(lookup_.IsField()); 5513 ASSERT(lookup_.IsField());
5498 if (!info->lookup_.IsField()) return false; 5514 if (!info->lookup_.IsField()) return false;
5499 5515
5500 Representation r = access_.representation(); 5516 Representation r = access_.representation();
5501 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; 5517 if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
5502 if (info->access_.offset() != access_.offset()) return false; 5518 if (info->access_.offset() != access_.offset()) return false;
5503 if (info->access_.IsInobject() != access_.IsInobject()) return false; 5519 if (info->access_.IsInobject() != access_.IsInobject()) return false;
5504 info->GeneralizeRepresentation(r); 5520 info->GeneralizeRepresentation(r);
5505 return true; 5521 return true;
5506 } 5522 }
5507 5523
5508 5524
5509 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() { 5525 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
5510 map_->LookupDescriptor(NULL, *name_, &lookup_); 5526 if (!type_->IsClass()) return true;
5511 return LoadResult(map_); 5527 map()->LookupDescriptor(NULL, *name_, &lookup_);
5528 return LoadResult(map());
5512 } 5529 }
5513 5530
5514 5531
5515 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { 5532 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
5516 if (lookup_.IsField()) { 5533 if (lookup_.IsField()) {
5517 access_ = HObjectAccess::ForField(map, &lookup_, name_); 5534 access_ = HObjectAccess::ForField(map, &lookup_, name_);
5518 } else if (lookup_.IsPropertyCallbacks()) { 5535 } else if (lookup_.IsPropertyCallbacks()) {
5519 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate()); 5536 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
5520 if (!callback->IsAccessorPair()) return false; 5537 if (!callback->IsAccessorPair()) return false;
5521 Object* getter = Handle<AccessorPair>::cast(callback)->getter(); 5538 Object* getter = Handle<AccessorPair>::cast(callback)->getter();
5522 if (!getter->IsJSFunction()) return false; 5539 if (!getter->IsJSFunction()) return false;
5523 Handle<JSFunction> accessor = handle(JSFunction::cast(getter)); 5540 Handle<JSFunction> accessor = handle(JSFunction::cast(getter));
5524 CallOptimization call_optimization(accessor); 5541 CallOptimization call_optimization(accessor);
5525 // TODO(dcarney): temporary hack unless crankshaft can handle api calls. 5542 // TODO(dcarney): temporary hack unless crankshaft can handle api calls.
5526 if (call_optimization.is_simple_api_call()) return false; 5543 if (call_optimization.is_simple_api_call()) return false;
5527 accessor_ = accessor; 5544 accessor_ = accessor;
5528 } else if (lookup_.IsConstant()) { 5545 } else if (lookup_.IsConstant()) {
5529 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate()); 5546 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
5530 } 5547 }
5531 5548
5532 return true; 5549 return true;
5533 } 5550 }
5534 5551
5535 5552
5536 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { 5553 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
5537 Handle<Map> map = map_; 5554 Handle<Map> map = this->map();
5555
5538 while (map->prototype()->IsJSObject()) { 5556 while (map->prototype()->IsJSObject()) {
5539 holder_ = handle(JSObject::cast(map->prototype())); 5557 holder_ = handle(JSObject::cast(map->prototype()));
5540 if (holder_->map()->is_deprecated()) { 5558 if (holder_->map()->is_deprecated()) {
5541 JSObject::TryMigrateInstance(holder_); 5559 JSObject::TryMigrateInstance(holder_);
5542 } 5560 }
5543 map = Handle<Map>(holder_->map()); 5561 map = Handle<Map>(holder_->map());
5544 if (!CanInlinePropertyAccess(*map)) { 5562 if (!CanInlinePropertyAccess(IC::MapToType(map))) {
5545 lookup_.NotFound(); 5563 lookup_.NotFound();
5546 return false; 5564 return false;
5547 } 5565 }
5548 map->LookupDescriptor(*holder_, *name_, &lookup_); 5566 map->LookupDescriptor(*holder_, *name_, &lookup_);
5549 if (lookup_.IsFound()) return LoadResult(map); 5567 if (lookup_.IsFound()) return LoadResult(map);
5550 } 5568 }
5551 lookup_.NotFound(); 5569 lookup_.NotFound();
5552 return true; 5570 return true;
5553 } 5571 }
5554 5572
5555 5573
5556 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { 5574 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() {
5557 if (!CanInlinePropertyAccess(*map_)) return IsStringLength(); 5575 if (!CanInlinePropertyAccess(type_)) return false;
5558 if (IsJSObjectFieldAccessor()) return true; 5576 if (IsJSObjectFieldAccessor()) return true;
5559 if (!LookupDescriptor()) return false; 5577 if (!LookupDescriptor()) return false;
5560 if (lookup_.IsFound()) return true; 5578 if (lookup_.IsFound()) return true;
5561 return LookupInPrototypes(); 5579 return LookupInPrototypes();
5562 } 5580 }
5563 5581
5564 5582
5565 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( 5583 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic(
5566 SmallMapList* types) { 5584 SmallMapList* types) {
5567 ASSERT(map_.is_identical_to(types->first())); 5585 ASSERT(type_->Is(IC::MapToType(types->first())));
5568 if (!CanLoadMonomorphic()) return false; 5586 if (!CanLoadMonomorphic()) return false;
5569 if (types->length() > kMaxLoadPolymorphism) return false; 5587 if (types->length() > kMaxLoadPolymorphism) return false;
5570 5588
5571 if (IsStringLength()) {
5572 for (int i = 1; i < types->length(); ++i) {
5573 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
5574 }
5575 return true;
5576 }
5577
5578 if (IsArrayLength()) { 5589 if (IsArrayLength()) {
5579 bool is_fast = IsFastElementsKind(map_->elements_kind()); 5590 bool is_fast = IsFastElementsKind(map()->elements_kind());
5580 for (int i = 1; i < types->length(); ++i) { 5591 for (int i = 1; i < types->length(); ++i) {
5581 Handle<Map> test_map = types->at(i); 5592 Handle<Map> test_map = types->at(i);
5582 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; 5593 if (test_map->instance_type() != JS_ARRAY_TYPE) return false;
5583 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { 5594 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) {
5584 return false; 5595 return false;
5585 } 5596 }
5586 } 5597 }
5587 return true; 5598 return true;
5588 } 5599 }
5589 5600
5590 if (IsJSObjectFieldAccessor()) { 5601 HObjectAccess access = HObjectAccess::ForMap(); // bogus default
5591 InstanceType instance_type = map_->instance_type(); 5602 if (GetJSObjectFieldAccess(&access)) {
5592 for (int i = 1; i < types->length(); ++i) { 5603 for (int i = 1; i < types->length(); ++i) {
5593 if (types->at(i)->instance_type() != instance_type) return false; 5604 PropertyAccessInfo test_info(
5605 builder_, IC::MapToType(types->at(i)), name_);
5606 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default
5607 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
5608 if (!access.Equals(test_access)) return false;
5594 } 5609 }
5595 return true; 5610 return true;
5596 } 5611 }
5597 5612
5613 // Currently only handle HeapType::Number as a polymorphic case.
5614 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5615 // instruction.
5616 if (type_->Is(HeapType::Number())) return false;
5617
5598 for (int i = 1; i < types->length(); ++i) { 5618 for (int i = 1; i < types->length(); ++i) {
5599 PropertyAccessInfo test_info(isolate(), types->at(i), name_); 5619 PropertyAccessInfo test_info(builder_, IC::MapToType(types->at(i)), name_);
5600 if (!test_info.IsCompatibleForLoad(this)) return false; 5620 if (!test_info.IsCompatibleForLoad(this)) return false;
5601 } 5621 }
5602 5622
5603 return true; 5623 return true;
5604 } 5624 }
5605 5625
5606 5626
5627 static bool NeedsWrappingFor(Handle<HeapType> type, Handle<JSFunction> target) {
5628 return type->Is(HeapType::NumberOrString()) &&
5629 target->shared()->is_classic_mode() &&
5630 !target->shared()->native();
5631 }
5632
5633
5607 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( 5634 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic(
5608 PropertyAccessInfo* info, 5635 PropertyAccessInfo* info,
5609 HValue* object, 5636 HValue* object,
5610 HInstruction* checked_object, 5637 HValue* checked_object,
5611 BailoutId ast_id, 5638 BailoutId ast_id,
5612 BailoutId return_id, 5639 BailoutId return_id,
5613 bool can_inline_accessor) { 5640 bool can_inline_accessor) {
5614 5641
5615 HObjectAccess access = HObjectAccess::ForMap(); // bogus default 5642 HObjectAccess access = HObjectAccess::ForMap(); // bogus default
5616 if (info->GetJSObjectFieldAccess(&access)) { 5643 if (info->GetJSObjectFieldAccess(&access)) {
5617 return New<HLoadNamedField>( 5644 return New<HLoadNamedField>(
5618 checked_object, static_cast<HValue*>(NULL), access); 5645 checked_object, static_cast<HValue*>(NULL), access);
5619 } 5646 }
5620 5647
5621 HValue* checked_holder = checked_object; 5648 HValue* checked_holder = checked_object;
5622 if (info->has_holder()) { 5649 if (info->has_holder()) {
5623 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); 5650 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
5624 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); 5651 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
5625 } 5652 }
5626 5653
5627 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); 5654 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined();
5628 5655
5629 if (info->lookup()->IsField()) { 5656 if (info->lookup()->IsField()) {
5630 return BuildLoadNamedField(checked_holder, info->access()); 5657 return BuildLoadNamedField(checked_holder, info->access());
5631 } 5658 }
5632 5659
5633 if (info->lookup()->IsPropertyCallbacks()) { 5660 if (info->lookup()->IsPropertyCallbacks()) {
5634 Push(checked_object); 5661 if (NeedsWrappingFor(info->type(), info->accessor())) {
5635 if (FLAG_inline_accessors && 5662 return New<HLoadNamedGeneric>(checked_object, info->name());
5636 can_inline_accessor && 5663 // HValue* function = Add<HConstant>(info->accessor());
5637 TryInlineGetter(info->accessor(), ast_id, return_id)) { 5664 // Add<HPushArgument>(checked_object);
5638 return NULL; 5665 // return New<HCallFunction>(function, 1, WRAP_AND_CALL);
5666 } else {
5667 Push(checked_object);
5668 if (FLAG_inline_accessors &&
5669 can_inline_accessor &&
5670 TryInlineGetter(info->accessor(), ast_id, return_id)) {
5671 return NULL;
5672 }
5673 Add<HPushArgument>(Pop());
5674 return BuildCallConstantFunction(info->accessor(), 1);
5639 } 5675 }
5640 Add<HPushArgument>(Pop());
5641 return BuildCallConstantFunction(info->accessor(), 1);
5642 } 5676 }
5643 5677
5644 ASSERT(info->lookup()->IsConstant()); 5678 ASSERT(info->lookup()->IsConstant());
5645 return New<HConstant>(info->constant()); 5679 return New<HConstant>(info->constant());
5646 } 5680 }
5647 5681
5648 5682
5649 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 5683 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
5650 BailoutId ast_id, 5684 BailoutId ast_id,
5651 BailoutId return_id, 5685 BailoutId return_id,
5652 HValue* object, 5686 HValue* object,
5653 SmallMapList* types, 5687 SmallMapList* types,
5654 Handle<String> name) { 5688 Handle<String> name) {
5655 // Something did not match; must use a polymorphic load. 5689 // Something did not match; must use a polymorphic load.
5656 int count = 0; 5690 int count = 0;
5657 HBasicBlock* join = NULL; 5691 HBasicBlock* join = NULL;
5692 HBasicBlock* number_block = NULL;
5693
5694 bool handle_smi = false;
5658 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 5695 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5659 PropertyAccessInfo info(isolate(), types->at(i), name); 5696 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name);
5660 if (info.CanLoadMonomorphic()) { 5697 if (info.CanLoadMonomorphic()) {
5661 if (count == 0) { 5698 count++;
5662 BuildCheckHeapObject(object); 5699 if (info.type()->Is(HeapType::Number())) {
5663 join = graph()->CreateBasicBlock(); 5700 handle_smi = true;
5701 break;
5664 } 5702 }
5665 ++count;
5666 HBasicBlock* if_true = graph()->CreateBasicBlock();
5667 HBasicBlock* if_false = graph()->CreateBasicBlock();
5668 HCompareMap* compare = New<HCompareMap>(
5669 object, info.map(), if_true, if_false);
5670 FinishCurrentBlock(compare);
5671
5672 set_current_block(if_true);
5673
5674 HInstruction* load = BuildLoadMonomorphic(
5675 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining);
5676 if (load == NULL) {
5677 if (HasStackOverflow()) return;
5678 } else {
5679 if (!load->IsLinked()) {
5680 AddInstruction(load);
5681 }
5682 if (!ast_context()->IsEffect()) Push(load);
5683 }
5684
5685 if (current_block() != NULL) Goto(join);
5686 set_current_block(if_false);
5687 } 5703 }
5688 } 5704 }
5689 5705
5706 count = 0;
5707 bool handled_string = false;
5708 HControlInstruction* smi_check = NULL;
5709
5710 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
5711 PropertyAccessInfo info(this, IC::MapToType(types->at(i)), name);
5712 if (info.type()->Is(HeapType::String())) {
5713 if (handled_string) continue;
5714 handled_string = true;
5715 }
5716 if (!info.CanLoadMonomorphic()) continue;
5717
5718 if (count == 0) {
5719 join = graph()->CreateBasicBlock();
5720 if (handle_smi) {
5721 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
5722 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
5723 number_block = graph()->CreateBasicBlock();
5724 smi_check = New<HIsSmiAndBranch>(
5725 object, empty_smi_block, not_smi_block);
5726 FinishCurrentBlock(smi_check);
5727 Goto(empty_smi_block, number_block);
5728 set_current_block(not_smi_block);
5729 } else {
5730 BuildCheckHeapObject(object);
5731 }
5732 }
5733 ++count;
5734 HBasicBlock* if_true = graph()->CreateBasicBlock();
5735 HBasicBlock* if_false = graph()->CreateBasicBlock();
5736 HUnaryControlInstruction* compare;
5737
5738 HValue* dependency;
5739 if (info.type()->Is(HeapType::Number())) {
5740 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
5741 compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
5742 dependency = smi_check;
5743 } else if (info.type()->Is(HeapType::String())) {
5744 compare = New<HIsStringAndBranch>(object, if_true, if_false);
5745 dependency = compare;
5746 } else {
5747 compare = New<HCompareMap>(object, info.map(), if_true, if_false);
5748 dependency = compare;
5749 }
5750 FinishCurrentBlock(compare);
5751
5752 if (info.type()->Is(HeapType::Number())) {
5753 Goto(if_true, number_block);
5754 if_true = number_block;
5755 number_block->SetJoinId(ast_id);
5756 }
5757
5758 set_current_block(if_true);
5759
5760 HInstruction* load = BuildLoadMonomorphic(
5761 &info, object, dependency, ast_id,
5762 return_id, FLAG_polymorphic_inlining);
5763 if (load == NULL) {
5764 if (HasStackOverflow()) return;
5765 } else {
5766 if (!load->IsLinked()) {
5767 AddInstruction(load);
5768 }
5769 if (!ast_context()->IsEffect()) Push(load);
5770 }
5771
5772 if (current_block() != NULL) Goto(join);
5773 set_current_block(if_false);
5774 }
5775
5690 // Finish up. Unconditionally deoptimize if we've handled all the maps we 5776 // Finish up. Unconditionally deoptimize if we've handled all the maps we
5691 // know about and do not want to handle ones we've never seen. Otherwise 5777 // know about and do not want to handle ones we've never seen. Otherwise
5692 // use a generic IC. 5778 // use a generic IC.
5693 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 5779 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
5694 // Because the deopt may be the only path in the polymorphic load, make sure 5780 // Because the deopt may be the only path in the polymorphic load, make sure
5695 // that the environment stack matches the depth on deopt that it otherwise 5781 // that the environment stack matches the depth on deopt that it otherwise
5696 // would have had after a successful load. 5782 // would have had after a successful load.
5697 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); 5783 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
5698 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); 5784 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
5699 } else { 5785 } else {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
5861 HValue* receiver, 5947 HValue* receiver,
5862 SmallMapList** t) { 5948 SmallMapList** t) {
5863 SmallMapList* types = expr->GetReceiverTypes(); 5949 SmallMapList* types = expr->GetReceiverTypes();
5864 *t = types; 5950 *t = types;
5865 bool monomorphic = expr->IsMonomorphic(); 5951 bool monomorphic = expr->IsMonomorphic();
5866 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { 5952 if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
5867 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); 5953 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
5868 types->FilterForPossibleTransitions(root_map); 5954 types->FilterForPossibleTransitions(root_map);
5869 monomorphic = types->length() == 1; 5955 monomorphic = types->length() == 1;
5870 } 5956 }
5871 return monomorphic && CanInlinePropertyAccess(*types->first()); 5957 return monomorphic && CanInlinePropertyAccess(IC::MapToType(types->first()));
5872 } 5958 }
5873 5959
5874 5960
5875 void HOptimizedGraphBuilder::BuildStore(Expression* expr, 5961 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
5876 Property* prop, 5962 Property* prop,
5877 BailoutId ast_id, 5963 BailoutId ast_id,
5878 BailoutId return_id, 5964 BailoutId return_id,
5879 bool is_uninitialized) { 5965 bool is_uninitialized) {
5880 HValue* value = environment()->ExpressionStackAt(0); 5966 HValue* value = environment()->ExpressionStackAt(0);
5881 5967
(...skipping 26 matching lines...) Expand all
5908 HInstruction* instr = NULL; 5994 HInstruction* instr = NULL;
5909 5995
5910 SmallMapList* types; 5996 SmallMapList* types;
5911 bool monomorphic = ComputeReceiverTypes(expr, object, &types); 5997 bool monomorphic = ComputeReceiverTypes(expr, object, &types);
5912 5998
5913 if (monomorphic) { 5999 if (monomorphic) {
5914 Handle<Map> map = types->first(); 6000 Handle<Map> map = types->first();
5915 Handle<JSFunction> setter; 6001 Handle<JSFunction> setter;
5916 Handle<JSObject> holder; 6002 Handle<JSObject> holder;
5917 if (LookupSetter(map, name, &setter, &holder)) { 6003 if (LookupSetter(map, name, &setter, &holder)) {
5918 AddCheckConstantFunction(holder, object, map); 6004 AddCheckMap(object, map);
5919 if (FLAG_inline_accessors && 6005 AddCheckPrototypeMaps(holder, map);
5920 TryInlineSetter(setter, ast_id, return_id, value)) { 6006 bool needs_wrapping = NeedsWrappingFor(IC::MapToType(map), setter);
6007 bool try_inline = FLAG_inline_accessors && !needs_wrapping;
6008 if (try_inline && TryInlineSetter(setter, ast_id, return_id, value)) {
5921 return; 6009 return;
5922 } 6010 }
5923 Drop(2); 6011 Drop(2);
5924 Add<HPushArgument>(object); 6012 if (needs_wrapping) {
5925 Add<HPushArgument>(value); 6013 instr = BuildStoreNamedGeneric(object, name, value);
5926 instr = BuildCallConstantFunction(setter, 2); 6014 } else {
6015 Add<HPushArgument>(object);
6016 Add<HPushArgument>(value);
6017 instr = BuildCallConstantFunction(setter, 2);
6018 }
5927 } else { 6019 } else {
5928 Drop(2); 6020 Drop(2);
5929 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, 6021 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
5930 name, 6022 name,
5931 value, 6023 value,
5932 map)); 6024 map));
5933 } 6025 }
5934 } else if (types != NULL && types->length() > 1) { 6026 } else if (types != NULL && types->length() > 1) {
5935 Drop(2); 6027 Drop(2);
5936 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); 6028 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name);
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after
6769 6861
6770 } else if (expr->key()->IsPropertyName()) { 6862 } else if (expr->key()->IsPropertyName()) {
6771 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 6863 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
6772 HValue* object = Pop(); 6864 HValue* object = Pop();
6773 6865
6774 SmallMapList* types; 6866 SmallMapList* types;
6775 ComputeReceiverTypes(expr, object, &types); 6867 ComputeReceiverTypes(expr, object, &types);
6776 ASSERT(types != NULL); 6868 ASSERT(types != NULL);
6777 6869
6778 if (types->length() > 0) { 6870 if (types->length() > 0) {
6779 PropertyAccessInfo info(isolate(), types->first(), name); 6871 PropertyAccessInfo info(this, IC::MapToType(types->first()), name);
6780 if (!info.CanLoadAsMonomorphic(types)) { 6872 if (!info.CanLoadAsMonomorphic(types)) {
6781 return HandlePolymorphicLoadNamedField( 6873 return HandlePolymorphicLoadNamedField(
6782 ast_id, expr->LoadId(), object, types, name); 6874 ast_id, expr->LoadId(), object, types, name);
6783 } 6875 }
6784 6876
6877 HValue* checked_object;
6878 // HeapType::Number() is only supported by polymorphic load/call handling.
6879 ASSERT(!info.type()->Is(HeapType::Number()));
6785 BuildCheckHeapObject(object); 6880 BuildCheckHeapObject(object);
6786 HInstruction* checked_object;
6787 if (AreStringTypes(types)) { 6881 if (AreStringTypes(types)) {
6788 checked_object = 6882 checked_object =
6789 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); 6883 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
6790 } else { 6884 } else {
6791 checked_object = Add<HCheckMaps>(object, types); 6885 checked_object = Add<HCheckMaps>(object, types);
6792 } 6886 }
6793 instr = BuildLoadMonomorphic( 6887 instr = BuildLoadMonomorphic(
6794 &info, object, checked_object, ast_id, expr->LoadId()); 6888 &info, object, checked_object, ast_id, expr->LoadId());
6795 if (instr == NULL) return; 6889 if (instr == NULL) return;
6796 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); 6890 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
7003 } 7097 }
7004 7098
7005 7099
7006 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic( 7100 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
7007 Call* expr, 7101 Call* expr,
7008 HValue* receiver, 7102 HValue* receiver,
7009 SmallMapList* types, 7103 SmallMapList* types,
7010 Handle<String> name) { 7104 Handle<String> name) {
7011 if (types->length() > kMaxCallPolymorphism) return false; 7105 if (types->length() > kMaxCallPolymorphism) return false;
7012 7106
7013 PropertyAccessInfo info(isolate(), types->at(0), name); 7107 PropertyAccessInfo info(this, IC::MapToType(types->at(0)), name);
7014 if (!info.CanLoadAsMonomorphic(types)) return false; 7108 if (!info.CanLoadAsMonomorphic(types)) return false;
7015 if (!expr->ComputeTarget(info.map(), name)) return false; 7109 if (!expr->ComputeTarget(info.map(), name)) return false;
7016 7110
7017 BuildCheckHeapObject(receiver); 7111 BuildCheckHeapObject(receiver);
7018 Add<HCheckMaps>(receiver, types); 7112 Add<HCheckMaps>(receiver, types);
7019 AddCheckPrototypeMaps(expr->holder(), info.map()); 7113 AddCheckPrototypeMaps(expr->holder(), info.map());
7020 if (FLAG_trace_inlining) { 7114 if (FLAG_trace_inlining) {
7021 Handle<JSFunction> caller = current_info()->closure(); 7115 Handle<JSFunction> caller = current_info()->closure();
7022 SmartArrayPointer<char> caller_name = 7116 SmartArrayPointer<char> caller_name =
7023 caller->shared()->DebugName()->ToCString(); 7117 caller->shared()->DebugName()->ToCString();
(...skipping 4237 matching lines...) Expand 10 before | Expand all | Expand 10 after
11261 if (ShouldProduceTraceOutput()) { 11355 if (ShouldProduceTraceOutput()) {
11262 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 11356 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11263 } 11357 }
11264 11358
11265 #ifdef DEBUG 11359 #ifdef DEBUG
11266 graph_->Verify(false); // No full verify. 11360 graph_->Verify(false); // No full verify.
11267 #endif 11361 #endif
11268 } 11362 }
11269 11363
11270 } } // namespace v8::internal 11364 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698