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

Side by Side Diff: src/hydrogen.cc

Issue 151603004: A64: Synchronize with r16587. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
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-escape-analysis.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 3987 matching lines...) Expand 10 before | Expand all | Expand 10 after
3998 3998
3999 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, 3999 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
4000 literals, 4000 literals,
4001 expr->pattern(), 4001 expr->pattern(),
4002 expr->flags(), 4002 expr->flags(),
4003 expr->literal_index()); 4003 expr->literal_index());
4004 return ast_context()->ReturnInstruction(instr, expr->id()); 4004 return ast_context()->ReturnInstruction(instr, expr->id());
4005 } 4005 }
4006 4006
4007 4007
4008 static bool CanInlinePropertyAccess(Map* type) {
4009 return !type->is_dictionary_map() && !type->has_named_interceptor();
4010 }
4011
4012
4008 static void LookupInPrototypes(Handle<Map> map, 4013 static void LookupInPrototypes(Handle<Map> map,
4009 Handle<String> name, 4014 Handle<String> name,
4010 LookupResult* lookup) { 4015 LookupResult* lookup) {
4011 while (map->prototype()->IsJSObject()) { 4016 while (map->prototype()->IsJSObject()) {
4012 Handle<JSObject> holder(JSObject::cast(map->prototype())); 4017 Handle<JSObject> holder(JSObject::cast(map->prototype()));
4013 if (!holder->HasFastProperties()) break;
4014 map = Handle<Map>(holder->map()); 4018 map = Handle<Map>(holder->map());
4019 if (!CanInlinePropertyAccess(*map)) break;
4015 map->LookupDescriptor(*holder, *name, lookup); 4020 map->LookupDescriptor(*holder, *name, lookup);
4016 if (lookup->IsFound()) return; 4021 if (lookup->IsFound()) return;
4017 } 4022 }
4018 lookup->NotFound(); 4023 lookup->NotFound();
4019 } 4024 }
4020 4025
4021 4026
4022 // Tries to find a JavaScript accessor of the given name in the prototype chain 4027 // Tries to find a JavaScript accessor of the given name in the prototype chain
4023 // starting at the given map. Return true iff there is one, including the 4028 // starting at the given map. Return true iff there is one, including the
4024 // corresponding AccessorPair plus its holder (which could be null when the 4029 // corresponding AccessorPair plus its holder (which could be null when the
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
4392 return ast_context()->ReturnValue(Pop()); 4397 return ast_context()->ReturnValue(Pop());
4393 } 4398 }
4394 4399
4395 4400
4396 // Sets the lookup result and returns true if the load/store can be inlined. 4401 // Sets the lookup result and returns true if the load/store can be inlined.
4397 static bool ComputeLoadStoreField(Handle<Map> type, 4402 static bool ComputeLoadStoreField(Handle<Map> type,
4398 Handle<String> name, 4403 Handle<String> name,
4399 LookupResult* lookup, 4404 LookupResult* lookup,
4400 bool is_store) { 4405 bool is_store) {
4401 ASSERT(!is_store || !type->is_observed()); 4406 ASSERT(!is_store || !type->is_observed());
4402 if (type->has_named_interceptor()) { 4407 if (!CanInlinePropertyAccess(*type)) {
4403 lookup->InterceptorResult(NULL); 4408 lookup->NotFound();
4404 return false; 4409 return false;
4405 } 4410 }
4406 // If we directly find a field, the access can be inlined. 4411 // If we directly find a field, the access can be inlined.
4407 type->LookupDescriptor(NULL, *name, lookup); 4412 type->LookupDescriptor(NULL, *name, lookup);
4408 if (lookup->IsField()) return true; 4413 if (lookup->IsField()) return true;
4409 4414
4410 // For a load, we are out of luck if there is no such field. 4415 // For a load, we are out of luck if there is no such field.
4411 if (!is_store) return false; 4416 if (!is_store) return false;
4412 4417
4413 // 2nd chance: A store into a non-existent field can still be inlined if we 4418 // 2nd chance: A store into a non-existent field can still be inlined if we
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
4536 } 4541 }
4537 4542
4538 // No luck, do a generic store. 4543 // No luck, do a generic store.
4539 return BuildStoreNamedGeneric(object, name, value); 4544 return BuildStoreNamedGeneric(object, name, value);
4540 } 4545 }
4541 4546
4542 4547
4543 static bool CanLoadPropertyFromPrototype(Handle<Map> map, 4548 static bool CanLoadPropertyFromPrototype(Handle<Map> map,
4544 Handle<Name> name, 4549 Handle<Name> name,
4545 LookupResult* lookup) { 4550 LookupResult* lookup) {
4546 if (map->has_named_interceptor()) return false; 4551 if (!CanInlinePropertyAccess(*map)) return false;
4547 if (map->is_dictionary_map()) return false;
4548 map->LookupDescriptor(NULL, *name, lookup); 4552 map->LookupDescriptor(NULL, *name, lookup);
4549 if (lookup->IsFound()) return false; 4553 if (lookup->IsFound()) return false;
4550 return true; 4554 return true;
4551 } 4555 }
4552 4556
4553 4557
4554 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( 4558 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
4555 Property* expr,
4556 HValue* object, 4559 HValue* object,
4557 SmallMapList* types, 4560 SmallMapList* types,
4558 Handle<String> name) { 4561 Handle<String> name) {
4559 // Use monomorphic load if property lookup results in the same field index 4562 // Use monomorphic load if property lookup results in the same field index
4560 // for all maps. Requires special map check on the set of all handled maps. 4563 // for all maps. Requires special map check on the set of all handled maps.
4561 if (types->length() > kMaxLoadPolymorphism) return NULL; 4564 if (types->length() > kMaxLoadPolymorphism) return NULL;
4562 4565
4563 LookupResult lookup(isolate()); 4566 LookupResult lookup(isolate());
4564 int count; 4567 int count;
4565 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. 4568 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
4629 // polymorphic loads where the property is sometimes found in the prototype 4632 // polymorphic loads where the property is sometimes found in the prototype
4630 // chain. 4633 // chain.
4631 static bool PrototypeChainCanNeverResolve( 4634 static bool PrototypeChainCanNeverResolve(
4632 Handle<Map> map, Handle<String> name) { 4635 Handle<Map> map, Handle<String> name) {
4633 Isolate* isolate = map->GetIsolate(); 4636 Isolate* isolate = map->GetIsolate();
4634 Object* current = map->prototype(); 4637 Object* current = map->prototype();
4635 while (current != isolate->heap()->null_value()) { 4638 while (current != isolate->heap()->null_value()) {
4636 if (current->IsJSGlobalProxy() || 4639 if (current->IsJSGlobalProxy() ||
4637 current->IsGlobalObject() || 4640 current->IsGlobalObject() ||
4638 !current->IsJSObject() || 4641 !current->IsJSObject() ||
4639 JSObject::cast(current)->map()->has_named_interceptor() || 4642 !CanInlinePropertyAccess(JSObject::cast(current)->map()) ||
4640 JSObject::cast(current)->IsAccessCheckNeeded() || 4643 JSObject::cast(current)->IsAccessCheckNeeded()) {
4641 !JSObject::cast(current)->HasFastProperties()) {
4642 return false; 4644 return false;
4643 } 4645 }
4644 4646
4645 LookupResult lookup(isolate); 4647 LookupResult lookup(isolate);
4646 Map* map = JSObject::cast(current)->map(); 4648 Map* map = JSObject::cast(current)->map();
4647 map->LookupDescriptor(NULL, *name, &lookup); 4649 map->LookupDescriptor(NULL, *name, &lookup);
4648 if (lookup.IsFound()) return false; 4650 if (lookup.IsFound()) return false;
4649 if (!lookup.IsCacheable()) return false; 4651 if (!lookup.IsCacheable()) return false;
4650 current = JSObject::cast(current)->GetPrototype(); 4652 current = JSObject::cast(current)->GetPrototype();
4651 } 4653 }
4652 return true; 4654 return true;
4653 } 4655 }
4654 4656
4655 4657
4656 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4658 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4657 Property* expr, 4659 int position,
4660 BailoutId ast_id,
4658 HValue* object, 4661 HValue* object,
4659 SmallMapList* types, 4662 SmallMapList* types,
4660 Handle<String> name) { 4663 Handle<String> name) {
4661 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( 4664 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(object, types, name);
4662 expr, object, types, name);
4663 if (instr != NULL) { 4665 if (instr != NULL) {
4664 instr->set_position(expr->position()); 4666 instr->set_position(position);
4665 return ast_context()->ReturnInstruction(instr, expr->id()); 4667 return ast_context()->ReturnInstruction(instr, ast_id);
4666 } 4668 }
4667 4669
4668 // Something did not match; must use a polymorphic load. 4670 // Something did not match; must use a polymorphic load.
4669 int count = 0; 4671 int count = 0;
4670 HBasicBlock* join = NULL; 4672 HBasicBlock* join = NULL;
4671 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 4673 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
4672 Handle<Map> map = types->at(i); 4674 Handle<Map> map = types->at(i);
4673 LookupResult lookup(isolate()); 4675 LookupResult lookup(isolate());
4674 if (ComputeLoadStoreField(map, name, &lookup, false) || 4676 if (ComputeLoadStoreField(map, name, &lookup, false) ||
4675 (lookup.IsCacheable() && 4677 (lookup.IsCacheable() &&
4676 !map->is_dictionary_map() && 4678 CanInlinePropertyAccess(*map) &&
4677 !map->has_named_interceptor() &&
4678 (lookup.IsConstant() || 4679 (lookup.IsConstant() ||
4679 (!lookup.IsFound() && 4680 (!lookup.IsFound() &&
4680 PrototypeChainCanNeverResolve(map, name))))) { 4681 PrototypeChainCanNeverResolve(map, name))))) {
4681 if (count == 0) { 4682 if (count == 0) {
4682 BuildCheckHeapObject(object); 4683 BuildCheckHeapObject(object);
4683 join = graph()->CreateBasicBlock(); 4684 join = graph()->CreateBasicBlock();
4684 } 4685 }
4685 ++count; 4686 ++count;
4686 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4687 HBasicBlock* if_true = graph()->CreateBasicBlock();
4687 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4688 HBasicBlock* if_false = graph()->CreateBasicBlock();
4688 HCompareMap* compare = 4689 HCompareMap* compare =
4689 new(zone()) HCompareMap(object, map, if_true, if_false); 4690 new(zone()) HCompareMap(object, map, if_true, if_false);
4690 current_block()->Finish(compare); 4691 current_block()->Finish(compare);
4691 4692
4692 set_current_block(if_true); 4693 set_current_block(if_true);
4693 4694
4694 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. 4695 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
4695 if (lookup.IsField()) { 4696 if (lookup.IsField()) {
4696 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); 4697 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
4697 HLoadNamedField* load = BuildLoadNamedField(compare, access); 4698 HLoadNamedField* load = BuildLoadNamedField(compare, access);
4698 load->set_position(expr->position()); 4699 load->set_position(position);
4699 AddInstruction(load); 4700 AddInstruction(load);
4700 if (!ast_context()->IsEffect()) Push(load); 4701 if (!ast_context()->IsEffect()) Push(load);
4701 } else if (lookup.IsConstant()) { 4702 } else if (lookup.IsConstant()) {
4702 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); 4703 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
4703 HConstant* hconstant = Add<HConstant>(constant); 4704 HConstant* hconstant = Add<HConstant>(constant);
4704 if (!ast_context()->IsEffect()) Push(hconstant); 4705 if (!ast_context()->IsEffect()) Push(hconstant);
4705 } else { 4706 } else {
4706 ASSERT(!lookup.IsFound()); 4707 ASSERT(!lookup.IsFound());
4707 if (map->prototype()->IsJSObject()) { 4708 if (map->prototype()->IsJSObject()) {
4708 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 4709 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
(...skipping 10 matching lines...) Expand all
4719 set_current_block(if_false); 4720 set_current_block(if_false);
4720 } 4721 }
4721 } 4722 }
4722 4723
4723 // Finish up. Unconditionally deoptimize if we've handled all the maps we 4724 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4724 // know about and do not want to handle ones we've never seen. Otherwise 4725 // know about and do not want to handle ones we've never seen. Otherwise
4725 // use a generic IC. 4726 // use a generic IC.
4726 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 4727 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4727 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); 4728 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
4728 } else { 4729 } else {
4729 HInstruction* load = BuildLoadNamedGeneric(object, name, expr); 4730 HValue* context = environment()->context();
4730 load->set_position(expr->position()); 4731 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name);
4732 load->set_position(position);
4731 AddInstruction(load); 4733 AddInstruction(load);
4732 if (!ast_context()->IsEffect()) Push(load); 4734 if (!ast_context()->IsEffect()) Push(load);
4733 4735
4734 if (join != NULL) { 4736 if (join != NULL) {
4735 current_block()->Goto(join); 4737 current_block()->Goto(join);
4736 } else { 4738 } else {
4737 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 4739 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4738 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 4740 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4739 return; 4741 return;
4740 } 4742 }
4741 } 4743 }
4742 4744
4743 ASSERT(join != NULL); 4745 ASSERT(join != NULL);
4744 join->SetJoinId(expr->id()); 4746 join->SetJoinId(ast_id);
4745 set_current_block(join); 4747 set_current_block(join);
4746 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 4748 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4747 } 4749 }
4748 4750
4749 4751
4750 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( 4752 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
4751 int position, 4753 int position,
4752 BailoutId assignment_id, 4754 BailoutId assignment_id,
4753 HValue* object, 4755 HValue* object,
4754 HValue* store_value, 4756 HValue* value,
4755 HValue* result_value,
4756 SmallMapList* types, 4757 SmallMapList* types,
4757 Handle<String> name) { 4758 Handle<String> name) {
4758 // Use monomorphic store if property lookup results in the same field index 4759 // Use monomorphic store if property lookup results in the same field index
4759 // for all maps. Requires special map check on the set of all handled maps. 4760 // for all maps. Requires special map check on the set of all handled maps.
4760 if (types->length() > kMaxStorePolymorphism) return false; 4761 if (types->length() > kMaxStorePolymorphism) return false;
4761 4762
4762 // TODO(verwaest): Merge the checking logic with the code in 4763 // TODO(verwaest): Merge the checking logic with the code in
4763 // TryLoadPolymorphicAsMonomorphic. 4764 // TryLoadPolymorphicAsMonomorphic.
4764 LookupResult lookup(isolate()); 4765 LookupResult lookup(isolate());
4765 int count; 4766 int count;
(...skipping 25 matching lines...) Expand all
4791 } 4792 }
4792 4793
4793 if (count != types->length()) return false; 4794 if (count != types->length()) return false;
4794 4795
4795 // Everything matched; can use monomorphic store. 4796 // Everything matched; can use monomorphic store.
4796 BuildCheckHeapObject(object); 4797 BuildCheckHeapObject(object);
4797 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); 4798 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
4798 HInstruction* store; 4799 HInstruction* store;
4799 CHECK_ALIVE_OR_RETURN( 4800 CHECK_ALIVE_OR_RETURN(
4800 store = BuildStoreNamedField( 4801 store = BuildStoreNamedField(
4801 checked_object, name, store_value, types->at(count - 1), &lookup), 4802 checked_object, name, value, types->at(count - 1), &lookup),
4802 true); 4803 true);
4803 if (!ast_context()->IsEffect()) Push(result_value); 4804 if (!ast_context()->IsEffect()) Push(value);
4804 store->set_position(position); 4805 store->set_position(position);
4805 AddInstruction(store); 4806 AddInstruction(store);
4806 Add<HSimulate>(assignment_id); 4807 Add<HSimulate>(assignment_id);
4807 if (!ast_context()->IsEffect()) Drop(1); 4808 if (!ast_context()->IsEffect()) Drop(1);
4808 ast_context()->ReturnValue(result_value); 4809 ast_context()->ReturnValue(value);
4809 return true; 4810 return true;
4810 } 4811 }
4811 4812
4812 4813
4813 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( 4814 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
4814 int position, 4815 int position,
4815 BailoutId assignment_id, 4816 BailoutId assignment_id,
4816 HValue* object, 4817 HValue* object,
4817 HValue* store_value, 4818 HValue* value,
4818 HValue* result_value,
4819 SmallMapList* types, 4819 SmallMapList* types,
4820 Handle<String> name) { 4820 Handle<String> name) {
4821 if (TryStorePolymorphicAsMonomorphic( 4821 if (TryStorePolymorphicAsMonomorphic(
4822 position, assignment_id, object, 4822 position, assignment_id, object, value, types, name)) {
4823 store_value, result_value, types, name)) {
4824 return; 4823 return;
4825 } 4824 }
4826 4825
4827 // TODO(ager): We should recognize when the prototype chains for different 4826 // TODO(ager): We should recognize when the prototype chains for different
4828 // maps are identical. In that case we can avoid repeatedly generating the 4827 // maps are identical. In that case we can avoid repeatedly generating the
4829 // same prototype map checks. 4828 // same prototype map checks.
4830 int count = 0; 4829 int count = 0;
4831 HBasicBlock* join = NULL; 4830 HBasicBlock* join = NULL;
4832 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 4831 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
4833 Handle<Map> map = types->at(i); 4832 Handle<Map> map = types->at(i);
4834 LookupResult lookup(isolate()); 4833 LookupResult lookup(isolate());
4835 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4834 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4836 if (count == 0) { 4835 if (count == 0) {
4837 BuildCheckHeapObject(object); 4836 BuildCheckHeapObject(object);
4838 join = graph()->CreateBasicBlock(); 4837 join = graph()->CreateBasicBlock();
4839 } 4838 }
4840 ++count; 4839 ++count;
4841 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4840 HBasicBlock* if_true = graph()->CreateBasicBlock();
4842 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4841 HBasicBlock* if_false = graph()->CreateBasicBlock();
4843 HCompareMap* compare = 4842 HCompareMap* compare =
4844 new(zone()) HCompareMap(object, map, if_true, if_false); 4843 new(zone()) HCompareMap(object, map, if_true, if_false);
4845 current_block()->Finish(compare); 4844 current_block()->Finish(compare);
4846 4845
4847 set_current_block(if_true); 4846 set_current_block(if_true);
4848 HInstruction* instr; 4847 HInstruction* instr;
4849 CHECK_ALIVE(instr = BuildStoreNamedField( 4848 CHECK_ALIVE(instr = BuildStoreNamedField(
4850 compare, name, store_value, map, &lookup)); 4849 compare, name, value, map, &lookup));
4851 instr->set_position(position); 4850 instr->set_position(position);
4852 // Goto will add the HSimulate for the store. 4851 // Goto will add the HSimulate for the store.
4853 AddInstruction(instr); 4852 AddInstruction(instr);
4854 if (!ast_context()->IsEffect()) Push(result_value); 4853 if (!ast_context()->IsEffect()) Push(value);
4855 current_block()->Goto(join); 4854 current_block()->Goto(join);
4856 4855
4857 set_current_block(if_false); 4856 set_current_block(if_false);
4858 } 4857 }
4859 } 4858 }
4860 4859
4861 // Finish up. Unconditionally deoptimize if we've handled all the maps we 4860 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4862 // know about and do not want to handle ones we've never seen. Otherwise 4861 // know about and do not want to handle ones we've never seen. Otherwise
4863 // use a generic IC. 4862 // use a generic IC.
4864 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 4863 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4865 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join); 4864 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
4866 } else { 4865 } else {
4867 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); 4866 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
4868 instr->set_position(position); 4867 instr->set_position(position);
4869 AddInstruction(instr); 4868 AddInstruction(instr);
4870 4869
4871 if (join != NULL) { 4870 if (join != NULL) {
4872 if (!ast_context()->IsEffect()) { 4871 if (!ast_context()->IsEffect()) {
4873 Push(result_value); 4872 Push(value);
4874 } 4873 }
4875 current_block()->Goto(join); 4874 current_block()->Goto(join);
4876 } else { 4875 } else {
4877 // The HSimulate for the store should not see the stored value in 4876 // The HSimulate for the store should not see the stored value in
4878 // effect contexts (it is not materialized at expr->id() in the 4877 // effect contexts (it is not materialized at expr->id() in the
4879 // unoptimized code). 4878 // unoptimized code).
4880 if (instr->HasObservableSideEffects()) { 4879 if (instr->HasObservableSideEffects()) {
4881 if (ast_context()->IsEffect()) { 4880 if (ast_context()->IsEffect()) {
4882 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); 4881 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
4883 } else { 4882 } else {
4884 Push(result_value); 4883 Push(value);
4885 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE); 4884 Add<HSimulate>(assignment_id, REMOVABLE_SIMULATE);
4886 Drop(1); 4885 Drop(1);
4887 } 4886 }
4888 } 4887 }
4889 return ast_context()->ReturnValue(result_value); 4888 return ast_context()->ReturnValue(value);
4890 } 4889 }
4891 } 4890 }
4892 4891
4893 ASSERT(join != NULL); 4892 ASSERT(join != NULL);
4894 join->SetJoinId(assignment_id); 4893 join->SetJoinId(assignment_id);
4895 set_current_block(join); 4894 set_current_block(join);
4896 if (!ast_context()->IsEffect()) { 4895 if (!ast_context()->IsEffect()) {
4897 ast_context()->ReturnValue(Pop()); 4896 ast_context()->ReturnValue(Pop());
4898 } 4897 }
4899 } 4898 }
4900 4899
4901 4900
4901 static bool ComputeReceiverTypes(Expression* expr,
4902 HValue* receiver,
4903 SmallMapList** t) {
4904 SmallMapList* types = expr->GetReceiverTypes();
4905 *t = types;
4906 bool monomorphic = expr->IsMonomorphic();
4907 if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
4908 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
4909 types->FilterForPossibleTransitions(root_map);
4910 monomorphic = types->length() == 1;
4911 }
4912 return monomorphic && CanInlinePropertyAccess(*types->first());
4913 }
4914
4915
4916 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
4917 Property* prop,
4918 BailoutId ast_id,
4919 BailoutId return_id,
4920 bool is_uninitialized) {
4921 HValue* value = environment()->ExpressionStackAt(0);
4922
4923 if (!prop->key()->IsPropertyName()) {
4924 // Keyed store.
4925 HValue* key = environment()->ExpressionStackAt(1);
4926 HValue* object = environment()->ExpressionStackAt(2);
4927 bool has_side_effects = false;
4928 HandleKeyedElementAccess(object, key, value, expr, return_id,
4929 expr->position(),
4930 true, // is_store
4931 &has_side_effects);
4932 Drop(3);
4933 Push(value);
4934 Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
4935 return ast_context()->ReturnValue(Pop());
4936 }
4937
4938 // Named store.
4939 HValue* object = environment()->ExpressionStackAt(1);
4940
4941 if (is_uninitialized) {
4942 Add<HDeoptimize>("Insufficient type feedback for property assignment",
4943 Deoptimizer::SOFT);
4944 }
4945
4946 Literal* key = prop->key()->AsLiteral();
4947 Handle<String> name = Handle<String>::cast(key->value());
4948 ASSERT(!name.is_null());
4949
4950 HInstruction* instr = NULL;
4951
4952 SmallMapList* types;
4953 bool monomorphic = ComputeReceiverTypes(expr, object, &types);
4954
4955 if (monomorphic) {
4956 Handle<Map> map = types->first();
4957 Handle<JSFunction> setter;
4958 Handle<JSObject> holder;
4959 if (LookupSetter(map, name, &setter, &holder)) {
4960 AddCheckConstantFunction(holder, object, map);
4961 if (FLAG_inline_accessors &&
4962 TryInlineSetter(setter, ast_id, return_id, value)) {
4963 return;
4964 }
4965 Drop(2);
4966 Add<HPushArgument>(object);
4967 Add<HPushArgument>(value);
4968 instr = new(zone()) HCallConstantFunction(setter, 2);
4969 } else {
4970 Drop(2);
4971 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
4972 name,
4973 value,
4974 map));
4975 }
4976 } else if (types != NULL && types->length() > 1) {
4977 Drop(2);
4978 return HandlePolymorphicStoreNamedField(
4979 expr->position(), ast_id, object, value, types, name);
4980 } else {
4981 Drop(2);
4982 instr = BuildStoreNamedGeneric(object, name, value);
4983 }
4984
4985 if (!ast_context()->IsEffect()) Push(value);
4986 instr->set_position(expr->position());
4987 AddInstruction(instr);
4988 if (instr->HasObservableSideEffects()) {
4989 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4990 }
4991 if (!ast_context()->IsEffect()) Drop(1);
4992 return ast_context()->ReturnValue(value);
4993 }
4994
4995
4902 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 4996 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
4903 Property* prop = expr->target()->AsProperty(); 4997 Property* prop = expr->target()->AsProperty();
4904 ASSERT(prop != NULL); 4998 ASSERT(prop != NULL);
4905 CHECK_ALIVE(VisitForValue(prop->obj())); 4999 CHECK_ALIVE(VisitForValue(prop->obj()));
4906 5000 if (!prop->key()->IsPropertyName()) {
4907 if (prop->key()->IsPropertyName()) {
4908 // Named store.
4909 CHECK_ALIVE(VisitForValue(expr->value()));
4910 HValue* value = environment()->ExpressionStackAt(0);
4911 HValue* object = environment()->ExpressionStackAt(1);
4912
4913 if (expr->IsUninitialized()) {
4914 Add<HDeoptimize>("Insufficient type feedback for property assignment",
4915 Deoptimizer::SOFT);
4916 }
4917 return BuildStoreNamed(expr, expr->id(), expr->position(),
4918 expr->AssignmentId(), prop, object, value, value);
4919 } else {
4920 // Keyed store.
4921 CHECK_ALIVE(VisitForValue(prop->key())); 5001 CHECK_ALIVE(VisitForValue(prop->key()));
4922 CHECK_ALIVE(VisitForValue(expr->value()));
4923 HValue* value = environment()->ExpressionStackAt(0);
4924 HValue* key = environment()->ExpressionStackAt(1);
4925 HValue* object = environment()->ExpressionStackAt(2);
4926 bool has_side_effects = false;
4927 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
4928 expr->position(),
4929 true, // is_store
4930 &has_side_effects);
4931 Drop(3);
4932 Push(value);
4933 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
4934 return ast_context()->ReturnValue(Pop());
4935 } 5002 }
5003 CHECK_ALIVE(VisitForValue(expr->value()));
5004 BuildStore(expr, prop, expr->id(),
5005 expr->AssignmentId(), expr->IsUninitialized());
4936 } 5006 }
4937 5007
4938 5008
4939 // Because not every expression has a position and there is not common 5009 // Because not every expression has a position and there is not common
4940 // superclass of Assignment and CountOperation, we cannot just pass the 5010 // superclass of Assignment and CountOperation, we cannot just pass the
4941 // owning expression instead of position and ast_id separately. 5011 // owning expression instead of position and ast_id separately.
4942 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( 5012 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
4943 Variable* var, 5013 Variable* var,
4944 HValue* value, 5014 HValue* value,
4945 int position, 5015 int position,
(...skipping 28 matching lines...) Expand all
4974 HStoreGlobalGeneric* instr = 5044 HStoreGlobalGeneric* instr =
4975 Add<HStoreGlobalGeneric>(global_object, var->name(), 5045 Add<HStoreGlobalGeneric>(global_object, var->name(),
4976 value, function_strict_mode_flag()); 5046 value, function_strict_mode_flag());
4977 instr->set_position(position); 5047 instr->set_position(position);
4978 ASSERT(instr->HasObservableSideEffects()); 5048 ASSERT(instr->HasObservableSideEffects());
4979 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 5049 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4980 } 5050 }
4981 } 5051 }
4982 5052
4983 5053
4984 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
4985 BailoutId id,
4986 int position,
4987 BailoutId assignment_id,
4988 Property* prop,
4989 HValue* object,
4990 HValue* store_value,
4991 HValue* result_value) {
4992 Literal* key = prop->key()->AsLiteral();
4993 Handle<String> name = Handle<String>::cast(key->value());
4994 ASSERT(!name.is_null());
4995
4996 HInstruction* instr = NULL;
4997 SmallMapList* types = expr->GetReceiverTypes();
4998 bool monomorphic = expr->IsMonomorphic();
4999 Handle<Map> map;
5000 if (monomorphic) {
5001 map = types->first();
5002 if (map->is_dictionary_map()) monomorphic = false;
5003 }
5004 if (monomorphic) {
5005 Handle<JSFunction> setter;
5006 Handle<JSObject> holder;
5007 if (LookupSetter(map, name, &setter, &holder)) {
5008 AddCheckConstantFunction(holder, object, map);
5009 // Don't try to inline if the result_value is different from the
5010 // store_value. That case isn't handled yet by the inlining.
5011 if (result_value == store_value &&
5012 FLAG_inline_accessors &&
5013 TryInlineSetter(setter, id, assignment_id, store_value)) {
5014 return;
5015 }
5016 Drop(2);
5017 Add<HPushArgument>(object);
5018 Add<HPushArgument>(store_value);
5019 instr = new(zone()) HCallConstantFunction(setter, 2);
5020 } else {
5021 Drop(2);
5022 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
5023 name,
5024 store_value,
5025 map));
5026 }
5027 } else if (types != NULL && types->length() > 1) {
5028 Drop(2);
5029 return HandlePolymorphicStoreNamedField(
5030 position, id, object,
5031 store_value, result_value, types, name);
5032 } else {
5033 Drop(2);
5034 instr = BuildStoreNamedGeneric(object, name, store_value);
5035 }
5036
5037 if (!ast_context()->IsEffect()) Push(result_value);
5038 instr->set_position(position);
5039 AddInstruction(instr);
5040 if (instr->HasObservableSideEffects()) {
5041 Add<HSimulate>(id, REMOVABLE_SIMULATE);
5042 }
5043 if (!ast_context()->IsEffect()) Drop(1);
5044 return ast_context()->ReturnValue(result_value);
5045 }
5046
5047
5048 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 5054 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
5049 Expression* target = expr->target(); 5055 Expression* target = expr->target();
5050 VariableProxy* proxy = target->AsVariableProxy(); 5056 VariableProxy* proxy = target->AsVariableProxy();
5051 Property* prop = target->AsProperty(); 5057 Property* prop = target->AsProperty();
5052 ASSERT(proxy == NULL || prop == NULL); 5058 ASSERT(proxy == NULL || prop == NULL);
5053 5059
5054 // We have a second position recorded in the FullCodeGenerator to have 5060 // We have a second position recorded in the FullCodeGenerator to have
5055 // type feedback for the binary operation. 5061 // type feedback for the binary operation.
5056 BinaryOperation* operation = expr->binary_operation(); 5062 BinaryOperation* operation = expr->binary_operation();
5057 5063
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
5119 } 5125 }
5120 break; 5126 break;
5121 } 5127 }
5122 5128
5123 case Variable::LOOKUP: 5129 case Variable::LOOKUP:
5124 return Bailout(kCompoundAssignmentToLookupSlot); 5130 return Bailout(kCompoundAssignmentToLookupSlot);
5125 } 5131 }
5126 return ast_context()->ReturnValue(Pop()); 5132 return ast_context()->ReturnValue(Pop());
5127 5133
5128 } else if (prop != NULL) { 5134 } else if (prop != NULL) {
5129 if (prop->key()->IsPropertyName()) { 5135 CHECK_ALIVE(VisitForValue(prop->obj()));
5130 // Named property. 5136 HValue* object = Top();
5131 CHECK_ALIVE(VisitForValue(prop->obj())); 5137 HValue* key = NULL;
5132 HValue* object = Top(); 5138 if ((!prop->IsStringLength() &&
5133 5139 !prop->IsFunctionPrototype() &&
5134 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 5140 !prop->key()->IsPropertyName()) ||
5135 Handle<Map> map; 5141 prop->IsStringAccess()) {
5136 HInstruction* load = NULL;
5137 SmallMapList* types = prop->GetReceiverTypes();
5138 bool monomorphic = prop->IsMonomorphic();
5139 if (monomorphic) {
5140 map = types->first();
5141 // We can't generate code for a monomorphic dict mode load so
5142 // just pretend it is not monomorphic.
5143 if (map->is_dictionary_map()) monomorphic = false;
5144 }
5145 if (monomorphic) {
5146 Handle<JSFunction> getter;
5147 Handle<JSObject> holder;
5148 if (LookupGetter(map, name, &getter, &holder)) {
5149 load = BuildCallGetter(object, map, getter, holder);
5150 } else {
5151 load = BuildLoadNamedMonomorphic(object, name, prop, map);
5152 }
5153 } else if (types != NULL && types->length() > 1) {
5154 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name);
5155 }
5156 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
5157 PushAndAdd(load);
5158 if (load->HasObservableSideEffects()) {
5159 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
5160 }
5161
5162 CHECK_ALIVE(VisitForValue(expr->value()));
5163 HValue* right = Pop();
5164 HValue* left = Pop();
5165
5166 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5167 PushAndAdd(instr);
5168 if (instr->HasObservableSideEffects()) {
5169 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
5170 }
5171
5172 return BuildStoreNamed(expr, expr->id(), expr->position(),
5173 expr->AssignmentId(), prop, object, instr, instr);
5174 } else {
5175 // Keyed property.
5176 CHECK_ALIVE(VisitForValue(prop->obj()));
5177 CHECK_ALIVE(VisitForValue(prop->key())); 5142 CHECK_ALIVE(VisitForValue(prop->key()));
5178 HValue* obj = environment()->ExpressionStackAt(1); 5143 key = Top();
5179 HValue* key = environment()->ExpressionStackAt(0);
5180
5181 bool has_side_effects = false;
5182 HValue* load = HandleKeyedElementAccess(
5183 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition,
5184 false, // is_store
5185 &has_side_effects);
5186 Push(load);
5187 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
5188
5189 CHECK_ALIVE(VisitForValue(expr->value()));
5190 HValue* right = Pop();
5191 HValue* left = Pop();
5192
5193 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5194 PushAndAdd(instr);
5195 if (instr->HasObservableSideEffects()) {
5196 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
5197 }
5198
5199 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
5200 RelocInfo::kNoPosition,
5201 true, // is_store
5202 &has_side_effects);
5203
5204 // Drop the simulated receiver, key, and value. Return the value.
5205 Drop(3);
5206 Push(instr);
5207 ASSERT(has_side_effects); // Stores always have side effects.
5208 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
5209 return ast_context()->ReturnValue(Pop());
5210 } 5144 }
5211 5145
5146 CHECK_ALIVE(PushLoad(prop, object, key, expr->position()));
5147
5148 CHECK_ALIVE(VisitForValue(expr->value()));
5149 HValue* right = Pop();
5150 HValue* left = Pop();
5151
5152 HInstruction* instr = BuildBinaryOperation(operation, left, right);
5153 PushAndAdd(instr);
5154 if (instr->HasObservableSideEffects()) {
5155 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE);
5156 }
5157 BuildStore(expr, prop, expr->id(),
5158 expr->AssignmentId(), expr->IsUninitialized());
5212 } else { 5159 } else {
5213 return Bailout(kInvalidLhsInCompoundAssignment); 5160 return Bailout(kInvalidLhsInCompoundAssignment);
5214 } 5161 }
5215 } 5162 }
5216 5163
5217 5164
5218 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { 5165 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
5219 ASSERT(!HasStackOverflow()); 5166 ASSERT(!HasStackOverflow());
5220 ASSERT(current_block() != NULL); 5167 ASSERT(current_block() != NULL);
5221 ASSERT(current_block()->HasPredecessor()); 5168 ASSERT(current_block()->HasPredecessor());
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
5389 } 5336 }
5390 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength()); 5337 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength());
5391 } 5338 }
5392 5339
5393 5340
5394 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 5341 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
5395 HValue* object, 5342 HValue* object,
5396 Handle<String> name, 5343 Handle<String> name,
5397 Property* expr) { 5344 Property* expr) {
5398 if (expr->IsUninitialized()) { 5345 if (expr->IsUninitialized()) {
5399 Add<HDeoptimize>("Insufficient feedback for generic named load", 5346 Add<HDeoptimize>("Insufficient type feedback for generic named load",
5400 Deoptimizer::SOFT); 5347 Deoptimizer::SOFT);
5401 } 5348 }
5402 HValue* context = environment()->context(); 5349 HValue* context = environment()->context();
5403 return new(zone()) HLoadNamedGeneric(context, object, name); 5350 return new(zone()) HLoadNamedGeneric(context, object, name);
5404 } 5351 }
5405 5352
5406 5353
5407 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( 5354 HInstruction* HOptimizedGraphBuilder::BuildCallGetter(
5408 HValue* object, 5355 HValue* object,
5409 Handle<Map> map, 5356 Handle<Map> map,
5410 Handle<JSFunction> getter, 5357 Handle<JSFunction> getter,
5411 Handle<JSObject> holder) { 5358 Handle<JSObject> holder) {
5412 AddCheckConstantFunction(holder, object, map); 5359 AddCheckConstantFunction(holder, object, map);
5413 Add<HPushArgument>(object); 5360 Add<HPushArgument>(object);
5414 return new(zone()) HCallConstantFunction(getter, 1); 5361 return new(zone()) HCallConstantFunction(getter, 1);
5415 } 5362 }
5416 5363
5417 5364
5418 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( 5365 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
5419 HValue* object, 5366 HValue* object,
5420 Handle<String> name, 5367 Handle<String> name,
5421 Property* expr,
5422 Handle<Map> map) { 5368 Handle<Map> map) {
5423 // Handle a load from a known field. 5369 // Handle a load from a known field.
5424 ASSERT(!map->is_dictionary_map()); 5370 ASSERT(!map->is_dictionary_map());
5425 5371
5426 // Handle access to various length properties 5372 // Handle access to various length properties
5427 if (name->Equals(isolate()->heap()->length_string())) { 5373 if (name->Equals(isolate()->heap()->length_string())) {
5428 if (map->instance_type() == JS_ARRAY_TYPE) { 5374 if (map->instance_type() == JS_ARRAY_TYPE) {
5429 HCheckMaps* checked_object = AddCheckMap(object, map); 5375 HCheckMaps* checked_object = AddCheckMap(object, map);
5430 return New<HLoadNamedField>( 5376 return New<HLoadNamedField>(
5431 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); 5377 checked_object, HObjectAccess::ForArrayLength(map->elements_kind()));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5464 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5410 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5465 Handle<JSObject> holder(lookup.holder()); 5411 Handle<JSObject> holder(lookup.holder());
5466 Handle<Map> holder_map(holder->map()); 5412 Handle<Map> holder_map(holder->map());
5467 AddCheckMap(object, map); 5413 AddCheckMap(object, map);
5468 BuildCheckPrototypeMaps(prototype, holder); 5414 BuildCheckPrototypeMaps(prototype, holder);
5469 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); 5415 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
5470 return New<HConstant>(constant); 5416 return New<HConstant>(constant);
5471 } 5417 }
5472 5418
5473 // No luck, do a generic load. 5419 // No luck, do a generic load.
5474 return BuildLoadNamedGeneric(object, name, expr); 5420 HValue* context = environment()->context();
5421 return new(zone()) HLoadNamedGeneric(context, object, name);
5475 } 5422 }
5476 5423
5477 5424
5478 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5425 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
5479 HValue* key) { 5426 HValue* key) {
5480 HValue* context = environment()->context(); 5427 HValue* context = environment()->context();
5481 return new(zone()) HLoadKeyedGeneric(context, object, key); 5428 return new(zone()) HLoadKeyedGeneric(context, object, key);
5482 } 5429 }
5483 5430
5484 5431
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
5703 if (!is_store) { 5650 if (!is_store) {
5704 Push(access); 5651 Push(access);
5705 } 5652 }
5706 NoObservableSideEffectsScope scope(this); 5653 NoObservableSideEffectsScope scope(this);
5707 current_block()->GotoNoSimulate(join); 5654 current_block()->GotoNoSimulate(join);
5708 set_current_block(other_map); 5655 set_current_block(other_map);
5709 } 5656 }
5710 5657
5711 // Deopt if none of the cases matched. 5658 // Deopt if none of the cases matched.
5712 NoObservableSideEffectsScope scope(this); 5659 NoObservableSideEffectsScope scope(this);
5713 FinishExitWithHardDeoptimization("Unknown type in polymorphic element access", 5660 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access",
5714 join); 5661 join);
5715 set_current_block(join); 5662 set_current_block(join);
5716 return is_store ? NULL : Pop(); 5663 return is_store ? NULL : Pop();
5717 } 5664 }
5718 5665
5719 5666
5720 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( 5667 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
5721 HValue* obj, 5668 HValue* obj,
5722 HValue* key, 5669 HValue* key,
5723 HValue* val, 5670 HValue* val,
5724 Expression* expr, 5671 Expression* expr,
5725 BailoutId ast_id, 5672 BailoutId ast_id,
5726 int position, 5673 int position,
5727 bool is_store, 5674 bool is_store,
5728 bool* has_side_effects) { 5675 bool* has_side_effects) {
5729 ASSERT(!expr->IsPropertyName()); 5676 ASSERT(!expr->IsPropertyName());
5730 HInstruction* instr = NULL; 5677 HInstruction* instr = NULL;
5731 if (expr->IsMonomorphic()) { 5678
5732 Handle<Map> map = expr->GetMonomorphicReceiverType(); 5679 SmallMapList* types;
5680 bool monomorphic = ComputeReceiverTypes(expr, obj, &types);
5681
5682 if (monomorphic) {
5683 Handle<Map> map = types->first();
5733 if (map->has_slow_elements_kind()) { 5684 if (map->has_slow_elements_kind()) {
5734 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 5685 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
5735 : BuildLoadKeyedGeneric(obj, key); 5686 : BuildLoadKeyedGeneric(obj, key);
5736 AddInstruction(instr); 5687 AddInstruction(instr);
5737 } else { 5688 } else {
5738 BuildCheckHeapObject(obj); 5689 BuildCheckHeapObject(obj);
5739 instr = BuildMonomorphicElementAccess( 5690 instr = BuildMonomorphicElementAccess(
5740 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); 5691 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
5741 } 5692 }
5742 } else if (expr->GetReceiverTypes() != NULL && 5693 } else if (expr->GetReceiverTypes() != NULL &&
5743 !expr->GetReceiverTypes()->is_empty()) { 5694 !expr->GetReceiverTypes()->is_empty()) {
5744 return HandlePolymorphicElementAccess( 5695 return HandlePolymorphicElementAccess(
5745 obj, key, val, expr, ast_id, position, is_store, 5696 obj, key, val, expr, ast_id, position, is_store,
5746 expr->GetStoreMode(), has_side_effects); 5697 expr->GetStoreMode(), has_side_effects);
5747 } else { 5698 } else {
5748 if (is_store) { 5699 if (is_store) {
5749 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { 5700 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
5750 Add<HDeoptimize>("Insufficient feedback for keyed store", 5701 Add<HDeoptimize>("Insufficient type feedback for keyed store",
5751 Deoptimizer::SOFT); 5702 Deoptimizer::SOFT);
5752 } 5703 }
5753 instr = BuildStoreKeyedGeneric(obj, key, val); 5704 instr = BuildStoreKeyedGeneric(obj, key, val);
5754 } else { 5705 } else {
5755 if (expr->AsProperty()->IsUninitialized()) { 5706 if (expr->AsProperty()->IsUninitialized()) {
5756 Add<HDeoptimize>("Insufficient feedback for keyed load", 5707 Add<HDeoptimize>("Insufficient type feedback for keyed load",
5757 Deoptimizer::SOFT); 5708 Deoptimizer::SOFT);
5758 } 5709 }
5759 instr = BuildLoadKeyedGeneric(obj, key); 5710 instr = BuildLoadKeyedGeneric(obj, key);
5760 } 5711 }
5761 AddInstruction(instr); 5712 AddInstruction(instr);
5762 } 5713 }
5763 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5714 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5764 *has_side_effects = instr->HasObservableSideEffects(); 5715 *has_side_effects = instr->HasObservableSideEffects();
5765 return instr; 5716 return instr;
5766 } 5717 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
5825 HInstruction* elements = Add<HArgumentsElements>(false); 5776 HInstruction* elements = Add<HArgumentsElements>(false);
5826 result = New<HArgumentsLength>(elements); 5777 result = New<HArgumentsLength>(elements);
5827 } else { 5778 } else {
5828 // Number of arguments without receiver. 5779 // Number of arguments without receiver.
5829 int argument_count = environment()-> 5780 int argument_count = environment()->
5830 arguments_environment()->parameter_count() - 1; 5781 arguments_environment()->parameter_count() - 1;
5831 result = New<HConstant>(argument_count); 5782 result = New<HConstant>(argument_count);
5832 } 5783 }
5833 } else { 5784 } else {
5834 Push(graph()->GetArgumentsObject()); 5785 Push(graph()->GetArgumentsObject());
5835 VisitForValue(expr->key()); 5786 CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
5836 if (HasStackOverflow() || current_block() == NULL) return true;
5837 HValue* key = Pop(); 5787 HValue* key = Pop();
5838 Drop(1); // Arguments object. 5788 Drop(1); // Arguments object.
5839 if (function_state()->outer() == NULL) { 5789 if (function_state()->outer() == NULL) {
5840 HInstruction* elements = Add<HArgumentsElements>(false); 5790 HInstruction* elements = Add<HArgumentsElements>(false);
5841 HInstruction* length = Add<HArgumentsLength>(elements); 5791 HInstruction* length = Add<HArgumentsLength>(elements);
5842 HInstruction* checked_key = Add<HBoundsCheck>(key, length); 5792 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
5843 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 5793 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
5844 } else { 5794 } else {
5845 EnsureArgumentsArePushedForAccess(); 5795 EnsureArgumentsArePushedForAccess();
5846 5796
5847 // Number of arguments without receiver. 5797 // Number of arguments without receiver.
5848 HInstruction* elements = function_state()->arguments_elements(); 5798 HInstruction* elements = function_state()->arguments_elements();
5849 int argument_count = environment()-> 5799 int argument_count = environment()->
5850 arguments_environment()->parameter_count() - 1; 5800 arguments_environment()->parameter_count() - 1;
5851 HInstruction* length = Add<HConstant>(argument_count); 5801 HInstruction* length = Add<HConstant>(argument_count);
5852 HInstruction* checked_key = Add<HBoundsCheck>(key, length); 5802 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
5853 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 5803 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
5854 } 5804 }
5855 } 5805 }
5856 ast_context()->ReturnInstruction(result, expr->id()); 5806 ast_context()->ReturnInstruction(result, expr->id());
5857 return true; 5807 return true;
5858 } 5808 }
5859 5809
5860 5810
5861 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { 5811 void HOptimizedGraphBuilder::PushLoad(Property* expr,
5862 ASSERT(!HasStackOverflow()); 5812 HValue* object,
5863 ASSERT(current_block() != NULL); 5813 HValue* key,
5864 ASSERT(current_block()->HasPredecessor()); 5814 int position) {
5815 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
5816 Push(object);
5817 if (key != NULL) Push(key);
5818 BuildLoad(expr, position, expr->LoadId());
5819 }
5865 5820
5866 if (TryArgumentsAccess(expr)) return;
5867 5821
5868 CHECK_ALIVE(VisitForValue(expr->obj())); 5822 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
5869 5823 int position,
5824 BailoutId ast_id) {
5870 HInstruction* instr = NULL; 5825 HInstruction* instr = NULL;
5871 if (expr->IsStringLength()) { 5826 if (expr->IsStringLength()) {
5872 HValue* string = Pop(); 5827 HValue* string = Pop();
5873 BuildCheckHeapObject(string); 5828 BuildCheckHeapObject(string);
5874 HInstruction* checkstring = 5829 HInstruction* checkstring =
5875 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); 5830 AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
5876 instr = BuildLoadStringLength(string, checkstring); 5831 instr = BuildLoadStringLength(string, checkstring);
5877 } else if (expr->IsStringAccess()) { 5832 } else if (expr->IsStringAccess()) {
5878 CHECK_ALIVE(VisitForValue(expr->key()));
5879 HValue* index = Pop(); 5833 HValue* index = Pop();
5880 HValue* string = Pop(); 5834 HValue* string = Pop();
5881 HValue* context = environment()->context(); 5835 HValue* context = environment()->context();
5882 HInstruction* char_code = 5836 HInstruction* char_code =
5883 BuildStringCharCodeAt(string, index); 5837 BuildStringCharCodeAt(string, index);
5884 AddInstruction(char_code); 5838 AddInstruction(char_code);
5885 instr = HStringCharFromCode::New(zone(), context, char_code); 5839 instr = HStringCharFromCode::New(zone(), context, char_code);
5886 5840
5887 } else if (expr->IsFunctionPrototype()) { 5841 } else if (expr->IsFunctionPrototype()) {
5888 HValue* function = Pop(); 5842 HValue* function = Pop();
5889 BuildCheckHeapObject(function); 5843 BuildCheckHeapObject(function);
5890 instr = new(zone()) HLoadFunctionPrototype(function); 5844 instr = new(zone()) HLoadFunctionPrototype(function);
5891 5845
5892 } else if (expr->key()->IsPropertyName()) { 5846 } else if (expr->key()->IsPropertyName()) {
5893 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 5847 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5894 SmallMapList* types = expr->GetReceiverTypes();
5895 HValue* object = Top(); 5848 HValue* object = Top();
5896 5849
5897 Handle<Map> map; 5850 SmallMapList* types;
5898 bool monomorphic = false; 5851 bool monomorphic = ComputeReceiverTypes(expr, object, &types);
5899 if (expr->IsMonomorphic()) { 5852
5900 map = types->first();
5901 monomorphic = !map->is_dictionary_map();
5902 } else if (object->HasMonomorphicJSObjectType()) {
5903 map = object->GetMonomorphicJSObjectMap();
5904 monomorphic = !map->is_dictionary_map();
5905 }
5906 if (monomorphic) { 5853 if (monomorphic) {
5854 Handle<Map> map = types->first();
5907 Handle<JSFunction> getter; 5855 Handle<JSFunction> getter;
5908 Handle<JSObject> holder; 5856 Handle<JSObject> holder;
5909 if (LookupGetter(map, name, &getter, &holder)) { 5857 if (LookupGetter(map, name, &getter, &holder)) {
5910 AddCheckConstantFunction(holder, Top(), map); 5858 AddCheckConstantFunction(holder, Top(), map);
5911 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; 5859 if (FLAG_inline_accessors &&
5860 TryInlineGetter(getter, ast_id, expr->LoadId())) {
5861 return;
5862 }
5912 Add<HPushArgument>(Pop()); 5863 Add<HPushArgument>(Pop());
5913 instr = new(zone()) HCallConstantFunction(getter, 1); 5864 instr = new(zone()) HCallConstantFunction(getter, 1);
5914 } else { 5865 } else {
5915 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); 5866 instr = BuildLoadNamedMonomorphic(Pop(), name, map);
5916 } 5867 }
5917 } else if (types != NULL && types->length() > 1) { 5868 } else if (types != NULL && types->length() > 1) {
5918 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); 5869 return HandlePolymorphicLoadNamedField(
5870 position, ast_id, Pop(), types, name);
5919 } else { 5871 } else {
5920 instr = BuildLoadNamedGeneric(Pop(), name, expr); 5872 instr = BuildLoadNamedGeneric(Pop(), name, expr);
5921 } 5873 }
5922 5874
5923 } else { 5875 } else {
5924 CHECK_ALIVE(VisitForValue(expr->key()));
5925
5926 HValue* key = Pop(); 5876 HValue* key = Pop();
5927 HValue* obj = Pop(); 5877 HValue* obj = Pop();
5928 5878
5929 bool has_side_effects = false; 5879 bool has_side_effects = false;
5930 HValue* load = HandleKeyedElementAccess( 5880 HValue* load = HandleKeyedElementAccess(
5931 obj, key, NULL, expr, expr->id(), expr->position(), 5881 obj, key, NULL, expr, ast_id, position,
5932 false, // is_store 5882 false, // is_store
5933 &has_side_effects); 5883 &has_side_effects);
5934 if (has_side_effects) { 5884 if (has_side_effects) {
5935 if (ast_context()->IsEffect()) { 5885 if (ast_context()->IsEffect()) {
5936 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 5886 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5937 } else { 5887 } else {
5938 Push(load); 5888 Push(load);
5939 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 5889 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
5940 Drop(1); 5890 Drop(1);
5941 } 5891 }
5942 } 5892 }
5943 return ast_context()->ReturnValue(load); 5893 return ast_context()->ReturnValue(load);
5944 } 5894 }
5945 instr->set_position(expr->position()); 5895 instr->set_position(position);
5946 return ast_context()->ReturnInstruction(instr, expr->id()); 5896 return ast_context()->ReturnInstruction(instr, ast_id);
5947 } 5897 }
5948 5898
5949 5899
5900 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
5901 ASSERT(!HasStackOverflow());
5902 ASSERT(current_block() != NULL);
5903 ASSERT(current_block()->HasPredecessor());
5904
5905 if (TryArgumentsAccess(expr)) return;
5906
5907 CHECK_ALIVE(VisitForValue(expr->obj()));
5908 if ((!expr->IsStringLength() &&
5909 !expr->IsFunctionPrototype() &&
5910 !expr->key()->IsPropertyName()) ||
5911 expr->IsStringAccess()) {
5912 CHECK_ALIVE(VisitForValue(expr->key()));
5913 }
5914
5915 BuildLoad(expr, expr->position(), expr->id());
5916 }
5917
5918
5950 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, 5919 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
5951 CompilationInfo* info) { 5920 CompilationInfo* info) {
5952 HConstant* constant_value = New<HConstant>(constant); 5921 HConstant* constant_value = New<HConstant>(constant);
5953 5922
5954 if (constant->map()->CanOmitMapChecks()) { 5923 if (constant->map()->CanOmitMapChecks()) {
5955 constant->map()->AddDependentCompilationInfo( 5924 constant->map()->AddDependentCompilationInfo(
5956 DependentCode::kPrototypeCheckGroup, info); 5925 DependentCode::kPrototypeCheckGroup, info);
5957 return constant_value; 5926 return constant_value;
5958 } 5927 }
5959 5928
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
6367 FunctionLiteral* function = target_info.function(); 6336 FunctionLiteral* function = target_info.function();
6368 6337
6369 // The following conditions must be checked again after re-parsing, because 6338 // The following conditions must be checked again after re-parsing, because
6370 // earlier the information might not have been complete due to lazy parsing. 6339 // earlier the information might not have been complete due to lazy parsing.
6371 nodes_added = function->ast_node_count(); 6340 nodes_added = function->ast_node_count();
6372 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 6341 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
6373 TraceInline(target, caller, "target AST is too large [late]"); 6342 TraceInline(target, caller, "target AST is too large [late]");
6374 return false; 6343 return false;
6375 } 6344 }
6376 AstProperties::Flags* flags(function->flags()); 6345 AstProperties::Flags* flags(function->flags());
6377 if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) { 6346 if (flags->Contains(kDontInline) || function->dont_optimize()) {
6378 TraceInline(target, caller, "target contains unsupported syntax [late]"); 6347 TraceInline(target, caller, "target contains unsupported syntax [late]");
6379 return false; 6348 return false;
6380 } 6349 }
6381 6350
6382 // If the function uses the arguments object check that inlining of functions 6351 // If the function uses the arguments object check that inlining of functions
6383 // with arguments object is enabled and the arguments-variable is 6352 // with arguments object is enabled and the arguments-variable is
6384 // stack allocated. 6353 // stack allocated.
6385 if (function->scope()->arguments() != NULL) { 6354 if (function->scope()->arguments() != NULL) {
6386 if (!FLAG_inline_arguments) { 6355 if (!FLAG_inline_arguments) {
6387 TraceInline(target, caller, "target uses arguments object"); 6356 TraceInline(target, caller, "target uses arguments object");
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
6613 expr->target(), 6582 expr->target(),
6614 expr->arguments()->length(), 6583 expr->arguments()->length(),
6615 implicit_return_value, 6584 implicit_return_value,
6616 expr->id(), 6585 expr->id(),
6617 expr->ReturnId(), 6586 expr->ReturnId(),
6618 CONSTRUCT_CALL_RETURN); 6587 CONSTRUCT_CALL_RETURN);
6619 } 6588 }
6620 6589
6621 6590
6622 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, 6591 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
6623 Property* prop) { 6592 BailoutId ast_id,
6593 BailoutId return_id) {
6624 return TryInline(CALL_AS_METHOD, 6594 return TryInline(CALL_AS_METHOD,
6625 getter, 6595 getter,
6626 0, 6596 0,
6627 NULL, 6597 NULL,
6628 prop->id(), 6598 ast_id,
6629 prop->LoadId(), 6599 return_id,
6630 GETTER_CALL_RETURN); 6600 GETTER_CALL_RETURN);
6631 } 6601 }
6632 6602
6633 6603
6634 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, 6604 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
6635 BailoutId id, 6605 BailoutId id,
6636 BailoutId assignment_id, 6606 BailoutId assignment_id,
6637 HValue* implicit_return_value) { 6607 HValue* implicit_return_value) {
6638 return TryInline(CALL_AS_METHOD, 6608 return TryInline(CALL_AS_METHOD,
6639 setter, 6609 setter,
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
6874 6844
6875 ZoneList<Expression*>* args = expr->arguments(); 6845 ZoneList<Expression*>* args = expr->arguments();
6876 if (args->length() != 2) return false; 6846 if (args->length() != 2) return false;
6877 6847
6878 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 6848 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
6879 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 6849 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
6880 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); 6850 HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
6881 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 6851 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
6882 6852
6883 // Found pattern f.apply(receiver, arguments). 6853 // Found pattern f.apply(receiver, arguments).
6884 VisitForValue(prop->obj()); 6854 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true);
6885 if (HasStackOverflow() || current_block() == NULL) return true;
6886 HValue* function = Top(); 6855 HValue* function = Top();
6887 AddCheckConstantFunction(expr->holder(), function, function_map); 6856 AddCheckConstantFunction(expr->holder(), function, function_map);
6888 Drop(1); 6857 Drop(1);
6889 6858
6890 VisitForValue(args->at(0)); 6859 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
6891 if (HasStackOverflow() || current_block() == NULL) return true;
6892 HValue* receiver = Pop(); 6860 HValue* receiver = Pop();
6893 6861
6894 if (function_state()->outer() == NULL) { 6862 if (function_state()->outer() == NULL) {
6895 HInstruction* elements = Add<HArgumentsElements>(false); 6863 HInstruction* elements = Add<HArgumentsElements>(false);
6896 HInstruction* length = Add<HArgumentsLength>(elements); 6864 HInstruction* length = Add<HArgumentsLength>(elements);
6897 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); 6865 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function);
6898 HInstruction* result = 6866 HInstruction* result =
6899 new(zone()) HApplyArguments(function, 6867 new(zone()) HApplyArguments(function,
6900 wrapped_receiver, 6868 wrapped_receiver,
6901 length, 6869 length,
(...skipping 10 matching lines...) Expand all
6912 const ZoneList<HValue*>* arguments_values = args->arguments_values(); 6880 const ZoneList<HValue*>* arguments_values = args->arguments_values();
6913 int arguments_count = arguments_values->length(); 6881 int arguments_count = arguments_values->length();
6914 Push(BuildWrapReceiver(receiver, function)); 6882 Push(BuildWrapReceiver(receiver, function));
6915 for (int i = 1; i < arguments_count; i++) { 6883 for (int i = 1; i < arguments_count; i++) {
6916 Push(arguments_values->at(i)); 6884 Push(arguments_values->at(i));
6917 } 6885 }
6918 6886
6919 Handle<JSFunction> known_function; 6887 Handle<JSFunction> known_function;
6920 if (function->IsConstant()) { 6888 if (function->IsConstant()) {
6921 HConstant* constant_function = HConstant::cast(function); 6889 HConstant* constant_function = HConstant::cast(function);
6922 known_function = Handle<JSFunction>::cast(constant_function->handle()); 6890 known_function = Handle<JSFunction>::cast(
6891 constant_function->handle(isolate()));
6923 int args_count = arguments_count - 1; // Excluding receiver. 6892 int args_count = arguments_count - 1; // Excluding receiver.
6924 if (TryInlineApply(known_function, expr, args_count)) return true; 6893 if (TryInlineApply(known_function, expr, args_count)) return true;
6925 } 6894 }
6926 6895
6927 Drop(arguments_count - 1); 6896 Drop(arguments_count - 1);
6928 PushAndAdd(New<HPushArgument>(Pop())); 6897 PushAndAdd(New<HPushArgument>(Pop()));
6929 for (int i = 1; i < arguments_count; i++) { 6898 for (int i = 1; i < arguments_count; i++) {
6930 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); 6899 PushAndAdd(New<HPushArgument>(arguments_values->at(i)));
6931 } 6900 }
6932 6901
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
6974 return ast_context()->ReturnInstruction(call, expr->id()); 6943 return ast_context()->ReturnInstruction(call, expr->id());
6975 } 6944 }
6976 6945
6977 // Named function call. 6946 // Named function call.
6978 if (TryCallApply(expr)) return; 6947 if (TryCallApply(expr)) return;
6979 6948
6980 CHECK_ALIVE(VisitForValue(prop->obj())); 6949 CHECK_ALIVE(VisitForValue(prop->obj()));
6981 CHECK_ALIVE(VisitExpressions(expr->arguments())); 6950 CHECK_ALIVE(VisitExpressions(expr->arguments()));
6982 6951
6983 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 6952 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
6984 SmallMapList* types = expr->GetReceiverTypes(); 6953 HValue* receiver =
6954 environment()->ExpressionStackAt(expr->arguments()->length());
6985 6955
6986 bool monomorphic = expr->IsMonomorphic(); 6956 SmallMapList* types;
6987 Handle<Map> receiver_map; 6957 bool was_monomorphic = expr->IsMonomorphic();
6988 if (monomorphic) { 6958 bool monomorphic = ComputeReceiverTypes(expr, receiver, &types);
6989 receiver_map = (types == NULL || types->is_empty()) 6959 if (!was_monomorphic && monomorphic) {
6990 ? Handle<Map>::null() 6960 monomorphic = expr->ComputeTarget(types->first(), name);
6991 : types->first();
6992 } 6961 }
6993 6962
6994 HValue* receiver =
6995 environment()->ExpressionStackAt(expr->arguments()->length());
6996 if (monomorphic) { 6963 if (monomorphic) {
6997 if (TryInlineBuiltinMethodCall(expr, 6964 Handle<Map> map = types->first();
6998 receiver, 6965 if (TryInlineBuiltinMethodCall(expr, receiver, map, expr->check_type())) {
6999 receiver_map,
7000 expr->check_type())) {
7001 if (FLAG_trace_inlining) { 6966 if (FLAG_trace_inlining) {
7002 PrintF("Inlining builtin "); 6967 PrintF("Inlining builtin ");
7003 expr->target()->ShortPrint(); 6968 expr->target()->ShortPrint();
7004 PrintF("\n"); 6969 PrintF("\n");
7005 } 6970 }
7006 return; 6971 return;
7007 } 6972 }
7008 6973
7009 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 6974 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) ||
7010 expr->check_type() != RECEIVER_MAP_CHECK) { 6975 expr->check_type() != RECEIVER_MAP_CHECK) {
7011 // When the target has a custom call IC generator, use the IC, 6976 // When the target has a custom call IC generator, use the IC,
7012 // because it is likely to generate better code. Also use the IC 6977 // because it is likely to generate better code. Also use the IC
7013 // when a primitive receiver check is required. 6978 // when a primitive receiver check is required.
7014 HValue* context = environment()->context(); 6979 HValue* context = environment()->context();
7015 call = PreProcessCall( 6980 call = PreProcessCall(
7016 new(zone()) HCallNamed(context, name, argument_count)); 6981 new(zone()) HCallNamed(context, name, argument_count));
7017 } else { 6982 } else {
7018 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 6983 AddCheckConstantFunction(expr->holder(), receiver, map);
7019 6984
7020 if (TryInlineCall(expr)) return; 6985 if (TryInlineCall(expr)) return;
7021 call = PreProcessCall( 6986 call = PreProcessCall(
7022 new(zone()) HCallConstantFunction(expr->target(), 6987 new(zone()) HCallConstantFunction(expr->target(),
7023 argument_count)); 6988 argument_count));
7024 } 6989 }
7025 } else if (types != NULL && types->length() > 1) { 6990 } else if (types != NULL && types->length() > 1) {
7026 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 6991 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
7027 HandlePolymorphicCallNamed(expr, receiver, types, name); 6992 HandlePolymorphicCallNamed(expr, receiver, types, name);
7028 return; 6993 return;
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
7483 HAdd* add = HAdd::cast(instr); 7448 HAdd* add = HAdd::cast(instr);
7484 add->set_observed_input_representation(1, rep); 7449 add->set_observed_input_representation(1, rep);
7485 add->set_observed_input_representation(2, Representation::Smi()); 7450 add->set_observed_input_representation(2, Representation::Smi());
7486 } 7451 }
7487 instr->SetFlag(HInstruction::kCannotBeTagged); 7452 instr->SetFlag(HInstruction::kCannotBeTagged);
7488 instr->ClearAllSideEffects(); 7453 instr->ClearAllSideEffects();
7489 return instr; 7454 return instr;
7490 } 7455 }
7491 7456
7492 7457
7458 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr,
7459 Property* prop,
7460 BailoutId ast_id,
7461 BailoutId return_id,
7462 HValue* object,
7463 HValue* key,
7464 HValue* value) {
7465 EffectContext for_effect(this);
7466 Push(object);
7467 if (key != NULL) Push(key);
7468 Push(value);
7469 BuildStore(expr, prop, ast_id, return_id);
7470 }
7471
7472
7493 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { 7473 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
7494 ASSERT(!HasStackOverflow()); 7474 ASSERT(!HasStackOverflow());
7495 ASSERT(current_block() != NULL); 7475 ASSERT(current_block() != NULL);
7496 ASSERT(current_block()->HasPredecessor()); 7476 ASSERT(current_block()->HasPredecessor());
7497 Expression* target = expr->expression(); 7477 Expression* target = expr->expression();
7498 VariableProxy* proxy = target->AsVariableProxy(); 7478 VariableProxy* proxy = target->AsVariableProxy();
7499 Property* prop = target->AsProperty(); 7479 Property* prop = target->AsProperty();
7500 if (proxy == NULL && prop == NULL) { 7480 if (proxy == NULL && prop == NULL) {
7501 return Bailout(kInvalidLhsInCountOperation); 7481 return Bailout(kInvalidLhsInCountOperation);
7502 } 7482 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
7559 if (instr->HasObservableSideEffects()) { 7539 if (instr->HasObservableSideEffects()) {
7560 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); 7540 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
7561 } 7541 }
7562 break; 7542 break;
7563 } 7543 }
7564 7544
7565 case Variable::LOOKUP: 7545 case Variable::LOOKUP:
7566 return Bailout(kLookupVariableInCountOperation); 7546 return Bailout(kLookupVariableInCountOperation);
7567 } 7547 }
7568 7548
7569 } else { 7549 Drop(returns_original_input ? 2 : 1);
7570 // Argument of the count operation is a property. 7550 return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
7571 ASSERT(prop != NULL);
7572
7573 if (prop->key()->IsPropertyName()) {
7574 // Named property.
7575 if (returns_original_input) Push(graph()->GetConstantUndefined());
7576
7577 CHECK_ALIVE(VisitForValue(prop->obj()));
7578 HValue* object = Top();
7579
7580 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
7581 Handle<Map> map;
7582 HInstruction* load = NULL;
7583 bool monomorphic = prop->IsMonomorphic();
7584 SmallMapList* types = prop->GetReceiverTypes();
7585 if (monomorphic) {
7586 map = types->first();
7587 if (map->is_dictionary_map()) monomorphic = false;
7588 }
7589 if (monomorphic) {
7590 Handle<JSFunction> getter;
7591 Handle<JSObject> holder;
7592 if (LookupGetter(map, name, &getter, &holder)) {
7593 load = BuildCallGetter(object, map, getter, holder);
7594 } else {
7595 load = BuildLoadNamedMonomorphic(object, name, prop, map);
7596 }
7597 } else if (types != NULL && types->length() > 1) {
7598 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name);
7599 }
7600 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
7601 PushAndAdd(load);
7602 if (load->HasObservableSideEffects()) {
7603 Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
7604 }
7605
7606 after = BuildIncrement(returns_original_input, expr);
7607 HValue* result = returns_original_input ? Pop() : after;
7608
7609 return BuildStoreNamed(expr, expr->id(), expr->position(),
7610 expr->AssignmentId(), prop, object, after, result);
7611 } else {
7612 // Keyed property.
7613 if (returns_original_input) Push(graph()->GetConstantUndefined());
7614
7615 CHECK_ALIVE(VisitForValue(prop->obj()));
7616 CHECK_ALIVE(VisitForValue(prop->key()));
7617 HValue* obj = environment()->ExpressionStackAt(1);
7618 HValue* key = environment()->ExpressionStackAt(0);
7619
7620 bool has_side_effects = false;
7621 HValue* load = HandleKeyedElementAccess(
7622 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition,
7623 false, // is_store
7624 &has_side_effects);
7625 Push(load);
7626 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE);
7627
7628 after = BuildIncrement(returns_original_input, expr);
7629 input = environment()->ExpressionStackAt(0);
7630
7631 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
7632 RelocInfo::kNoPosition,
7633 true, // is_store
7634 &has_side_effects);
7635
7636 // Drop the key and the original value from the bailout environment.
7637 // Overwrite the receiver with the result of the operation, and the
7638 // placeholder with the original value if necessary.
7639 Drop(2);
7640 environment()->SetExpressionStackAt(0, after);
7641 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
7642 ASSERT(has_side_effects); // Stores always have side effects.
7643 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
7644 }
7645 } 7551 }
7646 7552
7647 Drop(returns_original_input ? 2 : 1); 7553 // Argument of the count operation is a property.
7648 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); 7554 ASSERT(prop != NULL);
7555 if (returns_original_input) Push(graph()->GetConstantUndefined());
7556
7557 CHECK_ALIVE(VisitForValue(prop->obj()));
7558 HValue* object = Top();
7559
7560 HValue* key = NULL;
7561 if ((!prop->IsStringLength() &&
7562 !prop->IsFunctionPrototype() &&
7563 !prop->key()->IsPropertyName()) ||
7564 prop->IsStringAccess()) {
7565 CHECK_ALIVE(VisitForValue(prop->key()));
7566 key = Top();
7567 }
7568
7569 CHECK_ALIVE(PushLoad(prop, object, key, expr->position()));
7570
7571 after = BuildIncrement(returns_original_input, expr);
7572
7573 if (returns_original_input) {
7574 input = Pop();
7575 // Drop object and key to push it again in the effect context below.
7576 Drop(key == NULL ? 1 : 2);
7577 environment()->SetExpressionStackAt(0, input);
7578 CHECK_ALIVE(BuildStoreForEffect(
7579 expr, prop, expr->id(), expr->AssignmentId(), object, key, after));
7580 return ast_context()->ReturnValue(Pop());
7581 }
7582
7583 environment()->SetExpressionStackAt(0, after);
7584 return BuildStore(expr, prop, expr->id(), expr->AssignmentId());
7649 } 7585 }
7650 7586
7651 7587
7652 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( 7588 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
7653 HValue* string, 7589 HValue* string,
7654 HValue* index) { 7590 HValue* index) {
7655 if (string->IsConstant() && index->IsConstant()) { 7591 if (string->IsConstant() && index->IsConstant()) {
7656 HConstant* c_string = HConstant::cast(string); 7592 HConstant* c_string = HConstant::cast(string);
7657 HConstant* c_index = HConstant::cast(index); 7593 HConstant* c_index = HConstant::cast(index);
7658 if (c_string->HasStringValue() && c_index->HasNumberValue()) { 7594 if (c_string->HasStringValue() && c_index->HasNumberValue()) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
7761 7697
7762 if (expr->op() != Token::ADD || 7698 if (expr->op() != Token::ADD ||
7763 (left->type().IsNonString() && right->type().IsNonString())) { 7699 (left->type().IsNonString() && right->type().IsNonString())) {
7764 // For addition we can only truncate the arguments to number if we can 7700 // For addition we can only truncate the arguments to number if we can
7765 // prove that we will not end up in string concatenation mode. 7701 // prove that we will not end up in string concatenation mode.
7766 left = TruncateToNumber(left, &left_type); 7702 left = TruncateToNumber(left, &left_type);
7767 right = TruncateToNumber(right, &right_type); 7703 right = TruncateToNumber(right, &right_type);
7768 } 7704 }
7769 7705
7770 if (left_type->Is(Type::None())) { 7706 if (left_type->Is(Type::None())) {
7771 Add<HDeoptimize>("Insufficient type feedback for left side", 7707 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
7772 Deoptimizer::SOFT); 7708 Deoptimizer::SOFT);
7773 // TODO(rossberg): we should be able to get rid of non-continuous defaults. 7709 // TODO(rossberg): we should be able to get rid of non-continuous defaults.
7774 left_type = handle(Type::Any(), isolate()); 7710 left_type = handle(Type::Any(), isolate());
7775 } 7711 }
7776 if (right_type->Is(Type::None())) { 7712 if (right_type->Is(Type::None())) {
7777 Add<HDeoptimize>("Insufficient type feedback for right side", 7713 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
7778 Deoptimizer::SOFT); 7714 Deoptimizer::SOFT);
7779 right_type = handle(Type::Any(), isolate()); 7715 right_type = handle(Type::Any(), isolate());
7780 } 7716 }
7781 HInstruction* instr = NULL; 7717 HInstruction* instr = NULL;
7782 switch (expr->op()) { 7718 switch (expr->op()) {
7783 case Token::ADD: 7719 case Token::ADD:
7784 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { 7720 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) {
7785 BuildCheckHeapObject(left); 7721 BuildCheckHeapObject(left);
7786 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); 7722 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
7787 BuildCheckHeapObject(right); 7723 BuildCheckHeapObject(right);
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
8000 Expression* sub_expr, 7936 Expression* sub_expr,
8001 Handle<String> check) { 7937 Handle<String> check) {
8002 CHECK_ALIVE(VisitForTypeOf(sub_expr)); 7938 CHECK_ALIVE(VisitForTypeOf(sub_expr));
8003 HValue* value = Pop(); 7939 HValue* value = Pop();
8004 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 7940 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
8005 instr->set_position(expr->position()); 7941 instr->set_position(expr->position());
8006 return ast_context()->ReturnControl(instr, expr->id()); 7942 return ast_context()->ReturnControl(instr, expr->id());
8007 } 7943 }
8008 7944
8009 7945
8010 static bool IsLiteralCompareBool(HValue* left, 7946 static bool IsLiteralCompareBool(Isolate* isolate,
7947 HValue* left,
8011 Token::Value op, 7948 Token::Value op,
8012 HValue* right) { 7949 HValue* right) {
8013 return op == Token::EQ_STRICT && 7950 return op == Token::EQ_STRICT &&
8014 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || 7951 ((left->IsConstant() &&
8015 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); 7952 HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
7953 (right->IsConstant() &&
7954 HConstant::cast(right)->handle(isolate)->IsBoolean()));
8016 } 7955 }
8017 7956
8018 7957
8019 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 7958 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
8020 ASSERT(!HasStackOverflow()); 7959 ASSERT(!HasStackOverflow());
8021 ASSERT(current_block() != NULL); 7960 ASSERT(current_block() != NULL);
8022 ASSERT(current_block()->HasPredecessor()); 7961 ASSERT(current_block()->HasPredecessor());
8023 7962
8024 // Check for a few fast cases. The AST visiting behavior must be in sync 7963 // Check for a few fast cases. The AST visiting behavior must be in sync
8025 // with the full codegen: We don't push both left and right values onto 7964 // with the full codegen: We don't push both left and right values onto
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
8057 Representation right_rep = Representation::FromType(right_type); 7996 Representation right_rep = Representation::FromType(right_type);
8058 7997
8059 CHECK_ALIVE(VisitForValue(expr->left())); 7998 CHECK_ALIVE(VisitForValue(expr->left()));
8060 CHECK_ALIVE(VisitForValue(expr->right())); 7999 CHECK_ALIVE(VisitForValue(expr->right()));
8061 8000
8062 HValue* context = environment()->context(); 8001 HValue* context = environment()->context();
8063 HValue* right = Pop(); 8002 HValue* right = Pop();
8064 HValue* left = Pop(); 8003 HValue* left = Pop();
8065 Token::Value op = expr->op(); 8004 Token::Value op = expr->op();
8066 8005
8067 if (IsLiteralCompareBool(left, op, right)) { 8006 if (IsLiteralCompareBool(isolate(), left, op, right)) {
8068 HCompareObjectEqAndBranch* result = 8007 HCompareObjectEqAndBranch* result =
8069 New<HCompareObjectEqAndBranch>(left, right); 8008 New<HCompareObjectEqAndBranch>(left, right);
8070 result->set_position(expr->position()); 8009 result->set_position(expr->position());
8071 return ast_context()->ReturnControl(result, expr->id()); 8010 return ast_context()->ReturnControl(result, expr->id());
8072 } 8011 }
8073 8012
8074 if (op == Token::INSTANCEOF) { 8013 if (op == Token::INSTANCEOF) {
8075 // Check to see if the rhs of the instanceof is a global function not 8014 // Check to see if the rhs of the instanceof is a global function not
8076 // residing in new space. If it is we assume that the function will stay the 8015 // residing in new space. If it is we assume that the function will stay the
8077 // same. 8016 // same.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
8118 // TODO(olivf) InvokeFunction produces a check for the parameter count, 8057 // TODO(olivf) InvokeFunction produces a check for the parameter count,
8119 // even though we are certain to pass the correct number of arguments here. 8058 // even though we are certain to pass the correct number of arguments here.
8120 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); 8059 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2);
8121 result->set_position(expr->position()); 8060 result->set_position(expr->position());
8122 return ast_context()->ReturnInstruction(result, expr->id()); 8061 return ast_context()->ReturnInstruction(result, expr->id());
8123 } 8062 }
8124 8063
8125 // Cases handled below depend on collected type feedback. They should 8064 // Cases handled below depend on collected type feedback. They should
8126 // soft deoptimize when there is no type feedback. 8065 // soft deoptimize when there is no type feedback.
8127 if (combined_type->Is(Type::None())) { 8066 if (combined_type->Is(Type::None())) {
8128 Add<HDeoptimize>("insufficient type feedback for combined type", 8067 Add<HDeoptimize>("Insufficient type feedback for combined type "
8068 "of binary operation",
8129 Deoptimizer::SOFT); 8069 Deoptimizer::SOFT);
8130 combined_type = left_type = right_type = handle(Type::Any(), isolate()); 8070 combined_type = left_type = right_type = handle(Type::Any(), isolate());
8131 } 8071 }
8132 8072
8133 if (combined_type->Is(Type::Receiver())) { 8073 if (combined_type->Is(Type::Receiver())) {
8134 switch (op) { 8074 switch (op) {
8135 case Token::EQ: 8075 case Token::EQ:
8136 case Token::EQ_STRICT: { 8076 case Token::EQ_STRICT: {
8137 // Can we get away with map check and not instance type check? 8077 // Can we get away with map check and not instance type check?
8138 if (combined_type->IsClass()) { 8078 if (combined_type->IsClass()) {
(...skipping 1602 matching lines...) Expand 10 before | Expand all | Expand 10 after
9741 if (ShouldProduceTraceOutput()) { 9681 if (ShouldProduceTraceOutput()) {
9742 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9682 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9743 } 9683 }
9744 9684
9745 #ifdef DEBUG 9685 #ifdef DEBUG
9746 graph_->Verify(false); // No full verify. 9686 graph_->Verify(false); // No full verify.
9747 #endif 9687 #endif
9748 } 9688 }
9749 9689
9750 } } // namespace v8::internal 9690 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-escape-analysis.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698