| 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 |