OLD | NEW |
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 4536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4547 Handle<Name> name, | 4547 Handle<Name> name, |
4548 LookupResult* lookup) { | 4548 LookupResult* lookup) { |
4549 if (!CanInlinePropertyAccess(*map)) return false; | 4549 if (!CanInlinePropertyAccess(*map)) return false; |
4550 map->LookupDescriptor(NULL, *name, lookup); | 4550 map->LookupDescriptor(NULL, *name, lookup); |
4551 if (lookup->IsFound()) return false; | 4551 if (lookup->IsFound()) return false; |
4552 return true; | 4552 return true; |
4553 } | 4553 } |
4554 | 4554 |
4555 | 4555 |
4556 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( | 4556 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
4557 Property* expr, | |
4558 HValue* object, | 4557 HValue* object, |
4559 SmallMapList* types, | 4558 SmallMapList* types, |
4560 Handle<String> name) { | 4559 Handle<String> name) { |
4561 // Use monomorphic load if property lookup results in the same field index | 4560 // Use monomorphic load if property lookup results in the same field index |
4562 // for all maps. Requires special map check on the set of all handled maps. | 4561 // for all maps. Requires special map check on the set of all handled maps. |
4563 if (types->length() > kMaxLoadPolymorphism) return NULL; | 4562 if (types->length() > kMaxLoadPolymorphism) return NULL; |
4564 | 4563 |
4565 LookupResult lookup(isolate()); | 4564 LookupResult lookup(isolate()); |
4566 int count; | 4565 int count; |
4567 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 4566 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4648 map->LookupDescriptor(NULL, *name, &lookup); | 4647 map->LookupDescriptor(NULL, *name, &lookup); |
4649 if (lookup.IsFound()) return false; | 4648 if (lookup.IsFound()) return false; |
4650 if (!lookup.IsCacheable()) return false; | 4649 if (!lookup.IsCacheable()) return false; |
4651 current = JSObject::cast(current)->GetPrototype(); | 4650 current = JSObject::cast(current)->GetPrototype(); |
4652 } | 4651 } |
4653 return true; | 4652 return true; |
4654 } | 4653 } |
4655 | 4654 |
4656 | 4655 |
4657 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4656 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
4658 Property* expr, | 4657 int position, |
| 4658 BailoutId return_id, |
4659 HValue* object, | 4659 HValue* object, |
4660 SmallMapList* types, | 4660 SmallMapList* types, |
4661 Handle<String> name) { | 4661 Handle<String> name) { |
4662 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 4662 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(object, types, name); |
4663 expr, object, types, name); | |
4664 if (instr != NULL) { | 4663 if (instr != NULL) { |
4665 instr->set_position(expr->position()); | 4664 instr->set_position(position); |
4666 return ast_context()->ReturnInstruction(instr, expr->id()); | 4665 return ast_context()->ReturnInstruction(instr, return_id); |
4667 } | 4666 } |
4668 | 4667 |
4669 // Something did not match; must use a polymorphic load. | 4668 // Something did not match; must use a polymorphic load. |
4670 int count = 0; | 4669 int count = 0; |
4671 HBasicBlock* join = NULL; | 4670 HBasicBlock* join = NULL; |
4672 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 4671 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
4673 Handle<Map> map = types->at(i); | 4672 Handle<Map> map = types->at(i); |
4674 LookupResult lookup(isolate()); | 4673 LookupResult lookup(isolate()); |
4675 if (ComputeLoadStoreField(map, name, &lookup, false) || | 4674 if (ComputeLoadStoreField(map, name, &lookup, false) || |
4676 (lookup.IsCacheable() && | 4675 (lookup.IsCacheable() && |
(...skipping 11 matching lines...) Expand all Loading... |
4688 HCompareMap* compare = | 4687 HCompareMap* compare = |
4689 new(zone()) HCompareMap(object, map, if_true, if_false); | 4688 new(zone()) HCompareMap(object, map, if_true, if_false); |
4690 current_block()->Finish(compare); | 4689 current_block()->Finish(compare); |
4691 | 4690 |
4692 set_current_block(if_true); | 4691 set_current_block(if_true); |
4693 | 4692 |
4694 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. | 4693 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. |
4695 if (lookup.IsField()) { | 4694 if (lookup.IsField()) { |
4696 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); | 4695 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); |
4697 HLoadNamedField* load = BuildLoadNamedField(compare, access); | 4696 HLoadNamedField* load = BuildLoadNamedField(compare, access); |
4698 load->set_position(expr->position()); | 4697 load->set_position(position); |
4699 AddInstruction(load); | 4698 AddInstruction(load); |
4700 if (!ast_context()->IsEffect()) Push(load); | 4699 if (!ast_context()->IsEffect()) Push(load); |
4701 } else if (lookup.IsConstant()) { | 4700 } else if (lookup.IsConstant()) { |
4702 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 4701 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
4703 HConstant* hconstant = Add<HConstant>(constant); | 4702 HConstant* hconstant = Add<HConstant>(constant); |
4704 if (!ast_context()->IsEffect()) Push(hconstant); | 4703 if (!ast_context()->IsEffect()) Push(hconstant); |
4705 } else { | 4704 } else { |
4706 ASSERT(!lookup.IsFound()); | 4705 ASSERT(!lookup.IsFound()); |
4707 if (map->prototype()->IsJSObject()) { | 4706 if (map->prototype()->IsJSObject()) { |
4708 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 4707 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
(...skipping 10 matching lines...) Expand all Loading... |
4719 set_current_block(if_false); | 4718 set_current_block(if_false); |
4720 } | 4719 } |
4721 } | 4720 } |
4722 | 4721 |
4723 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4722 // 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 | 4723 // know about and do not want to handle ones we've never seen. Otherwise |
4725 // use a generic IC. | 4724 // use a generic IC. |
4726 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4725 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
4727 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); | 4726 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); |
4728 } else { | 4727 } else { |
4729 HInstruction* load = BuildLoadNamedGeneric(object, name, expr); | 4728 HValue* context = environment()->context(); |
4730 load->set_position(expr->position()); | 4729 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); |
| 4730 load->set_position(position); |
4731 AddInstruction(load); | 4731 AddInstruction(load); |
4732 if (!ast_context()->IsEffect()) Push(load); | 4732 if (!ast_context()->IsEffect()) Push(load); |
4733 | 4733 |
4734 if (join != NULL) { | 4734 if (join != NULL) { |
4735 current_block()->Goto(join); | 4735 current_block()->Goto(join); |
4736 } else { | 4736 } else { |
4737 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 4737 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
4738 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4738 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
4739 return; | 4739 return; |
4740 } | 4740 } |
4741 } | 4741 } |
4742 | 4742 |
4743 ASSERT(join != NULL); | 4743 ASSERT(join != NULL); |
4744 join->SetJoinId(expr->id()); | 4744 join->SetJoinId(return_id); |
4745 set_current_block(join); | 4745 set_current_block(join); |
4746 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 4746 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
4747 } | 4747 } |
4748 | 4748 |
4749 | 4749 |
4750 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 4750 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
4751 int position, | 4751 int position, |
4752 BailoutId assignment_id, | 4752 BailoutId assignment_id, |
4753 HValue* object, | 4753 HValue* object, |
4754 HValue* store_value, | 4754 HValue* store_value, |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5123 case Variable::LOOKUP: | 5123 case Variable::LOOKUP: |
5124 return Bailout(kCompoundAssignmentToLookupSlot); | 5124 return Bailout(kCompoundAssignmentToLookupSlot); |
5125 } | 5125 } |
5126 return ast_context()->ReturnValue(Pop()); | 5126 return ast_context()->ReturnValue(Pop()); |
5127 | 5127 |
5128 } else if (prop != NULL) { | 5128 } else if (prop != NULL) { |
5129 if (prop->key()->IsPropertyName()) { | 5129 if (prop->key()->IsPropertyName()) { |
5130 // Named property. | 5130 // Named property. |
5131 CHECK_ALIVE(VisitForValue(prop->obj())); | 5131 CHECK_ALIVE(VisitForValue(prop->obj())); |
5132 HValue* object = Top(); | 5132 HValue* object = Top(); |
5133 | 5133 PushLoad(prop, object, expr->position(), expr->id(), prop->LoadId()); |
5134 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
5135 Handle<Map> map; | |
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 monomorphic = CanInlinePropertyAccess(*map); | |
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 | 5134 |
5162 CHECK_ALIVE(VisitForValue(expr->value())); | 5135 CHECK_ALIVE(VisitForValue(expr->value())); |
5163 HValue* right = Pop(); | 5136 HValue* right = Pop(); |
5164 HValue* left = Pop(); | 5137 HValue* left = Pop(); |
5165 | 5138 |
5166 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5139 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5167 PushAndAdd(instr); | 5140 PushAndAdd(instr); |
5168 if (instr->HasObservableSideEffects()) { | 5141 if (instr->HasObservableSideEffects()) { |
5169 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); | 5142 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
5170 } | 5143 } |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5411 Handle<JSObject> holder) { | 5384 Handle<JSObject> holder) { |
5412 AddCheckConstantFunction(holder, object, map); | 5385 AddCheckConstantFunction(holder, object, map); |
5413 Add<HPushArgument>(object); | 5386 Add<HPushArgument>(object); |
5414 return new(zone()) HCallConstantFunction(getter, 1); | 5387 return new(zone()) HCallConstantFunction(getter, 1); |
5415 } | 5388 } |
5416 | 5389 |
5417 | 5390 |
5418 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( | 5391 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
5419 HValue* object, | 5392 HValue* object, |
5420 Handle<String> name, | 5393 Handle<String> name, |
5421 Property* expr, | |
5422 Handle<Map> map) { | 5394 Handle<Map> map) { |
5423 // Handle a load from a known field. | 5395 // Handle a load from a known field. |
5424 ASSERT(!map->is_dictionary_map()); | 5396 ASSERT(!map->is_dictionary_map()); |
5425 | 5397 |
5426 // Handle access to various length properties | 5398 // Handle access to various length properties |
5427 if (name->Equals(isolate()->heap()->length_string())) { | 5399 if (name->Equals(isolate()->heap()->length_string())) { |
5428 if (map->instance_type() == JS_ARRAY_TYPE) { | 5400 if (map->instance_type() == JS_ARRAY_TYPE) { |
5429 HCheckMaps* checked_object = AddCheckMap(object, map); | 5401 HCheckMaps* checked_object = AddCheckMap(object, map); |
5430 return New<HLoadNamedField>( | 5402 return New<HLoadNamedField>( |
5431 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); | 5403 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5464 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5436 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5465 Handle<JSObject> holder(lookup.holder()); | 5437 Handle<JSObject> holder(lookup.holder()); |
5466 Handle<Map> holder_map(holder->map()); | 5438 Handle<Map> holder_map(holder->map()); |
5467 AddCheckMap(object, map); | 5439 AddCheckMap(object, map); |
5468 BuildCheckPrototypeMaps(prototype, holder); | 5440 BuildCheckPrototypeMaps(prototype, holder); |
5469 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); | 5441 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
5470 return New<HConstant>(constant); | 5442 return New<HConstant>(constant); |
5471 } | 5443 } |
5472 | 5444 |
5473 // No luck, do a generic load. | 5445 // No luck, do a generic load. |
5474 return BuildLoadNamedGeneric(object, name, expr); | 5446 HValue* context = environment()->context(); |
| 5447 return new(zone()) HLoadNamedGeneric(context, object, name); |
5475 } | 5448 } |
5476 | 5449 |
5477 | 5450 |
5478 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5451 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
5479 HValue* key) { | 5452 HValue* key) { |
5480 HValue* context = environment()->context(); | 5453 HValue* context = environment()->context(); |
5481 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5454 return new(zone()) HLoadKeyedGeneric(context, object, key); |
5482 } | 5455 } |
5483 | 5456 |
5484 | 5457 |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5851 HInstruction* length = Add<HConstant>(argument_count); | 5824 HInstruction* length = Add<HConstant>(argument_count); |
5852 HInstruction* checked_key = Add<HBoundsCheck>(key, length); | 5825 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
5853 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 5826 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
5854 } | 5827 } |
5855 } | 5828 } |
5856 ast_context()->ReturnInstruction(result, expr->id()); | 5829 ast_context()->ReturnInstruction(result, expr->id()); |
5857 return true; | 5830 return true; |
5858 } | 5831 } |
5859 | 5832 |
5860 | 5833 |
5861 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 5834 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
5862 ASSERT(!HasStackOverflow()); | 5835 HValue* object, |
5863 ASSERT(current_block() != NULL); | 5836 int position, |
5864 ASSERT(current_block()->HasPredecessor()); | 5837 BailoutId ast_id, |
| 5838 BailoutId return_id) { |
| 5839 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
| 5840 Push(object); |
| 5841 BuildLoad(expr, position, ast_id, return_id); |
| 5842 } |
5865 | 5843 |
5866 if (TryArgumentsAccess(expr)) return; | |
5867 | 5844 |
5868 CHECK_ALIVE(VisitForValue(expr->obj())); | 5845 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
5869 | 5846 int position, |
| 5847 BailoutId ast_id, |
| 5848 BailoutId return_id) { |
5870 HInstruction* instr = NULL; | 5849 HInstruction* instr = NULL; |
5871 if (expr->IsStringLength()) { | 5850 if (expr->IsStringLength()) { |
5872 HValue* string = Pop(); | 5851 HValue* string = Pop(); |
5873 BuildCheckHeapObject(string); | 5852 BuildCheckHeapObject(string); |
5874 HInstruction* checkstring = | 5853 HInstruction* checkstring = |
5875 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 5854 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
5876 instr = BuildLoadStringLength(string, checkstring); | 5855 instr = BuildLoadStringLength(string, checkstring); |
5877 } else if (expr->IsStringAccess()) { | 5856 } else if (expr->IsStringAccess()) { |
5878 CHECK_ALIVE(VisitForValue(expr->key())); | 5857 CHECK_ALIVE(VisitForValue(expr->key())); |
5879 HValue* index = Pop(); | 5858 HValue* index = Pop(); |
(...skipping 21 matching lines...) Expand all Loading... |
5901 monomorphic = CanInlinePropertyAccess(*map); | 5880 monomorphic = CanInlinePropertyAccess(*map); |
5902 } else if (object->HasMonomorphicJSObjectType()) { | 5881 } else if (object->HasMonomorphicJSObjectType()) { |
5903 map = object->GetMonomorphicJSObjectMap(); | 5882 map = object->GetMonomorphicJSObjectMap(); |
5904 monomorphic = CanInlinePropertyAccess(*map); | 5883 monomorphic = CanInlinePropertyAccess(*map); |
5905 } | 5884 } |
5906 if (monomorphic) { | 5885 if (monomorphic) { |
5907 Handle<JSFunction> getter; | 5886 Handle<JSFunction> getter; |
5908 Handle<JSObject> holder; | 5887 Handle<JSObject> holder; |
5909 if (LookupGetter(map, name, &getter, &holder)) { | 5888 if (LookupGetter(map, name, &getter, &holder)) { |
5910 AddCheckConstantFunction(holder, Top(), map); | 5889 AddCheckConstantFunction(holder, Top(), map); |
5911 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; | 5890 if (FLAG_inline_accessors && TryInlineGetter(getter, return_id)) return; |
5912 Add<HPushArgument>(Pop()); | 5891 Add<HPushArgument>(Pop()); |
5913 instr = new(zone()) HCallConstantFunction(getter, 1); | 5892 instr = new(zone()) HCallConstantFunction(getter, 1); |
5914 } else { | 5893 } else { |
5915 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); | 5894 instr = BuildLoadNamedMonomorphic(Pop(), name, map); |
5916 } | 5895 } |
5917 } else if (types != NULL && types->length() > 1) { | 5896 } else if (types != NULL && types->length() > 1) { |
5918 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); | 5897 return HandlePolymorphicLoadNamedField( |
| 5898 position, return_id, Pop(), types, name); |
5919 } else { | 5899 } else { |
5920 instr = BuildLoadNamedGeneric(Pop(), name, expr); | 5900 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
5921 } | 5901 } |
5922 | 5902 |
5923 } else { | 5903 } else { |
5924 CHECK_ALIVE(VisitForValue(expr->key())); | 5904 CHECK_ALIVE(VisitForValue(expr->key())); |
5925 | 5905 |
5926 HValue* key = Pop(); | 5906 HValue* key = Pop(); |
5927 HValue* obj = Pop(); | 5907 HValue* obj = Pop(); |
5928 | 5908 |
5929 bool has_side_effects = false; | 5909 bool has_side_effects = false; |
5930 HValue* load = HandleKeyedElementAccess( | 5910 HValue* load = HandleKeyedElementAccess( |
5931 obj, key, NULL, expr, expr->id(), expr->position(), | 5911 obj, key, NULL, expr, return_id, position, |
5932 false, // is_store | 5912 false, // is_store |
5933 &has_side_effects); | 5913 &has_side_effects); |
5934 if (has_side_effects) { | 5914 if (has_side_effects) { |
5935 if (ast_context()->IsEffect()) { | 5915 if (ast_context()->IsEffect()) { |
5936 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 5916 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
5937 } else { | 5917 } else { |
5938 Push(load); | 5918 Push(load); |
5939 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 5919 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
5940 Drop(1); | 5920 Drop(1); |
5941 } | 5921 } |
5942 } | 5922 } |
5943 return ast_context()->ReturnValue(load); | 5923 return ast_context()->ReturnValue(load); |
5944 } | 5924 } |
5945 instr->set_position(expr->position()); | 5925 instr->set_position(position); |
5946 return ast_context()->ReturnInstruction(instr, expr->id()); | 5926 return ast_context()->ReturnInstruction(instr, return_id); |
5947 } | 5927 } |
5948 | 5928 |
5949 | 5929 |
| 5930 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
| 5931 ASSERT(!HasStackOverflow()); |
| 5932 ASSERT(current_block() != NULL); |
| 5933 ASSERT(current_block()->HasPredecessor()); |
| 5934 |
| 5935 if (TryArgumentsAccess(expr)) return; |
| 5936 |
| 5937 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 5938 BuildLoad(expr, expr->position(), expr->id(), expr->id()); |
| 5939 } |
| 5940 |
| 5941 |
5950 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 5942 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
5951 CompilationInfo* info) { | 5943 CompilationInfo* info) { |
5952 HConstant* constant_value = New<HConstant>(constant); | 5944 HConstant* constant_value = New<HConstant>(constant); |
5953 | 5945 |
5954 if (constant->map()->CanOmitMapChecks()) { | 5946 if (constant->map()->CanOmitMapChecks()) { |
5955 constant->map()->AddDependentCompilationInfo( | 5947 constant->map()->AddDependentCompilationInfo( |
5956 DependentCode::kPrototypeCheckGroup, info); | 5948 DependentCode::kPrototypeCheckGroup, info); |
5957 return constant_value; | 5949 return constant_value; |
5958 } | 5950 } |
5959 | 5951 |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6613 expr->target(), | 6605 expr->target(), |
6614 expr->arguments()->length(), | 6606 expr->arguments()->length(), |
6615 implicit_return_value, | 6607 implicit_return_value, |
6616 expr->id(), | 6608 expr->id(), |
6617 expr->ReturnId(), | 6609 expr->ReturnId(), |
6618 CONSTRUCT_CALL_RETURN); | 6610 CONSTRUCT_CALL_RETURN); |
6619 } | 6611 } |
6620 | 6612 |
6621 | 6613 |
6622 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, | 6614 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter, |
6623 Property* prop) { | 6615 BailoutId return_id) { |
6624 return TryInline(CALL_AS_METHOD, | 6616 return TryInline(CALL_AS_METHOD, |
6625 getter, | 6617 getter, |
6626 0, | 6618 0, |
6627 NULL, | 6619 NULL, |
6628 prop->id(), | 6620 return_id, |
6629 prop->LoadId(), | 6621 return_id, |
6630 GETTER_CALL_RETURN); | 6622 GETTER_CALL_RETURN); |
6631 } | 6623 } |
6632 | 6624 |
6633 | 6625 |
6634 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 6626 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
6635 BailoutId id, | 6627 BailoutId id, |
6636 BailoutId assignment_id, | 6628 BailoutId assignment_id, |
6637 HValue* implicit_return_value) { | 6629 HValue* implicit_return_value) { |
6638 return TryInline(CALL_AS_METHOD, | 6630 return TryInline(CALL_AS_METHOD, |
6639 setter, | 6631 setter, |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7569 } else { | 7561 } else { |
7570 // Argument of the count operation is a property. | 7562 // Argument of the count operation is a property. |
7571 ASSERT(prop != NULL); | 7563 ASSERT(prop != NULL); |
7572 | 7564 |
7573 if (prop->key()->IsPropertyName()) { | 7565 if (prop->key()->IsPropertyName()) { |
7574 // Named property. | 7566 // Named property. |
7575 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7567 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
7576 | 7568 |
7577 CHECK_ALIVE(VisitForValue(prop->obj())); | 7569 CHECK_ALIVE(VisitForValue(prop->obj())); |
7578 HValue* object = Top(); | 7570 HValue* object = Top(); |
7579 | 7571 PushLoad(prop, object, expr->position(), expr->id(), prop->LoadId()); |
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 monomorphic = CanInlinePropertyAccess(*map); | |
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 | 7572 |
7606 after = BuildIncrement(returns_original_input, expr); | 7573 after = BuildIncrement(returns_original_input, expr); |
7607 HValue* result = returns_original_input ? Pop() : after; | 7574 HValue* result = returns_original_input ? Pop() : after; |
7608 | 7575 |
7609 return BuildStoreNamed(expr, expr->id(), expr->position(), | 7576 return BuildStoreNamed(expr, expr->id(), expr->position(), |
7610 expr->AssignmentId(), prop, object, after, result); | 7577 expr->AssignmentId(), prop, object, after, result); |
7611 } else { | 7578 } else { |
7612 // Keyed property. | 7579 // Keyed property. |
7613 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7580 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
7614 | 7581 |
(...skipping 2126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9741 if (ShouldProduceTraceOutput()) { | 9708 if (ShouldProduceTraceOutput()) { |
9742 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9709 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9743 } | 9710 } |
9744 | 9711 |
9745 #ifdef DEBUG | 9712 #ifdef DEBUG |
9746 graph_->Verify(false); // No full verify. | 9713 graph_->Verify(false); // No full verify. |
9747 #endif | 9714 #endif |
9748 } | 9715 } |
9749 | 9716 |
9750 } } // namespace v8::internal | 9717 } } // namespace v8::internal |
OLD | NEW |