OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3864 UNREACHABLE(); | 3864 UNREACHABLE(); |
3865 break; | 3865 break; |
3866 } | 3866 } |
3867 | 3867 |
3868 AddSimulate(expr->GetIdForElement(i)); | 3868 AddSimulate(expr->GetIdForElement(i)); |
3869 } | 3869 } |
3870 return ast_context()->ReturnValue(Pop()); | 3870 return ast_context()->ReturnValue(Pop()); |
3871 } | 3871 } |
3872 | 3872 |
3873 | 3873 |
3874 // Sets the lookup result and returns true if the store can be inlined. | 3874 // Sets the lookup result and returns true if the load/store can be inlined. |
3875 static bool ComputeStoredField(Handle<Map> type, | 3875 static bool ComputeLoadStoreField(Handle<Map> type, |
3876 Handle<String> name, | 3876 Handle<String> name, |
3877 LookupResult* lookup) { | 3877 LookupResult* lookup, |
| 3878 bool is_store) { |
3878 type->LookupInDescriptors(NULL, *name, lookup); | 3879 type->LookupInDescriptors(NULL, *name, lookup); |
3879 if (!lookup->IsFound()) return false; | 3880 if (!lookup->IsFound()) return false; |
3880 if (lookup->type() == FIELD) return true; | 3881 if (lookup->type() == FIELD) return true; |
3881 return (lookup->type() == MAP_TRANSITION) && | 3882 return is_store && (lookup->type() == MAP_TRANSITION) && |
3882 (type->unused_property_fields() > 0); | 3883 (type->unused_property_fields() > 0); |
3883 } | 3884 } |
3884 | 3885 |
3885 | 3886 |
3886 static int ComputeStoredFieldIndex(Handle<Map> type, | 3887 static int ComputeLoadStoreFieldIndex(Handle<Map> type, |
3887 Handle<String> name, | 3888 Handle<String> name, |
3888 LookupResult* lookup) { | 3889 LookupResult* lookup) { |
3889 ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION); | 3890 ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION); |
3890 if (lookup->type() == FIELD) { | 3891 if (lookup->type() == FIELD) { |
3891 return lookup->GetLocalFieldIndexFromMap(*type); | 3892 return lookup->GetLocalFieldIndexFromMap(*type); |
3892 } else { | 3893 } else { |
3893 Map* transition = lookup->GetTransitionMapFromMap(*type); | 3894 Map* transition = lookup->GetTransitionMapFromMap(*type); |
3894 return transition->PropertyIndexFor(*name) - type->inobject_properties(); | 3895 return transition->PropertyIndexFor(*name) - type->inobject_properties(); |
3895 } | 3896 } |
3896 } | 3897 } |
3897 | 3898 |
3898 | 3899 |
3899 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, | 3900 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
3900 Handle<String> name, | 3901 Handle<String> name, |
3901 HValue* value, | 3902 HValue* value, |
3902 Handle<Map> type, | 3903 Handle<Map> type, |
3903 LookupResult* lookup, | 3904 LookupResult* lookup, |
3904 bool smi_and_map_check) { | 3905 bool smi_and_map_check) { |
3905 if (smi_and_map_check) { | 3906 if (smi_and_map_check) { |
3906 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3907 AddInstruction(new(zone()) HCheckNonSmi(object)); |
3907 AddInstruction(new(zone()) HCheckMap(object, type, NULL, | 3908 AddInstruction(HCheckMaps::NewWithTransitions(object, type)); |
3908 ALLOW_ELEMENT_TRANSITION_MAPS)); | |
3909 } | 3909 } |
3910 | 3910 |
3911 int index = ComputeStoredFieldIndex(type, name, lookup); | 3911 int index = ComputeLoadStoreFieldIndex(type, name, lookup); |
3912 bool is_in_object = index < 0; | 3912 bool is_in_object = index < 0; |
3913 int offset = index * kPointerSize; | 3913 int offset = index * kPointerSize; |
3914 if (index < 0) { | 3914 if (index < 0) { |
3915 // Negative property indices are in-object properties, indexed | 3915 // Negative property indices are in-object properties, indexed |
3916 // from the end of the fixed part of the object. | 3916 // from the end of the fixed part of the object. |
3917 offset += type->instance_size(); | 3917 offset += type->instance_size(); |
3918 } else { | 3918 } else { |
3919 offset += FixedArray::kHeaderSize; | 3919 offset += FixedArray::kHeaderSize; |
3920 } | 3920 } |
3921 HStoreNamedField* instr = | 3921 HStoreNamedField* instr = |
(...skipping 28 matching lines...) Expand all Loading... |
3950 Property* prop = (expr->AsProperty() != NULL) | 3950 Property* prop = (expr->AsProperty() != NULL) |
3951 ? expr->AsProperty() | 3951 ? expr->AsProperty() |
3952 : expr->AsAssignment()->target()->AsProperty(); | 3952 : expr->AsAssignment()->target()->AsProperty(); |
3953 Literal* key = prop->key()->AsLiteral(); | 3953 Literal* key = prop->key()->AsLiteral(); |
3954 Handle<String> name = Handle<String>::cast(key->handle()); | 3954 Handle<String> name = Handle<String>::cast(key->handle()); |
3955 ASSERT(!name.is_null()); | 3955 ASSERT(!name.is_null()); |
3956 | 3956 |
3957 LookupResult lookup(isolate()); | 3957 LookupResult lookup(isolate()); |
3958 SmallMapList* types = expr->GetReceiverTypes(); | 3958 SmallMapList* types = expr->GetReceiverTypes(); |
3959 bool is_monomorphic = expr->IsMonomorphic() && | 3959 bool is_monomorphic = expr->IsMonomorphic() && |
3960 ComputeStoredField(types->first(), name, &lookup); | 3960 ComputeLoadStoreField(types->first(), name, &lookup, true); |
3961 | 3961 |
3962 return is_monomorphic | 3962 return is_monomorphic |
3963 ? BuildStoreNamedField(object, name, value, types->first(), &lookup, | 3963 ? BuildStoreNamedField(object, name, value, types->first(), &lookup, |
3964 true) // Needs smi and map check. | 3964 true) // Needs smi and map check. |
3965 : BuildStoreNamedGeneric(object, name, value); | 3965 : BuildStoreNamedGeneric(object, name, value); |
3966 } | 3966 } |
3967 | 3967 |
3968 | 3968 |
| 3969 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 3970 HValue* object, |
| 3971 SmallMapList* types, |
| 3972 Handle<String> name) { |
| 3973 int count = 0; |
| 3974 int previous_field_index = 0; |
| 3975 bool is_monomorphic_field = true; |
| 3976 Handle<Map> map; |
| 3977 LookupResult lookup(isolate()); |
| 3978 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| 3979 map = types->at(i); |
| 3980 if (ComputeLoadStoreField(map, name, &lookup, false)) { |
| 3981 int index = ComputeLoadStoreFieldIndex(map, name, &lookup); |
| 3982 if (count == 0) { |
| 3983 previous_field_index = index; |
| 3984 } else if (is_monomorphic_field) { |
| 3985 is_monomorphic_field = (index == previous_field_index); |
| 3986 } |
| 3987 ++count; |
| 3988 } |
| 3989 } |
| 3990 |
| 3991 // Use monomorphic load if property lookup results in the same field index |
| 3992 // for all maps. Requires special map check on the set of all handled maps. |
| 3993 HInstruction* instr; |
| 3994 if (count == types->length() && is_monomorphic_field) { |
| 3995 AddInstruction(new(zone()) HCheckMaps(object, types)); |
| 3996 instr = BuildLoadNamedField(object, expr, map, &lookup, false); |
| 3997 } else { |
| 3998 HValue* context = environment()->LookupContext(); |
| 3999 instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
| 4000 object, |
| 4001 types, |
| 4002 name); |
| 4003 } |
| 4004 |
| 4005 instr->set_position(expr->position()); |
| 4006 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4007 } |
| 4008 |
| 4009 |
3969 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, | 4010 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
3970 HValue* object, | 4011 HValue* object, |
3971 HValue* value, | 4012 HValue* value, |
3972 SmallMapList* types, | 4013 SmallMapList* types, |
3973 Handle<String> name) { | 4014 Handle<String> name) { |
3974 // TODO(ager): We should recognize when the prototype chains for different | 4015 // TODO(ager): We should recognize when the prototype chains for different |
3975 // maps are identical. In that case we can avoid repeatedly generating the | 4016 // maps are identical. In that case we can avoid repeatedly generating the |
3976 // same prototype map checks. | 4017 // same prototype map checks. |
3977 int count = 0; | 4018 int count = 0; |
3978 HBasicBlock* join = NULL; | 4019 HBasicBlock* join = NULL; |
3979 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 4020 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
3980 Handle<Map> map = types->at(i); | 4021 Handle<Map> map = types->at(i); |
3981 LookupResult lookup(isolate()); | 4022 LookupResult lookup(isolate()); |
3982 if (ComputeStoredField(map, name, &lookup)) { | 4023 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
3983 if (count == 0) { | 4024 if (count == 0) { |
3984 AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once. | 4025 AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once. |
3985 join = graph()->CreateBasicBlock(); | 4026 join = graph()->CreateBasicBlock(); |
3986 } | 4027 } |
3987 ++count; | 4028 ++count; |
3988 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4029 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
3989 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4030 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
3990 HCompareMap* compare = | 4031 HCompareMap* compare = |
3991 new(zone()) HCompareMap(object, map, if_true, if_false); | 4032 new(zone()) HCompareMap(object, map, if_true, if_false); |
3992 current_block()->Finish(compare); | 4033 current_block()->Finish(compare); |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4443 } | 4484 } |
4444 | 4485 |
4445 | 4486 |
4446 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 4487 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
4447 Property* expr, | 4488 Property* expr, |
4448 Handle<Map> type, | 4489 Handle<Map> type, |
4449 LookupResult* lookup, | 4490 LookupResult* lookup, |
4450 bool smi_and_map_check) { | 4491 bool smi_and_map_check) { |
4451 if (smi_and_map_check) { | 4492 if (smi_and_map_check) { |
4452 AddInstruction(new(zone()) HCheckNonSmi(object)); | 4493 AddInstruction(new(zone()) HCheckNonSmi(object)); |
4453 AddInstruction(new(zone()) HCheckMap(object, type, NULL, | 4494 AddInstruction(HCheckMaps::NewWithTransitions(object, type)); |
4454 ALLOW_ELEMENT_TRANSITION_MAPS)); | |
4455 } | 4495 } |
4456 | 4496 |
4457 int index = lookup->GetLocalFieldIndexFromMap(*type); | 4497 int index = lookup->GetLocalFieldIndexFromMap(*type); |
4458 if (index < 0) { | 4498 if (index < 0) { |
4459 // Negative property indices are in-object properties, indexed | 4499 // Negative property indices are in-object properties, indexed |
4460 // from the end of the fixed part of the object. | 4500 // from the end of the fixed part of the object. |
4461 int offset = (index * kPointerSize) + type->instance_size(); | 4501 int offset = (index * kPointerSize) + type->instance_size(); |
4462 return new(zone()) HLoadNamedField(object, true, offset); | 4502 return new(zone()) HLoadNamedField(object, true, offset); |
4463 } else { | 4503 } else { |
4464 // Non-negative property indices are in the properties array. | 4504 // Non-negative property indices are in the properties array. |
(...skipping 19 matching lines...) Expand all Loading... |
4484 LookupResult lookup(isolate()); | 4524 LookupResult lookup(isolate()); |
4485 map->LookupInDescriptors(NULL, *name, &lookup); | 4525 map->LookupInDescriptors(NULL, *name, &lookup); |
4486 if (lookup.IsFound() && lookup.type() == FIELD) { | 4526 if (lookup.IsFound() && lookup.type() == FIELD) { |
4487 return BuildLoadNamedField(obj, | 4527 return BuildLoadNamedField(obj, |
4488 expr, | 4528 expr, |
4489 map, | 4529 map, |
4490 &lookup, | 4530 &lookup, |
4491 true); | 4531 true); |
4492 } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) { | 4532 } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) { |
4493 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 4533 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
4494 AddInstruction(new(zone()) HCheckMap(obj, map, NULL, | 4534 AddInstruction(HCheckMaps::NewWithTransitions(obj, map)); |
4495 ALLOW_ELEMENT_TRANSITION_MAPS)); | |
4496 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 4535 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
4497 return new(zone()) HConstant(function, Representation::Tagged()); | 4536 return new(zone()) HConstant(function, Representation::Tagged()); |
4498 } else { | 4537 } else { |
4499 return BuildLoadNamedGeneric(obj, expr); | 4538 return BuildLoadNamedGeneric(obj, expr); |
4500 } | 4539 } |
4501 } | 4540 } |
4502 | 4541 |
4503 | 4542 |
4504 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 4543 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
4505 HValue* key) { | 4544 HValue* key) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4587 return new(zone()) HLoadKeyedFastElement(elements, checked_key); | 4626 return new(zone()) HLoadKeyedFastElement(elements, checked_key); |
4588 } | 4627 } |
4589 } | 4628 } |
4590 | 4629 |
4591 | 4630 |
4592 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, | 4631 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
4593 HValue* key, | 4632 HValue* key, |
4594 HValue* val, | 4633 HValue* val, |
4595 Handle<Map> map, | 4634 Handle<Map> map, |
4596 bool is_store) { | 4635 bool is_store) { |
4597 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); | 4636 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMaps(object, map)); |
4598 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); | 4637 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); |
4599 bool fast_elements = map->has_fast_elements(); | 4638 bool fast_elements = map->has_fast_elements(); |
4600 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 4639 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
4601 if (is_store && (fast_elements || fast_smi_only_elements)) { | 4640 if (is_store && (fast_elements || fast_smi_only_elements)) { |
4602 AddInstruction(new(zone()) HCheckMap( | 4641 AddInstruction(new(zone()) HCheckMaps( |
4603 elements, isolate()->factory()->fixed_array_map())); | 4642 elements, isolate()->factory()->fixed_array_map())); |
4604 } | 4643 } |
4605 HInstruction* length = NULL; | 4644 HInstruction* length = NULL; |
4606 HInstruction* checked_key = NULL; | 4645 HInstruction* checked_key = NULL; |
4607 if (map->has_external_array_elements()) { | 4646 if (map->has_external_array_elements()) { |
4608 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 4647 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
4609 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4648 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4610 HLoadExternalArrayPointer* external_elements = | 4649 HLoadExternalArrayPointer* external_elements = |
4611 new(zone()) HLoadExternalArrayPointer(elements); | 4650 new(zone()) HLoadExternalArrayPointer(elements); |
4612 AddInstruction(external_elements); | 4651 AddInstruction(external_elements); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4742 elements_kind_branch->SetSuccessorAt(0, if_true); | 4781 elements_kind_branch->SetSuccessorAt(0, if_true); |
4743 elements_kind_branch->SetSuccessorAt(1, if_false); | 4782 elements_kind_branch->SetSuccessorAt(1, if_false); |
4744 current_block()->Finish(elements_kind_branch); | 4783 current_block()->Finish(elements_kind_branch); |
4745 | 4784 |
4746 set_current_block(if_true); | 4785 set_current_block(if_true); |
4747 HInstruction* access; | 4786 HInstruction* access; |
4748 if (elements_kind == FAST_SMI_ONLY_ELEMENTS || | 4787 if (elements_kind == FAST_SMI_ONLY_ELEMENTS || |
4749 elements_kind == FAST_ELEMENTS || | 4788 elements_kind == FAST_ELEMENTS || |
4750 elements_kind == FAST_DOUBLE_ELEMENTS) { | 4789 elements_kind == FAST_DOUBLE_ELEMENTS) { |
4751 if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) { | 4790 if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) { |
4752 AddInstruction(new(zone()) HCheckMap( | 4791 AddInstruction(new(zone()) HCheckMaps( |
4753 elements, isolate()->factory()->fixed_array_map(), | 4792 elements, isolate()->factory()->fixed_array_map(), |
4754 elements_kind_branch)); | 4793 elements_kind_branch)); |
4755 } | 4794 } |
4756 // TODO(jkummerow): The need for these two blocks could be avoided | 4795 // TODO(jkummerow): The need for these two blocks could be avoided |
4757 // in one of two ways: | 4796 // in one of two ways: |
4758 // (1) Introduce ElementsKinds for JSArrays that are distinct from | 4797 // (1) Introduce ElementsKinds for JSArrays that are distinct from |
4759 // those for fast objects. | 4798 // those for fast objects. |
4760 // (2) Put the common instructions into a third "join" block. This | 4799 // (2) Put the common instructions into a third "join" block. This |
4761 // requires additional AST IDs that we can deopt to from inside | 4800 // requires additional AST IDs that we can deopt to from inside |
4762 // that join block. They must be added to the Property class (when | 4801 // that join block. They must be added to the Property class (when |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4946 | 4985 |
4947 } else if (expr->key()->IsPropertyName()) { | 4986 } else if (expr->key()->IsPropertyName()) { |
4948 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 4987 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
4949 SmallMapList* types = expr->GetReceiverTypes(); | 4988 SmallMapList* types = expr->GetReceiverTypes(); |
4950 | 4989 |
4951 HValue* obj = Pop(); | 4990 HValue* obj = Pop(); |
4952 if (expr->IsMonomorphic()) { | 4991 if (expr->IsMonomorphic()) { |
4953 instr = BuildLoadNamed(obj, expr, types->first(), name); | 4992 instr = BuildLoadNamed(obj, expr, types->first(), name); |
4954 } else if (types != NULL && types->length() > 1) { | 4993 } else if (types != NULL && types->length() > 1) { |
4955 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 4994 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
4956 HValue* context = environment()->LookupContext(); | 4995 HandlePolymorphicLoadNamedField(expr, obj, types, name); |
4957 instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name); | 4996 return; |
4958 } else { | 4997 } else { |
4959 instr = BuildLoadNamedGeneric(obj, expr); | 4998 instr = BuildLoadNamedGeneric(obj, expr); |
4960 } | 4999 } |
4961 | 5000 |
4962 } else { | 5001 } else { |
4963 CHECK_ALIVE(VisitForValue(expr->key())); | 5002 CHECK_ALIVE(VisitForValue(expr->key())); |
4964 | 5003 |
4965 HValue* key = Pop(); | 5004 HValue* key = Pop(); |
4966 HValue* obj = Pop(); | 5005 HValue* obj = Pop(); |
4967 | 5006 |
(...skipping 20 matching lines...) Expand all Loading... |
4988 | 5027 |
4989 void HGraphBuilder::AddCheckConstantFunction(Call* expr, | 5028 void HGraphBuilder::AddCheckConstantFunction(Call* expr, |
4990 HValue* receiver, | 5029 HValue* receiver, |
4991 Handle<Map> receiver_map, | 5030 Handle<Map> receiver_map, |
4992 bool smi_and_map_check) { | 5031 bool smi_and_map_check) { |
4993 // Constant functions have the nice property that the map will change if they | 5032 // Constant functions have the nice property that the map will change if they |
4994 // are overwritten. Therefore it is enough to check the map of the holder and | 5033 // are overwritten. Therefore it is enough to check the map of the holder and |
4995 // its prototypes. | 5034 // its prototypes. |
4996 if (smi_and_map_check) { | 5035 if (smi_and_map_check) { |
4997 AddInstruction(new(zone()) HCheckNonSmi(receiver)); | 5036 AddInstruction(new(zone()) HCheckNonSmi(receiver)); |
4998 AddInstruction(new(zone()) HCheckMap(receiver, receiver_map, NULL, | 5037 AddInstruction(HCheckMaps::NewWithTransitions(receiver, receiver_map)); |
4999 ALLOW_ELEMENT_TRANSITION_MAPS)); | |
5000 } | 5038 } |
5001 if (!expr->holder().is_null()) { | 5039 if (!expr->holder().is_null()) { |
5002 AddInstruction(new(zone()) HCheckPrototypeMaps( | 5040 AddInstruction(new(zone()) HCheckPrototypeMaps( |
5003 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), | 5041 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), |
5004 expr->holder())); | 5042 expr->holder())); |
5005 } | 5043 } |
5006 } | 5044 } |
5007 | 5045 |
5008 | 5046 |
5009 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, | 5047 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
(...skipping 1749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6759 result->set_position(expr->position()); | 6797 result->set_position(expr->position()); |
6760 return ast_context()->ReturnInstruction(result, expr->id()); | 6798 return ast_context()->ReturnInstruction(result, expr->id()); |
6761 } else if (type_info.IsNonPrimitive()) { | 6799 } else if (type_info.IsNonPrimitive()) { |
6762 switch (op) { | 6800 switch (op) { |
6763 case Token::EQ: | 6801 case Token::EQ: |
6764 case Token::EQ_STRICT: { | 6802 case Token::EQ_STRICT: { |
6765 // Can we get away with map check and not instance type check? | 6803 // Can we get away with map check and not instance type check? |
6766 Handle<Map> map = oracle()->GetCompareMap(expr); | 6804 Handle<Map> map = oracle()->GetCompareMap(expr); |
6767 if (!map.is_null()) { | 6805 if (!map.is_null()) { |
6768 AddInstruction(new(zone()) HCheckNonSmi(left)); | 6806 AddInstruction(new(zone()) HCheckNonSmi(left)); |
6769 AddInstruction(new(zone()) HCheckMap(left, map, NULL, | 6807 AddInstruction(HCheckMaps::NewWithTransitions(left, map)); |
6770 ALLOW_ELEMENT_TRANSITION_MAPS)); | |
6771 AddInstruction(new(zone()) HCheckNonSmi(right)); | 6808 AddInstruction(new(zone()) HCheckNonSmi(right)); |
6772 AddInstruction(new(zone()) HCheckMap(right, map, NULL, | 6809 AddInstruction(HCheckMaps::NewWithTransitions(right, map)); |
6773 ALLOW_ELEMENT_TRANSITION_MAPS)); | |
6774 HCompareObjectEqAndBranch* result = | 6810 HCompareObjectEqAndBranch* result = |
6775 new(zone()) HCompareObjectEqAndBranch(left, right); | 6811 new(zone()) HCompareObjectEqAndBranch(left, right); |
6776 result->set_position(expr->position()); | 6812 result->set_position(expr->position()); |
6777 return ast_context()->ReturnControl(result, expr->id()); | 6813 return ast_context()->ReturnControl(result, expr->id()); |
6778 } else { | 6814 } else { |
6779 AddInstruction(new(zone()) HCheckNonSmi(left)); | 6815 AddInstruction(new(zone()) HCheckNonSmi(left)); |
6780 AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); | 6816 AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); |
6781 AddInstruction(new(zone()) HCheckNonSmi(right)); | 6817 AddInstruction(new(zone()) HCheckNonSmi(right)); |
6782 AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); | 6818 AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); |
6783 HCompareObjectEqAndBranch* result = | 6819 HCompareObjectEqAndBranch* result = |
(...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8047 } | 8083 } |
8048 } | 8084 } |
8049 | 8085 |
8050 #ifdef DEBUG | 8086 #ifdef DEBUG |
8051 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 8087 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
8052 if (allocator_ != NULL) allocator_->Verify(); | 8088 if (allocator_ != NULL) allocator_->Verify(); |
8053 #endif | 8089 #endif |
8054 } | 8090 } |
8055 | 8091 |
8056 } } // namespace v8::internal | 8092 } } // namespace v8::internal |
OLD | NEW |