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

Side by Side Diff: src/hydrogen.cc

Issue 9616014: Improve polymorphic loads on single slots. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Renamed CheckMap to CheckMaps. Created 8 years, 9 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-instructions.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 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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698