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

Side by Side Diff: src/hydrogen.cc

Issue 24088003: Unify Crankshaft Load handling into CanLoad and Load. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 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
« src/hydrogen.h ('K') | « src/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 // 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 4044 matching lines...) Expand 10 before | Expand all | Expand 10 after
4055 *accessors = Handle<AccessorPair>::cast(callback); 4055 *accessors = Handle<AccessorPair>::cast(callback);
4056 *holder = Handle<JSObject>(lookup.holder()); 4056 *holder = Handle<JSObject>(lookup.holder());
4057 return true; 4057 return true;
4058 } 4058 }
4059 4059
4060 // We haven't found a JavaScript accessor anywhere. 4060 // We haven't found a JavaScript accessor anywhere.
4061 return false; 4061 return false;
4062 } 4062 }
4063 4063
4064 4064
4065 static bool LookupGetter(Handle<Map> map,
4066 Handle<String> name,
4067 Handle<JSFunction>* getter,
4068 Handle<JSObject>* holder) {
4069 Handle<AccessorPair> accessors;
4070 if (LookupAccessorPair(map, name, &accessors, holder) &&
4071 accessors->getter()->IsJSFunction()) {
4072 *getter = Handle<JSFunction>(JSFunction::cast(accessors->getter()));
4073 return true;
4074 }
4075 return false;
4076 }
4077
4078
4079 static bool LookupSetter(Handle<Map> map, 4065 static bool LookupSetter(Handle<Map> map,
4080 Handle<String> name, 4066 Handle<String> name,
4081 Handle<JSFunction>* setter, 4067 Handle<JSFunction>* setter,
4082 Handle<JSObject>* holder) { 4068 Handle<JSObject>* holder) {
4083 Handle<AccessorPair> accessors; 4069 Handle<AccessorPair> accessors;
4084 if (LookupAccessorPair(map, name, &accessors, holder) && 4070 if (LookupAccessorPair(map, name, &accessors, holder) &&
4085 accessors->setter()->IsJSFunction()) { 4071 accessors->setter()->IsJSFunction()) {
4086 *setter = Handle<JSFunction>(JSFunction::cast(accessors->setter())); 4072 *setter = Handle<JSFunction>(JSFunction::cast(accessors->setter()));
4087 return true; 4073 return true;
4088 } 4074 }
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
4536 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4522 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4537 HCheckMaps* checked_object = AddCheckMap(object, map); 4523 HCheckMaps* checked_object = AddCheckMap(object, map);
4538 return BuildStoreNamedField(checked_object, name, value, map, &lookup); 4524 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
4539 } 4525 }
4540 4526
4541 // No luck, do a generic store. 4527 // No luck, do a generic store.
4542 return BuildStoreNamedGeneric(object, name, value); 4528 return BuildStoreNamedGeneric(object, name, value);
4543 } 4529 }
4544 4530
4545 4531
4546 static bool CanLoadPropertyFromPrototype(Handle<Map> map, 4532 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad(
4547 Handle<Name> name, 4533 PropertyAccessInfo* info) {
4548 LookupResult* lookup) { 4534 if (!CanInlinePropertyAccess(*map_)) return false;
4549 if (!CanInlinePropertyAccess(*map)) return false; 4535
4550 map->LookupDescriptor(NULL, *name, lookup); 4536 if (!LookupDescriptor()) return false;
4551 if (lookup->IsFound()) return false; 4537
4538 if (!lookup_.IsFound()) {
4539 return (!info->lookup_.IsFound() || !info->holder_.is_null()) &&
4540 map_->prototype() == info->map_->prototype();
4541 }
4542
4543 if (lookup_.IsPropertyCallbacks()) {
4544 return accessor_.is_identical_to(info->accessor_);
4545 }
4546
4547 if (lookup_.IsConstant()) {
4548 return constant_.is_identical_to(info->constant_);
4549 }
4550
4551 ASSERT(lookup_.IsField());
4552 if (!info->lookup_.IsField()) return false;
4553
4554 Representation r = access_.representation();
4555 if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
4556 if (info->access_.offset() != access_.offset()) return false;
4557 if (info->access_.IsInobject() != access_.IsInobject()) return false;
4558 info->GeneralizeRepresentation(r);
4552 return true; 4559 return true;
4553 } 4560 }
4554 4561
4555 4562
4556 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( 4563 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
4557 HValue* object, 4564 map_->LookupDescriptor(NULL, *name_, &lookup_);
4558 SmallMapList* types, 4565 return LoadResult(map_);
4559 Handle<String> name) {
4560 // Use monomorphic load if property lookup results in the same field index
4561 // for all maps. Requires special map check on the set of all handled maps.
4562 if (types->length() > kMaxLoadPolymorphism) return NULL;
4563
4564 LookupResult lookup(isolate());
4565 int count;
4566 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
4567 for (count = 0; count < types->length(); ++count) {
4568 Handle<Map> map = types->at(count);
4569 if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
4570
4571 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
4572
4573 if (count == 0) {
4574 // First time through the loop; set access and representation.
4575 access = new_access;
4576 } else if (!access.representation().IsCompatibleForLoad(
4577 new_access.representation())) {
4578 // Representations did not match.
4579 break;
4580 } else if (access.offset() != new_access.offset()) {
4581 // Offsets did not match.
4582 break;
4583 } else if (access.IsInobject() != new_access.IsInobject()) {
4584 // In-objectness did not match.
4585 break;
4586 }
4587 access = access.WithRepresentation(
4588 access.representation().generalize(new_access.representation()));
4589 }
4590
4591 if (count == types->length()) {
4592 // Everything matched; can use monomorphic load.
4593 BuildCheckHeapObject(object);
4594 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
4595 return BuildLoadNamedField(checked_object, access);
4596 }
4597
4598 if (count != 0) return NULL;
4599
4600 // Second chance: the property is on the prototype and all maps have the
4601 // same prototype.
4602 Handle<Map> map(types->at(0));
4603 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL;
4604
4605 Handle<Object> prototype(map->prototype(), isolate());
4606 for (count = 1; count < types->length(); ++count) {
4607 Handle<Map> test_map(types->at(count));
4608 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL;
4609 if (test_map->prototype() != *prototype) return NULL;
4610 }
4611
4612 LookupInPrototypes(map, name, &lookup);
4613 if (!lookup.IsField()) return NULL;
4614
4615 BuildCheckHeapObject(object);
4616 Add<HCheckMaps>(object, types);
4617
4618 Handle<JSObject> holder(lookup.holder());
4619 Handle<Map> holder_map(holder->map());
4620 HValue* checked_holder = BuildCheckPrototypeMaps(
4621 Handle<JSObject>::cast(prototype), holder);
4622 return BuildLoadNamedField(checked_holder,
4623 HObjectAccess::ForField(holder_map, &lookup, name));
4624 } 4566 }
4625 4567
4626 4568
4627 // Returns true if an instance of this map can never find a property with this 4569 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
4628 // name in its prototype chain. This means all prototypes up to the top are 4570 if (lookup_.IsField()) {
4629 // fast and don't have the name in them. It would be good if we could optimize 4571 access_ = HObjectAccess::ForField(map, &lookup_, name_);
4630 // polymorphic loads where the property is sometimes found in the prototype 4572 } else if (lookup_.IsPropertyCallbacks()) {
4631 // chain. 4573 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
4632 static bool PrototypeChainCanNeverResolve( 4574 if (!callback->IsAccessorPair()) return false;
4633 Handle<Map> map, Handle<String> name) { 4575 Object* getter = Handle<AccessorPair>::cast(callback)->getter();
4634 Isolate* isolate = map->GetIsolate(); 4576 if (!getter->IsJSFunction()) return false;
4635 Object* current = map->prototype(); 4577 accessor_ = handle(JSFunction::cast(getter));
4636 while (current != isolate->heap()->null_value()) { 4578 } else if (lookup_.IsConstant()) {
4637 if (current->IsJSGlobalProxy() || 4579 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
4638 current->IsGlobalObject() || 4580 }
4639 !current->IsJSObject() || 4581
4640 !CanInlinePropertyAccess(JSObject::cast(current)->map()) || 4582 return true;
4641 JSObject::cast(current)->IsAccessCheckNeeded()) { 4583 }
4584
4585
4586 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
4587 Handle<Map> map = map_;
4588 while (map->prototype()->IsJSObject()) {
4589 holder_ = handle(JSObject::cast(map->prototype()));
4590 map = Handle<Map>(holder_->map());
4591 if (!CanInlinePropertyAccess(*map)) {
4592 lookup_.NotFound();
4642 return false; 4593 return false;
4643 } 4594 }
4595 map->LookupDescriptor(*holder_, *name_, &lookup_);
4596 if (lookup_.IsFound()) return LoadResult(map);
4597 }
4598 lookup_.NotFound();
4599 return true;
4600 }
4644 4601
4645 LookupResult lookup(isolate); 4602
4646 Map* map = JSObject::cast(current)->map(); 4603 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() {
4647 map->LookupDescriptor(NULL, *name, &lookup); 4604 if (!CanInlinePropertyAccess(*map_)) return IsStringLength();
4648 if (lookup.IsFound()) return false; 4605 if (IsArrayLength()) return true;
4649 if (!lookup.IsCacheable()) return false; 4606 if (!LookupDescriptor()) return false;
4650 current = JSObject::cast(current)->GetPrototype(); 4607 if (lookup_.IsFound()) return true;
4608 return LookupInPrototypes();
4609 }
4610
4611
4612 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic(
4613 SmallMapList* types) {
4614 ASSERT(map_.is_identical_to(types->first()));
4615 if (!CanLoadMonomorphic()) return false;
4616 if (types->length() > kMaxLoadPolymorphism) return false;
4617
4618 if (IsStringLength()) {
4619 for (int i = 1; i < types->length(); ++i) {
4620 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
4621 }
4622 return true;
4651 } 4623 }
4624
4625 if (IsArrayLength()) {
4626 bool is_fast = IsFastElementsKind(map_->elements_kind());
4627 for (int i = 1; i < types->length(); ++i) {
4628 Handle<Map> test_map = types->at(i);
4629 if (test_map->instance_type() != JS_ARRAY_TYPE) return false;
4630 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) {
4631 return false;
4632 }
4633 }
4634 return true;
4635 }
4636
4637 for (int i = 1; i < types->length(); ++i) {
4638 PropertyAccessInfo test_info(isolate(), types->at(i), name_);
4639 if (!test_info.IsCompatibleForLoad(this)) return false;
4640 }
4641
4652 return true; 4642 return true;
4653 } 4643 }
4654 4644
4655 4645
4646 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic(
4647 PropertyAccessInfo* info,
4648 HValue* object,
4649 HInstruction* checked_object,
4650 BailoutId ast_id,
4651 BailoutId return_id,
4652 bool can_inline_accessor) {
4653 if (info->IsStringLength()) {
4654 return New<HLoadNamedField>(
4655 checked_object, HObjectAccess::ForStringLength());
4656 }
4657
4658 if (info->IsArrayLength()) {
4659 return New<HLoadNamedField>(
4660 checked_object, HObjectAccess::ForArrayLength(
4661 info->map()->elements_kind()));
4662 }
4663
4664 HValue* checked_holder = checked_object;
4665 if (info->has_holder()) {
4666 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
4667 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
4668 }
4669
4670 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined();
4671
4672 if (info->lookup()->IsField()) {
4673 return BuildLoadNamedField(checked_holder, info->access());
4674 }
4675
4676 if (info->lookup()->IsPropertyCallbacks()) {
4677 Push(checked_object);
4678 if (FLAG_inline_accessors &&
4679 can_inline_accessor &&
4680 TryInlineGetter(info->accessor(), ast_id, return_id)) {
4681 return NULL;
4682 }
4683 Add<HPushArgument>(Pop());
4684 return new(zone()) HCallConstantFunction(info->accessor(), 1);
4685 }
4686
4687 ASSERT(info->lookup()->IsConstant());
4688 return New<HConstant>(info->constant());
4689 }
4690
4691
4656 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4692 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4657 int position, 4693 int position,
4658 BailoutId ast_id, 4694 BailoutId ast_id,
4695 BailoutId return_id,
4659 HValue* object, 4696 HValue* object,
4660 SmallMapList* types, 4697 SmallMapList* types,
4661 Handle<String> name) { 4698 Handle<String> name) {
4662 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(object, types, name);
4663 if (instr != NULL) {
4664 instr->set_position(position);
4665 return ast_context()->ReturnInstruction(instr, ast_id);
4666 }
4667
4668 // Something did not match; must use a polymorphic load. 4699 // Something did not match; must use a polymorphic load.
4669 int count = 0; 4700 int count = 0;
4670 HBasicBlock* join = NULL; 4701 HBasicBlock* join = NULL;
4671 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 4702 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
4672 Handle<Map> map = types->at(i); 4703 PropertyAccessInfo info(isolate(), types->at(i), name);
4673 LookupResult lookup(isolate()); 4704 if (info.CanLoadMonomorphic()) {
4674 if (ComputeLoadStoreField(map, name, &lookup, false) ||
4675 (lookup.IsCacheable() &&
4676 CanInlinePropertyAccess(*map) &&
4677 (lookup.IsConstant() ||
4678 (!lookup.IsFound() &&
4679 PrototypeChainCanNeverResolve(map, name))))) {
4680 if (count == 0) { 4705 if (count == 0) {
4681 BuildCheckHeapObject(object); 4706 BuildCheckHeapObject(object);
4682 join = graph()->CreateBasicBlock(); 4707 join = graph()->CreateBasicBlock();
4683 } 4708 }
4684 ++count; 4709 ++count;
4685 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4710 HBasicBlock* if_true = graph()->CreateBasicBlock();
4686 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4711 HBasicBlock* if_false = graph()->CreateBasicBlock();
4687 HCompareMap* compare = 4712 HCompareMap* compare = new(zone()) HCompareMap(
4688 new(zone()) HCompareMap(object, map, if_true, if_false); 4713 object, info.map(), if_true, if_false);
4689 current_block()->Finish(compare); 4714 current_block()->Finish(compare);
4690 4715
4691 set_current_block(if_true); 4716 set_current_block(if_true);
4692 4717
4693 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. 4718 HInstruction* load = BuildLoadMonomorphic(
4694 if (lookup.IsField()) { 4719 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining);
4695 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); 4720 if (load == NULL) {
4696 HLoadNamedField* load = BuildLoadNamedField(compare, access); 4721 if (HasStackOverflow()) return;
4697 load->set_position(position); 4722 } else {
4698 AddInstruction(load); 4723 if (!load->IsLinked()) {
4724 load->set_position(position);
4725 AddInstruction(load);
4726 }
4699 if (!ast_context()->IsEffect()) Push(load); 4727 if (!ast_context()->IsEffect()) Push(load);
4700 } else if (lookup.IsConstant()) {
4701 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
4702 HConstant* hconstant = Add<HConstant>(constant);
4703 if (!ast_context()->IsEffect()) Push(hconstant);
4704 } else {
4705 ASSERT(!lookup.IsFound());
4706 if (map->prototype()->IsJSObject()) {
4707 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
4708 Handle<JSObject> holder = prototype;
4709 while (holder->map()->prototype()->IsJSObject()) {
4710 holder = handle(JSObject::cast(holder->map()->prototype()));
4711 }
4712 BuildCheckPrototypeMaps(prototype, holder);
4713 }
4714 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
4715 } 4728 }
4716 4729
4717 current_block()->Goto(join); 4730 if (current_block() != NULL) current_block()->Goto(join);
4718 set_current_block(if_false); 4731 set_current_block(if_false);
4719 } 4732 }
4720 } 4733 }
4721 4734
4722 // Finish up. Unconditionally deoptimize if we've handled all the maps we 4735 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4723 // know about and do not want to handle ones we've never seen. Otherwise 4736 // know about and do not want to handle ones we've never seen. Otherwise
4724 // use a generic IC. 4737 // use a generic IC.
4725 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 4738 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4726 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); 4739 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
4727 } else { 4740 } else {
(...skipping 23 matching lines...) Expand all
4751 int position, 4764 int position,
4752 BailoutId assignment_id, 4765 BailoutId assignment_id,
4753 HValue* object, 4766 HValue* object,
4754 HValue* value, 4767 HValue* value,
4755 SmallMapList* types, 4768 SmallMapList* types,
4756 Handle<String> name) { 4769 Handle<String> name) {
4757 // Use monomorphic store if property lookup results in the same field index 4770 // Use monomorphic store if property lookup results in the same field index
4758 // for all maps. Requires special map check on the set of all handled maps. 4771 // for all maps. Requires special map check on the set of all handled maps.
4759 if (types->length() > kMaxStorePolymorphism) return false; 4772 if (types->length() > kMaxStorePolymorphism) return false;
4760 4773
4761 // TODO(verwaest): Merge the checking logic with the code in
4762 // TryLoadPolymorphicAsMonomorphic.
4763 LookupResult lookup(isolate()); 4774 LookupResult lookup(isolate());
4764 int count; 4775 int count;
4765 Representation representation = Representation::None(); 4776 Representation representation = Representation::None();
4766 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. 4777 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
4767 for (count = 0; count < types->length(); ++count) { 4778 for (count = 0; count < types->length(); ++count) {
4768 Handle<Map> map = types->at(count); 4779 Handle<Map> map = types->at(count);
4769 // Pass false to ignore transitions. 4780 // Pass false to ignore transitions.
4770 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; 4781 if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
4771 ASSERT(!map->is_observed()); 4782 ASSERT(!map->is_observed());
4772 4783
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after
5351 HValue* object, 5362 HValue* object,
5352 Handle<Map> map, 5363 Handle<Map> map,
5353 Handle<JSFunction> getter, 5364 Handle<JSFunction> getter,
5354 Handle<JSObject> holder) { 5365 Handle<JSObject> holder) {
5355 AddCheckConstantFunction(holder, object, map); 5366 AddCheckConstantFunction(holder, object, map);
5356 Add<HPushArgument>(object); 5367 Add<HPushArgument>(object);
5357 return new(zone()) HCallConstantFunction(getter, 1); 5368 return new(zone()) HCallConstantFunction(getter, 1);
5358 } 5369 }
5359 5370
5360 5371
5361 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
5362 HValue* object,
5363 Handle<String> name,
5364 Handle<Map> map) {
5365 // Handle a load from a known field.
5366 ASSERT(!map->is_dictionary_map());
5367
5368 // Handle access to various length properties
5369 if (name->Equals(isolate()->heap()->length_string())) {
5370 if (map->instance_type() == JS_ARRAY_TYPE) {
5371 HCheckMaps* checked_object = AddCheckMap(object, map);
5372 return New<HLoadNamedField>(
5373 checked_object, HObjectAccess::ForArrayLength(map->elements_kind()));
5374 }
5375 }
5376
5377 LookupResult lookup(isolate());
5378 map->LookupDescriptor(NULL, *name, &lookup);
5379 if (lookup.IsField()) {
5380 HCheckMaps* checked_object = AddCheckMap(object, map);
5381 ASSERT(map->IsJSObjectMap());
5382 return BuildLoadNamedField(
5383 checked_object, HObjectAccess::ForField(map, &lookup, name));
5384 }
5385
5386 // Handle a load of a constant known function.
5387 if (lookup.IsConstant()) {
5388 AddCheckMap(object, map);
5389 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
5390 return New<HConstant>(constant);
5391 }
5392
5393 if (lookup.IsFound()) {
5394 // Cannot handle the property, do a generic load instead.
5395 HValue* context = environment()->context();
5396 return new(zone()) HLoadNamedGeneric(context, object, name);
5397 }
5398
5399 // Handle a load from a known field somewhere in the prototype chain.
5400 LookupInPrototypes(map, name, &lookup);
5401 if (lookup.IsField()) {
5402 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5403 Handle<JSObject> holder(lookup.holder());
5404 Handle<Map> holder_map(holder->map());
5405 AddCheckMap(object, map);
5406 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder);
5407 return BuildLoadNamedField(
5408 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name));
5409 }
5410
5411 // Handle a load of a constant function somewhere in the prototype chain.
5412 if (lookup.IsConstant()) {
5413 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5414 Handle<JSObject> holder(lookup.holder());
5415 Handle<Map> holder_map(holder->map());
5416 AddCheckMap(object, map);
5417 BuildCheckPrototypeMaps(prototype, holder);
5418 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
5419 return New<HConstant>(constant);
5420 }
5421
5422 // No luck, do a generic load.
5423 HValue* context = environment()->context();
5424 return new(zone()) HLoadNamedGeneric(context, object, name);
5425 }
5426
5427
5428 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5372 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
5429 HValue* key) { 5373 HValue* key) {
5430 HValue* context = environment()->context(); 5374 HValue* context = environment()->context();
5431 return new(zone()) HLoadKeyedGeneric(context, object, key); 5375 return new(zone()) HLoadKeyedGeneric(context, object, key);
5432 } 5376 }
5433 5377
5434 5378
5435 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { 5379 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
5436 // Loads from a "stock" fast holey double arrays can elide the hole check. 5380 // Loads from a "stock" fast holey double arrays can elide the hole check.
5437 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5381 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
5817 HValue* key, 5761 HValue* key,
5818 int position) { 5762 int position) {
5819 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 5763 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
5820 Push(object); 5764 Push(object);
5821 if (key != NULL) Push(key); 5765 if (key != NULL) Push(key);
5822 BuildLoad(expr, position, expr->LoadId()); 5766 BuildLoad(expr, position, expr->LoadId());
5823 } 5767 }
5824 5768
5825 5769
5826 static bool AreStringTypes(SmallMapList* types) { 5770 static bool AreStringTypes(SmallMapList* types) {
5827 if (types == NULL || types->length() == 0) return false;
5828 for (int i = 0; i < types->length(); i++) { 5771 for (int i = 0; i < types->length(); i++) {
5829 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; 5772 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
5830 } 5773 }
5831 return true; 5774 return true;
5832 } 5775 }
5833 5776
5834 5777
5835 void HOptimizedGraphBuilder::BuildLoad(Property* expr, 5778 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
5836 int position, 5779 int position,
5837 BailoutId ast_id) { 5780 BailoutId ast_id) {
5838 HInstruction* instr = NULL; 5781 HInstruction* instr = NULL;
5839 if (expr->IsStringAccess()) { 5782 if (expr->IsStringAccess()) {
5840 HValue* index = Pop(); 5783 HValue* index = Pop();
5841 HValue* string = Pop(); 5784 HValue* string = Pop();
5842 HValue* context = environment()->context(); 5785 HValue* context = environment()->context();
5843 HInstruction* char_code = 5786 HInstruction* char_code =
5844 BuildStringCharCodeAt(string, index); 5787 BuildStringCharCodeAt(string, index);
5845 AddInstruction(char_code); 5788 AddInstruction(char_code);
5846 instr = HStringCharFromCode::New(zone(), context, char_code); 5789 instr = HStringCharFromCode::New(zone(), context, char_code);
5847 5790
5848 } else if (expr->IsFunctionPrototype()) { 5791 } else if (expr->IsFunctionPrototype()) {
5849 HValue* function = Pop(); 5792 HValue* function = Pop();
5850 BuildCheckHeapObject(function); 5793 BuildCheckHeapObject(function);
5851 instr = new(zone()) HLoadFunctionPrototype(function); 5794 instr = new(zone()) HLoadFunctionPrototype(function);
5852 5795
5853 } else if (expr->key()->IsPropertyName()) { 5796 } else if (expr->key()->IsPropertyName()) {
5854 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 5797 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5855 HValue* object = Top(); 5798 HValue* object = Pop();
5856 5799
5857 SmallMapList* types; 5800 SmallMapList* types;
5858 bool monomorphic = ComputeReceiverTypes(expr, object, &types); 5801 ComputeReceiverTypes(expr, object, &types);
5802 ASSERT(types != NULL);
5859 5803
5860 if (monomorphic) { 5804 if (types->length() > 0) {
5861 Handle<Map> map = types->first(); 5805 PropertyAccessInfo info(isolate(), types->first(), name);
5862 Handle<JSFunction> getter; 5806 if (!info.CanLoadAsMonomorphic(types)) {
5863 Handle<JSObject> holder; 5807 return HandlePolymorphicLoadNamedField(
5864 if (LookupGetter(map, name, &getter, &holder)) { 5808 position, ast_id, expr->LoadId(), object, types, name);
5865 AddCheckConstantFunction(holder, Top(), map); 5809 }
5866 if (FLAG_inline_accessors && 5810
5867 TryInlineGetter(getter, ast_id, expr->LoadId())) { 5811 BuildCheckHeapObject(object);
5868 return; 5812 HInstruction* checked_object;
5869 } 5813 if (AreStringTypes(types)) {
5870 Add<HPushArgument>(Pop()); 5814 checked_object =
5871 instr = new(zone()) HCallConstantFunction(getter, 1); 5815 AddInstruction(HCheckInstanceType::NewIsString(object, zone()));
5872 } else { 5816 } else {
5873 instr = BuildLoadNamedMonomorphic(Pop(), name, map); 5817 checked_object = Add<HCheckMaps>(object, types);
5874 } 5818 }
5875 } else if (AreStringTypes(types) && 5819 instr = BuildLoadMonomorphic(
5876 name->Equals(isolate()->heap()->length_string())) { 5820 &info, object, checked_object, ast_id, expr->LoadId());
5877 BuildCheckHeapObject(Pop()); 5821 if (instr == NULL) return;
5878 HValue* checked_object = 5822 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
5879 AddInstruction(HCheckInstanceType::NewIsString(object, zone()));
5880 instr = BuildLoadStringLength(object, checked_object);
5881 } else if (types != NULL && types->length() > 1) {
5882 return HandlePolymorphicLoadNamedField(
5883 position, ast_id, Pop(), types, name);
5884 } else { 5823 } else {
5885 instr = BuildLoadNamedGeneric(Pop(), name, expr); 5824 instr = BuildLoadNamedGeneric(object, name, expr);
5886 } 5825 }
5887 5826
5888 } else { 5827 } else {
5889 HValue* key = Pop(); 5828 HValue* key = Pop();
5890 HValue* obj = Pop(); 5829 HValue* obj = Pop();
5891 5830
5892 bool has_side_effects = false; 5831 bool has_side_effects = false;
5893 HValue* load = HandleKeyedElementAccess( 5832 HValue* load = HandleKeyedElementAccess(
5894 obj, key, NULL, expr, ast_id, position, 5833 obj, key, NULL, expr, ast_id, position,
5895 false, // is_store 5834 false, // is_store
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
6010 } 5949 }
6011 5950
6012 5951
6013 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic( 5952 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
6014 Call* expr, 5953 Call* expr,
6015 HValue* receiver, 5954 HValue* receiver,
6016 SmallMapList* types, 5955 SmallMapList* types,
6017 Handle<String> name) { 5956 Handle<String> name) {
6018 if (types->length() > kMaxCallPolymorphism) return false; 5957 if (types->length() > kMaxCallPolymorphism) return false;
6019 5958
6020 Handle<Map> map(types->at(0)); 5959 PropertyAccessInfo info(isolate(), types->at(0), name);
6021 LookupResult lookup(isolate()); 5960 if (!info.CanLoadAsMonomorphic(types)) return false;
6022 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return false; 5961 if (!expr->ComputeTarget(info.map(), name)) return false;
6023
6024 Handle<Object> prototype(map->prototype(), isolate());
6025 for (int count = 1; count < types->length(); ++count) {
6026 Handle<Map> test_map(types->at(count));
6027 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false;
6028 if (test_map->prototype() != *prototype) return false;
6029 }
6030
6031 if (!expr->ComputeTarget(map, name)) return false;
6032 5962
6033 BuildCheckHeapObject(receiver); 5963 BuildCheckHeapObject(receiver);
6034 Add<HCheckMaps>(receiver, types); 5964 Add<HCheckMaps>(receiver, types);
6035 AddCheckPrototypeMaps(expr->holder(), map); 5965 AddCheckPrototypeMaps(expr->holder(), info.map());
6036 if (FLAG_trace_inlining) { 5966 if (FLAG_trace_inlining) {
6037 Handle<JSFunction> caller = current_info()->closure(); 5967 Handle<JSFunction> caller = current_info()->closure();
6038 SmartArrayPointer<char> caller_name = 5968 SmartArrayPointer<char> caller_name =
6039 caller->shared()->DebugName()->ToCString(); 5969 caller->shared()->DebugName()->ToCString();
6040 PrintF("Trying to inline the polymorphic call to %s from %s\n", 5970 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6041 *name->ToCString(), *caller_name); 5971 *name->ToCString(), *caller_name);
6042 } 5972 }
6043 5973
6044 if (!TryInlineCall(expr)) { 5974 if (!TryInlineCall(expr)) {
6045 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 5975 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
(...skipping 3651 matching lines...) Expand 10 before | Expand all | Expand 10 after
9697 if (ShouldProduceTraceOutput()) { 9627 if (ShouldProduceTraceOutput()) {
9698 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9628 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9699 } 9629 }
9700 9630
9701 #ifdef DEBUG 9631 #ifdef DEBUG
9702 graph_->Verify(false); // No full verify. 9632 graph_->Verify(false); // No full verify.
9703 #endif 9633 #endif
9704 } 9634 }
9705 9635
9706 } } // namespace v8::internal 9636 } } // namespace v8::internal
OLDNEW
« src/hydrogen.h ('K') | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698