| 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 1143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 capacity_checker.If<HCompareNumericAndBranch>(length, current_capacity, | 1154 capacity_checker.If<HCompareNumericAndBranch>(length, current_capacity, |
| 1155 Token::EQ); | 1155 Token::EQ); |
| 1156 capacity_checker.Then(); | 1156 capacity_checker.Then(); |
| 1157 | 1157 |
| 1158 HValue* context = environment()->LookupContext(); | 1158 HValue* context = environment()->LookupContext(); |
| 1159 | 1159 |
| 1160 HValue* new_capacity = | 1160 HValue* new_capacity = |
| 1161 BuildNewElementsCapacity(context, current_capacity); | 1161 BuildNewElementsCapacity(context, current_capacity); |
| 1162 | 1162 |
| 1163 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1163 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1164 kind, length, | 1164 kind, kind, length, |
| 1165 new_capacity); | 1165 new_capacity); |
| 1166 | 1166 |
| 1167 environment()->Push(new_elements); | 1167 environment()->Push(new_elements); |
| 1168 capacity_checker.Else(); | 1168 capacity_checker.Else(); |
| 1169 | 1169 |
| 1170 environment()->Push(elements); | 1170 environment()->Push(elements); |
| 1171 capacity_checker.End(); | 1171 capacity_checker.End(); |
| 1172 | 1172 |
| 1173 if (is_js_array) { | 1173 if (is_js_array) { |
| 1174 HValue* new_length = AddInstruction( | 1174 HValue* new_length = AddInstruction( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1198 HValue* length) { | 1198 HValue* length) { |
| 1199 Factory* factory = isolate()->factory(); | 1199 Factory* factory = isolate()->factory(); |
| 1200 | 1200 |
| 1201 IfBuilder cow_checker(this); | 1201 IfBuilder cow_checker(this); |
| 1202 | 1202 |
| 1203 cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map()); | 1203 cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map()); |
| 1204 cow_checker.Then(); | 1204 cow_checker.Then(); |
| 1205 | 1205 |
| 1206 HValue* capacity = AddLoadFixedArrayLength(elements); | 1206 HValue* capacity = AddLoadFixedArrayLength(elements); |
| 1207 | 1207 |
| 1208 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1208 HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, |
| 1209 kind, length, capacity); | 1209 kind, length, capacity); |
| 1210 | 1210 |
| 1211 environment()->Push(new_elements); | 1211 environment()->Push(new_elements); |
| 1212 | 1212 |
| 1213 cow_checker.Else(); | 1213 cow_checker.Else(); |
| 1214 | 1214 |
| 1215 environment()->Push(elements); | 1215 environment()->Push(elements); |
| 1216 | 1216 |
| 1217 cow_checker.End(); | 1217 cow_checker.End(); |
| 1218 | 1218 |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 HConstant* max_size_constant = Add<HConstant>(max_size); | 1470 HConstant* max_size_constant = Add<HConstant>(max_size); |
| 1471 // Since we're forcing Integer32 representation for this HBoundsCheck, | 1471 // Since we're forcing Integer32 representation for this HBoundsCheck, |
| 1472 // there's no need to Smi-check the index. | 1472 // there's no need to Smi-check the index. |
| 1473 Add<HBoundsCheck>(length, max_size_constant); | 1473 Add<HBoundsCheck>(length, max_size_constant); |
| 1474 } | 1474 } |
| 1475 | 1475 |
| 1476 | 1476 |
| 1477 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1477 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
| 1478 HValue* elements, | 1478 HValue* elements, |
| 1479 ElementsKind kind, | 1479 ElementsKind kind, |
| 1480 ElementsKind new_kind, |
| 1480 HValue* length, | 1481 HValue* length, |
| 1481 HValue* new_capacity) { | 1482 HValue* new_capacity) { |
| 1482 HValue* context = environment()->LookupContext(); | 1483 HValue* context = environment()->LookupContext(); |
| 1483 | 1484 |
| 1484 BuildNewSpaceArrayCheck(new_capacity, kind); | 1485 BuildNewSpaceArrayCheck(new_capacity, new_kind); |
| 1485 | 1486 |
| 1486 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 1487 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
| 1487 context, kind, new_capacity); | 1488 context, new_kind, new_capacity); |
| 1488 | 1489 |
| 1489 BuildCopyElements(context, elements, kind, | 1490 BuildCopyElements(context, elements, kind, |
| 1490 new_elements, kind, | 1491 new_elements, new_kind, |
| 1491 length, new_capacity); | 1492 length, new_capacity); |
| 1492 | 1493 |
| 1493 AddStore(object, HObjectAccess::ForElementsPointer(), new_elements); | 1494 AddStore(object, HObjectAccess::ForElementsPointer(), new_elements); |
| 1494 | 1495 |
| 1495 return new_elements; | 1496 return new_elements; |
| 1496 } | 1497 } |
| 1497 | 1498 |
| 1498 | 1499 |
| 1499 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1500 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, |
| 1500 HValue* elements, | 1501 HValue* elements, |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1952 | 1953 |
| 1953 | 1954 |
| 1954 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 1955 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
| 1955 Handle<Map> map) { | 1956 Handle<Map> map) { |
| 1956 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 1957 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
| 1957 Add<HConstant>(map)); | 1958 Add<HConstant>(map)); |
| 1958 } | 1959 } |
| 1959 | 1960 |
| 1960 | 1961 |
| 1961 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin, | 1962 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin, |
| 1962 HContext* context) { | 1963 HValue* context) { |
| 1963 HGlobalObject* global_object = Add<HGlobalObject>(context); | 1964 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 1964 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 1965 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 1965 GlobalObject::kBuiltinsOffset); | 1966 GlobalObject::kBuiltinsOffset); |
| 1966 HValue* builtins = AddLoad(global_object, access); | 1967 HValue* builtins = AddLoad(global_object, access); |
| 1967 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( | 1968 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( |
| 1968 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); | 1969 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); |
| 1969 return AddLoad(builtins, function_access); | 1970 return AddLoad(builtins, function_access); |
| 1970 } | 1971 } |
| 1971 | 1972 |
| 1972 | 1973 |
| (...skipping 2672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4645 Handle<Object> raw_boilerplate; | 4646 Handle<Object> raw_boilerplate; |
| 4646 if (literals_cell->IsUndefined()) { | 4647 if (literals_cell->IsUndefined()) { |
| 4647 uninitialized = true; | 4648 uninitialized = true; |
| 4648 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( | 4649 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( |
| 4649 isolate(), literals, expr->constant_elements()); | 4650 isolate(), literals, expr->constant_elements()); |
| 4650 if (raw_boilerplate.is_null()) { | 4651 if (raw_boilerplate.is_null()) { |
| 4651 return Bailout("array boilerplate creation failed"); | 4652 return Bailout("array boilerplate creation failed"); |
| 4652 } | 4653 } |
| 4653 | 4654 |
| 4654 site = isolate()->factory()->NewAllocationSite(); | 4655 site = isolate()->factory()->NewAllocationSite(); |
| 4655 site->set_payload(*raw_boilerplate); | 4656 site->set_transition_info(*raw_boilerplate); |
| 4656 literals->set(expr->literal_index(), *site); | 4657 literals->set(expr->literal_index(), *site); |
| 4657 | 4658 |
| 4658 if (JSObject::cast(*raw_boilerplate)->elements()->map() == | 4659 if (JSObject::cast(*raw_boilerplate)->elements()->map() == |
| 4659 isolate()->heap()->fixed_cow_array_map()) { | 4660 isolate()->heap()->fixed_cow_array_map()) { |
| 4660 isolate()->counters()->cow_arrays_created_runtime()->Increment(); | 4661 isolate()->counters()->cow_arrays_created_runtime()->Increment(); |
| 4661 } | 4662 } |
| 4662 } else { | 4663 } else { |
| 4663 ASSERT(literals_cell->IsAllocationSite()); | 4664 ASSERT(literals_cell->IsAllocationSite()); |
| 4664 site = Handle<AllocationSite>::cast(literals_cell); | 4665 site = Handle<AllocationSite>::cast(literals_cell); |
| 4665 raw_boilerplate = Handle<Object>(site->payload(), isolate()); | 4666 raw_boilerplate = Handle<Object>(site->transition_info(), isolate()); |
| 4666 } | 4667 } |
| 4667 | 4668 |
| 4668 ASSERT(!raw_boilerplate.is_null()); | 4669 ASSERT(!raw_boilerplate.is_null()); |
| 4669 ASSERT(site->IsLiteralSite()); | 4670 ASSERT(site->IsLiteralSite()); |
| 4670 | 4671 |
| 4671 Handle<JSObject> original_boilerplate_object = | 4672 Handle<JSObject> original_boilerplate_object = |
| 4672 Handle<JSObject>::cast(raw_boilerplate); | 4673 Handle<JSObject>::cast(raw_boilerplate); |
| 4673 ElementsKind boilerplate_elements_kind = | 4674 ElementsKind boilerplate_elements_kind = |
| 4674 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); | 4675 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); |
| 4675 | 4676 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4769 Drop(1); // array literal index | 4770 Drop(1); // array literal index |
| 4770 return ast_context()->ReturnValue(Pop()); | 4771 return ast_context()->ReturnValue(Pop()); |
| 4771 } | 4772 } |
| 4772 | 4773 |
| 4773 | 4774 |
| 4774 // Sets the lookup result and returns true if the load/store can be inlined. | 4775 // Sets the lookup result and returns true if the load/store can be inlined. |
| 4775 static bool ComputeLoadStoreField(Handle<Map> type, | 4776 static bool ComputeLoadStoreField(Handle<Map> type, |
| 4776 Handle<String> name, | 4777 Handle<String> name, |
| 4777 LookupResult* lookup, | 4778 LookupResult* lookup, |
| 4778 bool is_store) { | 4779 bool is_store) { |
| 4780 ASSERT(!is_store || !type->is_observed()); |
| 4779 if (type->has_named_interceptor()) { | 4781 if (type->has_named_interceptor()) { |
| 4780 lookup->InterceptorResult(NULL); | 4782 lookup->InterceptorResult(NULL); |
| 4781 return false; | 4783 return false; |
| 4782 } | 4784 } |
| 4783 // If we directly find a field, the access can be inlined. | 4785 // If we directly find a field, the access can be inlined. |
| 4784 type->LookupDescriptor(NULL, *name, lookup); | 4786 type->LookupDescriptor(NULL, *name, lookup); |
| 4785 if (lookup->IsField()) return true; | 4787 if (lookup->IsField()) return true; |
| 4786 | 4788 |
| 4787 // For a load, we are out of luck if there is no such field. | 4789 // For a load, we are out of luck if there is no such field. |
| 4788 if (!is_store) return false; | 4790 if (!is_store) return false; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4936 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 4938 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 4937 AddCheckMapsWithTransitions(object, map); | 4939 AddCheckMapsWithTransitions(object, map); |
| 4938 return BuildStoreNamedField(object, name, value, map, &lookup); | 4940 return BuildStoreNamedField(object, name, value, map, &lookup); |
| 4939 } | 4941 } |
| 4940 | 4942 |
| 4941 // No luck, do a generic store. | 4943 // No luck, do a generic store. |
| 4942 return BuildStoreNamedGeneric(object, name, value); | 4944 return BuildStoreNamedGeneric(object, name, value); |
| 4943 } | 4945 } |
| 4944 | 4946 |
| 4945 | 4947 |
| 4948 static bool CanLoadPropertyFromPrototype(Handle<Map> map, |
| 4949 Handle<Name> name, |
| 4950 LookupResult* lookup) { |
| 4951 if (map->has_named_interceptor()) return false; |
| 4952 if (map->is_dictionary_map()) return false; |
| 4953 map->LookupDescriptor(NULL, *name, lookup); |
| 4954 if (lookup->IsFound()) return false; |
| 4955 return true; |
| 4956 } |
| 4957 |
| 4958 |
| 4946 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( | 4959 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
| 4947 Property* expr, | 4960 Property* expr, |
| 4948 HValue* object, | 4961 HValue* object, |
| 4949 SmallMapList* types, | 4962 SmallMapList* types, |
| 4950 Handle<String> name) { | 4963 Handle<String> name) { |
| 4951 // Use monomorphic load if property lookup results in the same field index | 4964 // Use monomorphic load if property lookup results in the same field index |
| 4952 // for all maps. Requires special map check on the set of all handled maps. | 4965 // for all maps. Requires special map check on the set of all handled maps. |
| 4953 if (types->length() > kMaxLoadPolymorphism) return NULL; | 4966 if (types->length() > kMaxLoadPolymorphism) return NULL; |
| 4954 | 4967 |
| 4955 LookupResult lookup(isolate()); | 4968 LookupResult lookup(isolate()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4973 } else if (access.offset() != new_access.offset()) { | 4986 } else if (access.offset() != new_access.offset()) { |
| 4974 // Offsets did not match. | 4987 // Offsets did not match. |
| 4975 break; | 4988 break; |
| 4976 } else if (access.IsInobject() != new_access.IsInobject()) { | 4989 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 4977 // In-objectness did not match. | 4990 // In-objectness did not match. |
| 4978 break; | 4991 break; |
| 4979 } | 4992 } |
| 4980 representation = representation.generalize(new_representation); | 4993 representation = representation.generalize(new_representation); |
| 4981 } | 4994 } |
| 4982 | 4995 |
| 4983 if (count != types->length()) return NULL; | 4996 if (count == types->length()) { |
| 4997 // Everything matched; can use monomorphic load. |
| 4998 BuildCheckHeapObject(object); |
| 4999 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 5000 return BuildLoadNamedField(object, access, representation); |
| 5001 } |
| 4984 | 5002 |
| 4985 // Everything matched; can use monomorphic load. | 5003 if (count != 0) return NULL; |
| 5004 |
| 5005 // Second chance: the property is on the prototype and all maps have the |
| 5006 // same prototype. |
| 5007 Handle<Map> map(types->at(0)); |
| 5008 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; |
| 5009 |
| 5010 Handle<Object> prototype(map->prototype(), isolate()); |
| 5011 for (count = 1; count < types->length(); ++count) { |
| 5012 Handle<Map> test_map(types->at(count)); |
| 5013 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; |
| 5014 if (test_map->prototype() != *prototype) return NULL; |
| 5015 } |
| 5016 |
| 5017 LookupInPrototypes(map, name, &lookup); |
| 5018 if (!lookup.IsField()) return NULL; |
| 5019 |
| 4986 BuildCheckHeapObject(object); | 5020 BuildCheckHeapObject(object); |
| 4987 AddInstruction(HCheckMaps::New(object, types, zone())); | 5021 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 4988 return BuildLoadNamedField(object, access, representation); | 5022 Handle<JSObject> holder(lookup.holder()); |
| 5023 Handle<Map> holder_map(holder->map()); |
| 5024 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 5025 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); |
| 5026 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); |
| 5027 return BuildLoadNamedField(holder_value, |
| 5028 HObjectAccess::ForField(holder_map, &lookup, name), |
| 5029 ComputeLoadStoreRepresentation(map, &lookup)); |
| 4989 } | 5030 } |
| 4990 | 5031 |
| 4991 | 5032 |
| 4992 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 5033 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 4993 Property* expr, | 5034 Property* expr, |
| 4994 HValue* object, | 5035 HValue* object, |
| 4995 SmallMapList* types, | 5036 SmallMapList* types, |
| 4996 Handle<String> name) { | 5037 Handle<String> name) { |
| 4997 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 5038 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
| 4998 expr, object, types, name); | 5039 expr, object, types, name); |
| 4999 if (instr == NULL) { | 5040 if (instr == NULL) { |
| 5000 // Something did not match; must use a polymorphic load. | 5041 // Something did not match; must use a polymorphic load. |
| 5001 BuildCheckHeapObject(object); | 5042 BuildCheckHeapObject(object); |
| 5002 HValue* context = environment()->LookupContext(); | 5043 HValue* context = environment()->LookupContext(); |
| 5003 instr = new(zone()) HLoadNamedFieldPolymorphic( | 5044 instr = new(zone()) HLoadNamedFieldPolymorphic( |
| 5004 context, object, types, name, zone()); | 5045 context, object, types, name, zone()); |
| 5005 } | 5046 } |
| 5006 | 5047 |
| 5007 instr->set_position(expr->position()); | 5048 instr->set_position(expr->position()); |
| 5008 return ast_context()->ReturnInstruction(instr, expr->id()); | 5049 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5009 } | 5050 } |
| 5010 | 5051 |
| 5011 | 5052 |
| 5012 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 5053 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
| 5013 int position, | 5054 int position, |
| 5014 BailoutId assignment_id, | 5055 BailoutId assignment_id, |
| 5015 HValue* object, | 5056 HValue* object, |
| 5016 HValue* value, | 5057 HValue* store_value, |
| 5058 HValue* result_value, |
| 5017 SmallMapList* types, | 5059 SmallMapList* types, |
| 5018 Handle<String> name) { | 5060 Handle<String> name) { |
| 5019 // Use monomorphic store if property lookup results in the same field index | 5061 // Use monomorphic store if property lookup results in the same field index |
| 5020 // for all maps. Requires special map check on the set of all handled maps. | 5062 // for all maps. Requires special map check on the set of all handled maps. |
| 5021 if (types->length() > kMaxStorePolymorphism) return false; | 5063 if (types->length() > kMaxStorePolymorphism) return false; |
| 5022 | 5064 |
| 5023 // TODO(verwaest): Merge the checking logic with the code in | 5065 // TODO(verwaest): Merge the checking logic with the code in |
| 5024 // TryLoadPolymorphicAsMonomorphic. | 5066 // TryLoadPolymorphicAsMonomorphic. |
| 5025 LookupResult lookup(isolate()); | 5067 LookupResult lookup(isolate()); |
| 5026 int count; | 5068 int count; |
| 5027 Representation representation = Representation::None(); | 5069 Representation representation = Representation::None(); |
| 5028 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 5070 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 5029 for (count = 0; count < types->length(); ++count) { | 5071 for (count = 0; count < types->length(); ++count) { |
| 5030 Handle<Map> map = types->at(count); | 5072 Handle<Map> map = types->at(count); |
| 5031 // Pass false to ignore transitions. | 5073 // Pass false to ignore transitions. |
| 5032 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 5074 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 5075 ASSERT(!map->is_observed()); |
| 5033 | 5076 |
| 5034 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 5077 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 5035 Representation new_representation = | 5078 Representation new_representation = |
| 5036 ComputeLoadStoreRepresentation(map, &lookup); | 5079 ComputeLoadStoreRepresentation(map, &lookup); |
| 5037 | 5080 |
| 5038 if (count == 0) { | 5081 if (count == 0) { |
| 5039 // First time through the loop; set access and representation. | 5082 // First time through the loop; set access and representation. |
| 5040 access = new_access; | 5083 access = new_access; |
| 5041 representation = new_representation; | 5084 representation = new_representation; |
| 5042 } else if (!representation.IsCompatibleForStore(new_representation)) { | 5085 } else if (!representation.IsCompatibleForStore(new_representation)) { |
| 5043 // Representations did not match. | 5086 // Representations did not match. |
| 5044 break; | 5087 break; |
| 5045 } else if (access.offset() != new_access.offset()) { | 5088 } else if (access.offset() != new_access.offset()) { |
| 5046 // Offsets did not match. | 5089 // Offsets did not match. |
| 5047 break; | 5090 break; |
| 5048 } else if (access.IsInobject() != new_access.IsInobject()) { | 5091 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 5049 // In-objectness did not match. | 5092 // In-objectness did not match. |
| 5050 break; | 5093 break; |
| 5051 } | 5094 } |
| 5052 } | 5095 } |
| 5053 | 5096 |
| 5054 if (count != types->length()) return false; | 5097 if (count != types->length()) return false; |
| 5055 | 5098 |
| 5056 // Everything matched; can use monomorphic store. | 5099 // Everything matched; can use monomorphic store. |
| 5057 BuildCheckHeapObject(object); | 5100 BuildCheckHeapObject(object); |
| 5058 AddInstruction(HCheckMaps::New(object, types, zone())); | 5101 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 5059 HInstruction* store; | 5102 HInstruction* store; |
| 5060 CHECK_ALIVE_OR_RETURN( | 5103 CHECK_ALIVE_OR_RETURN( |
| 5061 store = BuildStoreNamedField( | 5104 store = BuildStoreNamedField( |
| 5062 object, name, value, types->at(count - 1), &lookup), | 5105 object, name, store_value, types->at(count - 1), &lookup), |
| 5063 true); | 5106 true); |
| 5064 Push(value); | 5107 if (result_value != NULL) Push(result_value); |
| 5108 Push(store_value); |
| 5065 store->set_position(position); | 5109 store->set_position(position); |
| 5066 AddInstruction(store); | 5110 AddInstruction(store); |
| 5067 AddSimulate(assignment_id); | 5111 AddSimulate(assignment_id); |
| 5112 if (result_value != NULL) Drop(1); |
| 5068 ast_context()->ReturnValue(Pop()); | 5113 ast_context()->ReturnValue(Pop()); |
| 5069 return true; | 5114 return true; |
| 5070 } | 5115 } |
| 5071 | 5116 |
| 5072 | 5117 |
| 5073 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 5118 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 5074 BailoutId id, | 5119 BailoutId id, |
| 5075 int position, | 5120 int position, |
| 5076 BailoutId assignment_id, | 5121 BailoutId assignment_id, |
| 5077 HValue* object, | 5122 HValue* object, |
| 5078 HValue* value, | 5123 HValue* store_value, |
| 5124 HValue* result_value, |
| 5079 SmallMapList* types, | 5125 SmallMapList* types, |
| 5080 Handle<String> name) { | 5126 Handle<String> name) { |
| 5081 if (TryStorePolymorphicAsMonomorphic( | 5127 if (TryStorePolymorphicAsMonomorphic( |
| 5082 position, assignment_id, object, value, types, name)) { | 5128 position, assignment_id, object, |
| 5129 store_value, result_value, types, name)) { |
| 5083 return; | 5130 return; |
| 5084 } | 5131 } |
| 5085 | 5132 |
| 5086 // TODO(ager): We should recognize when the prototype chains for different | 5133 // TODO(ager): We should recognize when the prototype chains for different |
| 5087 // maps are identical. In that case we can avoid repeatedly generating the | 5134 // maps are identical. In that case we can avoid repeatedly generating the |
| 5088 // same prototype map checks. | 5135 // same prototype map checks. |
| 5089 int count = 0; | 5136 int count = 0; |
| 5090 HBasicBlock* join = NULL; | 5137 HBasicBlock* join = NULL; |
| 5091 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 5138 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 5092 Handle<Map> map = types->at(i); | 5139 Handle<Map> map = types->at(i); |
| 5093 LookupResult lookup(isolate()); | 5140 LookupResult lookup(isolate()); |
| 5094 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 5141 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 5095 if (count == 0) { | 5142 if (count == 0) { |
| 5096 BuildCheckHeapObject(object); | 5143 BuildCheckHeapObject(object); |
| 5097 join = graph()->CreateBasicBlock(); | 5144 join = graph()->CreateBasicBlock(); |
| 5098 } | 5145 } |
| 5099 ++count; | 5146 ++count; |
| 5100 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5147 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 5101 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5148 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 5102 HCompareMap* compare = | 5149 HCompareMap* compare = |
| 5103 new(zone()) HCompareMap(object, map, if_true, if_false); | 5150 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 5104 current_block()->Finish(compare); | 5151 current_block()->Finish(compare); |
| 5105 | 5152 |
| 5106 set_current_block(if_true); | 5153 set_current_block(if_true); |
| 5107 HInstruction* instr; | 5154 HInstruction* instr; |
| 5108 CHECK_ALIVE( | 5155 CHECK_ALIVE(instr = BuildStoreNamedField( |
| 5109 instr = BuildStoreNamedField(object, name, value, map, &lookup)); | 5156 object, name, store_value, map, &lookup)); |
| 5110 instr->set_position(position); | 5157 instr->set_position(position); |
| 5111 // Goto will add the HSimulate for the store. | 5158 // Goto will add the HSimulate for the store. |
| 5112 AddInstruction(instr); | 5159 AddInstruction(instr); |
| 5113 if (!ast_context()->IsEffect()) Push(value); | 5160 if (!ast_context()->IsEffect()) { |
| 5161 if (result_value != NULL) Push(result_value); |
| 5162 Push(store_value); |
| 5163 } |
| 5114 current_block()->Goto(join); | 5164 current_block()->Goto(join); |
| 5115 | 5165 |
| 5116 set_current_block(if_false); | 5166 set_current_block(if_false); |
| 5117 } | 5167 } |
| 5118 } | 5168 } |
| 5119 | 5169 |
| 5120 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 5170 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 5121 // know about and do not want to handle ones we've never seen. Otherwise | 5171 // know about and do not want to handle ones we've never seen. Otherwise |
| 5122 // use a generic IC. | 5172 // use a generic IC. |
| 5123 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 5173 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 5124 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 5174 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
| 5125 } else { | 5175 } else { |
| 5126 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | 5176 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
| 5127 instr->set_position(position); | 5177 instr->set_position(position); |
| 5128 AddInstruction(instr); | 5178 AddInstruction(instr); |
| 5129 | 5179 |
| 5130 if (join != NULL) { | 5180 if (join != NULL) { |
| 5131 if (!ast_context()->IsEffect()) Push(value); | 5181 if (!ast_context()->IsEffect()) { |
| 5182 if (result_value != NULL) Push(result_value); |
| 5183 Push(store_value); |
| 5184 } |
| 5132 current_block()->Goto(join); | 5185 current_block()->Goto(join); |
| 5133 } else { | 5186 } else { |
| 5134 // The HSimulate for the store should not see the stored value in | 5187 // The HSimulate for the store should not see the stored value in |
| 5135 // effect contexts (it is not materialized at expr->id() in the | 5188 // effect contexts (it is not materialized at expr->id() in the |
| 5136 // unoptimized code). | 5189 // unoptimized code). |
| 5137 if (instr->HasObservableSideEffects()) { | 5190 if (instr->HasObservableSideEffects()) { |
| 5138 if (ast_context()->IsEffect()) { | 5191 if (ast_context()->IsEffect()) { |
| 5139 AddSimulate(id, REMOVABLE_SIMULATE); | 5192 AddSimulate(id, REMOVABLE_SIMULATE); |
| 5140 } else { | 5193 } else { |
| 5141 Push(value); | 5194 if (result_value != NULL) Push(result_value); |
| 5195 Push(store_value); |
| 5142 AddSimulate(id, REMOVABLE_SIMULATE); | 5196 AddSimulate(id, REMOVABLE_SIMULATE); |
| 5143 Drop(1); | 5197 Drop(result_value != NULL ? 2 : 1); |
| 5144 } | 5198 } |
| 5145 } | 5199 } |
| 5146 return ast_context()->ReturnValue(value); | 5200 return ast_context()->ReturnValue( |
| 5201 result_value != NULL ? result_value : store_value); |
| 5147 } | 5202 } |
| 5148 } | 5203 } |
| 5149 | 5204 |
| 5150 ASSERT(join != NULL); | 5205 ASSERT(join != NULL); |
| 5151 join->SetJoinId(id); | 5206 join->SetJoinId(id); |
| 5152 set_current_block(join); | 5207 set_current_block(join); |
| 5153 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 5208 if (!ast_context()->IsEffect()) { |
| 5209 if (result_value != NULL) Drop(1); |
| 5210 ast_context()->ReturnValue(Pop()); |
| 5211 } |
| 5154 } | 5212 } |
| 5155 | 5213 |
| 5156 | 5214 |
| 5157 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 5215 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 5158 Property* prop = expr->target()->AsProperty(); | 5216 Property* prop = expr->target()->AsProperty(); |
| 5159 ASSERT(prop != NULL); | 5217 ASSERT(prop != NULL); |
| 5160 CHECK_ALIVE(VisitForValue(prop->obj())); | 5218 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5161 | 5219 |
| 5162 if (prop->key()->IsPropertyName()) { | 5220 if (prop->key()->IsPropertyName()) { |
| 5163 // Named store. | 5221 // Named store. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5232 } | 5290 } |
| 5233 } | 5291 } |
| 5234 | 5292 |
| 5235 | 5293 |
| 5236 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 5294 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
| 5237 BailoutId id, | 5295 BailoutId id, |
| 5238 int position, | 5296 int position, |
| 5239 BailoutId assignment_id, | 5297 BailoutId assignment_id, |
| 5240 Property* prop, | 5298 Property* prop, |
| 5241 HValue* object, | 5299 HValue* object, |
| 5242 HValue* value) { | 5300 HValue* store_value, |
| 5301 HValue* result_value) { |
| 5243 Literal* key = prop->key()->AsLiteral(); | 5302 Literal* key = prop->key()->AsLiteral(); |
| 5244 Handle<String> name = Handle<String>::cast(key->value()); | 5303 Handle<String> name = Handle<String>::cast(key->value()); |
| 5245 ASSERT(!name.is_null()); | 5304 ASSERT(!name.is_null()); |
| 5246 | 5305 |
| 5247 HInstruction* instr = NULL; | 5306 HInstruction* instr = NULL; |
| 5248 SmallMapList* types = expr->GetReceiverTypes(); | 5307 SmallMapList* types = expr->GetReceiverTypes(); |
| 5249 bool monomorphic = expr->IsMonomorphic(); | 5308 bool monomorphic = expr->IsMonomorphic(); |
| 5250 Handle<Map> map; | 5309 Handle<Map> map; |
| 5251 if (monomorphic) { | 5310 if (monomorphic) { |
| 5252 map = types->first(); | 5311 map = types->first(); |
| 5253 if (map->is_dictionary_map()) monomorphic = false; | 5312 if (map->is_dictionary_map()) monomorphic = false; |
| 5254 } | 5313 } |
| 5255 if (monomorphic) { | 5314 if (monomorphic) { |
| 5256 Handle<JSFunction> setter; | 5315 Handle<JSFunction> setter; |
| 5257 Handle<JSObject> holder; | 5316 Handle<JSObject> holder; |
| 5258 if (LookupSetter(map, name, &setter, &holder)) { | 5317 if (LookupSetter(map, name, &setter, &holder)) { |
| 5259 AddCheckConstantFunction(holder, object, map); | 5318 AddCheckConstantFunction(holder, object, map); |
| 5260 if (FLAG_inline_accessors && | 5319 // Don't try to inline if the result_value is different from the |
| 5261 TryInlineSetter(setter, id, assignment_id, value)) { | 5320 // store_value. That case isn't handled yet by the inlining. |
| 5321 if (result_value == NULL && |
| 5322 FLAG_inline_accessors && |
| 5323 TryInlineSetter(setter, id, assignment_id, store_value)) { |
| 5262 return; | 5324 return; |
| 5263 } | 5325 } |
| 5264 Drop(2); | 5326 Drop(2); |
| 5265 Add<HPushArgument>(object); | 5327 Add<HPushArgument>(object); |
| 5266 Add<HPushArgument>(value); | 5328 Add<HPushArgument>(store_value); |
| 5267 instr = new(zone()) HCallConstantFunction(setter, 2); | 5329 instr = new(zone()) HCallConstantFunction(setter, 2); |
| 5268 } else { | 5330 } else { |
| 5269 Drop(2); | 5331 Drop(2); |
| 5270 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5332 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| 5271 name, | 5333 name, |
| 5272 value, | 5334 store_value, |
| 5273 map)); | 5335 map)); |
| 5274 } | 5336 } |
| 5275 | |
| 5276 } else if (types != NULL && types->length() > 1) { | 5337 } else if (types != NULL && types->length() > 1) { |
| 5277 Drop(2); | 5338 Drop(2); |
| 5278 return HandlePolymorphicStoreNamedField( | 5339 return HandlePolymorphicStoreNamedField( |
| 5279 id, position, assignment_id, object, value, types, name); | 5340 id, position, assignment_id, object, |
| 5341 store_value, result_value, types, name); |
| 5280 } else { | 5342 } else { |
| 5281 Drop(2); | 5343 Drop(2); |
| 5282 instr = BuildStoreNamedGeneric(object, name, value); | 5344 instr = BuildStoreNamedGeneric(object, name, store_value); |
| 5283 } | 5345 } |
| 5284 | 5346 |
| 5285 Push(value); | 5347 if (result_value != NULL) Push(result_value); |
| 5348 Push(store_value); |
| 5286 instr->set_position(position); | 5349 instr->set_position(position); |
| 5287 AddInstruction(instr); | 5350 AddInstruction(instr); |
| 5288 if (instr->HasObservableSideEffects()) { | 5351 if (instr->HasObservableSideEffects()) { |
| 5289 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 5352 AddSimulate(assignment_id, REMOVABLE_SIMULATE); |
| 5290 } | 5353 } |
| 5354 if (result_value != NULL) Drop(1); |
| 5291 return ast_context()->ReturnValue(Pop()); | 5355 return ast_context()->ReturnValue(Pop()); |
| 5292 } | 5356 } |
| 5293 | 5357 |
| 5294 | 5358 |
| 5295 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5359 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5296 Expression* target = expr->target(); | 5360 Expression* target = expr->target(); |
| 5297 VariableProxy* proxy = target->AsVariableProxy(); | 5361 VariableProxy* proxy = target->AsVariableProxy(); |
| 5298 Property* prop = target->AsProperty(); | 5362 Property* prop = target->AsProperty(); |
| 5299 ASSERT(proxy == NULL || prop == NULL); | 5363 ASSERT(proxy == NULL || prop == NULL); |
| 5300 | 5364 |
| (...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6298 | 6362 |
| 6299 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { | 6363 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { |
| 6300 int diff = lhs.ticks() - rhs.ticks(); | 6364 int diff = lhs.ticks() - rhs.ticks(); |
| 6301 if (diff != 0) return diff > 0; | 6365 if (diff != 0) return diff > 0; |
| 6302 diff = lhs.ast_length() - rhs.ast_length(); | 6366 diff = lhs.ast_length() - rhs.ast_length(); |
| 6303 if (diff != 0) return diff < 0; | 6367 if (diff != 0) return diff < 0; |
| 6304 return lhs.src_length() < rhs.src_length(); | 6368 return lhs.src_length() < rhs.src_length(); |
| 6305 } | 6369 } |
| 6306 | 6370 |
| 6307 | 6371 |
| 6372 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic( |
| 6373 Call* expr, |
| 6374 HValue* receiver, |
| 6375 SmallMapList* types, |
| 6376 Handle<String> name) { |
| 6377 if (types->length() > kMaxCallPolymorphism) return false; |
| 6378 |
| 6379 Handle<Map> map(types->at(0)); |
| 6380 LookupResult lookup(isolate()); |
| 6381 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return false; |
| 6382 |
| 6383 Handle<Object> prototype(map->prototype(), isolate()); |
| 6384 for (int count = 1; count < types->length(); ++count) { |
| 6385 Handle<Map> test_map(types->at(count)); |
| 6386 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false; |
| 6387 if (test_map->prototype() != *prototype) return false; |
| 6388 } |
| 6389 |
| 6390 if (!expr->ComputeTarget(map, name)) return false; |
| 6391 |
| 6392 BuildCheckHeapObject(receiver); |
| 6393 AddInstruction(HCheckMaps::New(receiver, types, zone())); |
| 6394 AddCheckPrototypeMaps(expr->holder(), map); |
| 6395 if (FLAG_trace_inlining) { |
| 6396 Handle<JSFunction> caller = current_info()->closure(); |
| 6397 SmartArrayPointer<char> caller_name = |
| 6398 caller->shared()->DebugName()->ToCString(); |
| 6399 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6400 *name->ToCString(), *caller_name); |
| 6401 } |
| 6402 |
| 6403 if (!TryInlineCall(expr)) { |
| 6404 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6405 HCallConstantFunction* call = |
| 6406 new(zone()) HCallConstantFunction(expr->target(), argument_count); |
| 6407 call->set_position(expr->position()); |
| 6408 PreProcessCall(call); |
| 6409 AddInstruction(call); |
| 6410 if (!ast_context()->IsEffect()) Push(call); |
| 6411 AddSimulate(expr->id(), REMOVABLE_SIMULATE); |
| 6412 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6413 } |
| 6414 |
| 6415 return true; |
| 6416 } |
| 6417 |
| 6418 |
| 6308 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6419 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
| 6309 Call* expr, | 6420 Call* expr, |
| 6310 HValue* receiver, | 6421 HValue* receiver, |
| 6311 SmallMapList* types, | 6422 SmallMapList* types, |
| 6312 Handle<String> name) { | 6423 Handle<String> name) { |
| 6313 // TODO(ager): We should recognize when the prototype chains for different | 6424 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return; |
| 6314 // maps are identical. In that case we can avoid repeatedly generating the | 6425 |
| 6315 // same prototype map checks. | |
| 6316 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6426 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6317 HBasicBlock* join = NULL; | 6427 HBasicBlock* join = NULL; |
| 6318 FunctionSorter order[kMaxCallPolymorphism]; | 6428 FunctionSorter order[kMaxCallPolymorphism]; |
| 6319 int ordered_functions = 0; | 6429 int ordered_functions = 0; |
| 6320 | 6430 |
| 6321 Handle<Map> initial_string_map( | 6431 Handle<Map> initial_string_map( |
| 6322 isolate()->native_context()->string_function()->initial_map()); | 6432 isolate()->native_context()->string_function()->initial_map()); |
| 6323 Handle<Map> string_marker_map( | 6433 Handle<Map> string_marker_map( |
| 6324 JSObject::cast(initial_string_map->prototype())->map()); | 6434 JSObject::cast(initial_string_map->prototype())->map()); |
| 6325 Handle<Map> initial_number_map( | 6435 Handle<Map> initial_number_map( |
| (...skipping 1264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7590 | 7700 |
| 7591 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7701 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { |
| 7592 Property* prop = expr->expression()->AsProperty(); | 7702 Property* prop = expr->expression()->AsProperty(); |
| 7593 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7703 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 7594 if (prop != NULL) { | 7704 if (prop != NULL) { |
| 7595 CHECK_ALIVE(VisitForValue(prop->obj())); | 7705 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7596 CHECK_ALIVE(VisitForValue(prop->key())); | 7706 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7597 HValue* key = Pop(); | 7707 HValue* key = Pop(); |
| 7598 HValue* obj = Pop(); | 7708 HValue* obj = Pop(); |
| 7599 HValue* context = environment()->LookupContext(); | 7709 HValue* context = environment()->LookupContext(); |
| 7600 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); | 7710 HValue* function = AddLoadJSBuiltin(Builtins::DELETE, context); |
| 7711 Add<HPushArgument>(obj); |
| 7712 Add<HPushArgument>(key); |
| 7713 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); |
| 7714 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
| 7715 // even though we are certain to pass the correct number of arguments here. |
| 7716 HInstruction* instr = new(zone()) HInvokeFunction(context, function, 3); |
| 7601 return ast_context()->ReturnInstruction(instr, expr->id()); | 7717 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7602 } else if (proxy != NULL) { | 7718 } else if (proxy != NULL) { |
| 7603 Variable* var = proxy->var(); | 7719 Variable* var = proxy->var(); |
| 7604 if (var->IsUnallocated()) { | 7720 if (var->IsUnallocated()) { |
| 7605 Bailout("delete with global variable"); | 7721 Bailout("delete with global variable"); |
| 7606 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 7722 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 7607 // Result of deleting non-global variables is false. 'this' is not | 7723 // Result of deleting non-global variables is false. 'this' is not |
| 7608 // really a variable, though we implement it as one. The | 7724 // really a variable, though we implement it as one. The |
| 7609 // subexpression does not have side effects. | 7725 // subexpression does not have side effects. |
| 7610 HValue* value = var->is_this() | 7726 HValue* value = var->is_this() |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7845 } else if (types != NULL && types->length() > 1) { | 7961 } else if (types != NULL && types->length() > 1) { |
| 7846 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 7962 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 7847 } | 7963 } |
| 7848 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 7964 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 7849 PushAndAdd(load); | 7965 PushAndAdd(load); |
| 7850 if (load->HasObservableSideEffects()) { | 7966 if (load->HasObservableSideEffects()) { |
| 7851 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7967 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7852 } | 7968 } |
| 7853 | 7969 |
| 7854 after = BuildIncrement(returns_original_input, expr); | 7970 after = BuildIncrement(returns_original_input, expr); |
| 7855 input = Pop(); | |
| 7856 | 7971 |
| 7857 HInstruction* store; | 7972 HValue* result = returns_original_input ? Pop() : NULL; |
| 7858 if (!monomorphic || map->is_observed()) { | |
| 7859 // If we don't know the monomorphic type, do a generic store. | |
| 7860 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, after)); | |
| 7861 } else { | |
| 7862 Handle<JSFunction> setter; | |
| 7863 Handle<JSObject> holder; | |
| 7864 if (LookupSetter(map, name, &setter, &holder)) { | |
| 7865 store = BuildCallSetter(object, after, map, setter, holder); | |
| 7866 } else { | |
| 7867 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, | |
| 7868 name, | |
| 7869 after, | |
| 7870 map)); | |
| 7871 } | |
| 7872 } | |
| 7873 AddInstruction(store); | |
| 7874 | 7973 |
| 7875 // Overwrite the receiver in the bailout environment with the result | 7974 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 7876 // of the operation, and the placeholder with the original value if | 7975 expr->AssignmentId(), prop, object, after, result); |
| 7877 // necessary. | |
| 7878 environment()->SetExpressionStackAt(0, after); | |
| 7879 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | |
| 7880 if (store->HasObservableSideEffects()) { | |
| 7881 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | |
| 7882 } | |
| 7883 | |
| 7884 } else { | 7976 } else { |
| 7885 // Keyed property. | 7977 // Keyed property. |
| 7886 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7978 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 7887 | 7979 |
| 7888 CHECK_ALIVE(VisitForValue(prop->obj())); | 7980 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7889 CHECK_ALIVE(VisitForValue(prop->key())); | 7981 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7890 HValue* obj = environment()->ExpressionStackAt(1); | 7982 HValue* obj = environment()->ExpressionStackAt(1); |
| 7891 HValue* key = environment()->ExpressionStackAt(0); | 7983 HValue* key = environment()->ExpressionStackAt(0); |
| 7892 | 7984 |
| 7893 bool has_side_effects = false; | 7985 bool has_side_effects = false; |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8403 Add<HCheckFunction>(right, target); | 8495 Add<HCheckFunction>(right, target); |
| 8404 HInstanceOfKnownGlobal* result = | 8496 HInstanceOfKnownGlobal* result = |
| 8405 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 8497 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
| 8406 result->set_position(expr->position()); | 8498 result->set_position(expr->position()); |
| 8407 return ast_context()->ReturnInstruction(result, expr->id()); | 8499 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8408 } | 8500 } |
| 8409 | 8501 |
| 8410 // Code below assumes that we don't fall through. | 8502 // Code below assumes that we don't fall through. |
| 8411 UNREACHABLE(); | 8503 UNREACHABLE(); |
| 8412 } else if (op == Token::IN) { | 8504 } else if (op == Token::IN) { |
| 8413 HIn* result = new(zone()) HIn(context, left, right); | 8505 HValue* function = AddLoadJSBuiltin(Builtins::IN, context); |
| 8506 Add<HPushArgument>(left); |
| 8507 Add<HPushArgument>(right); |
| 8508 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
| 8509 // even though we are certain to pass the correct number of arguments here. |
| 8510 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
| 8414 result->set_position(expr->position()); | 8511 result->set_position(expr->position()); |
| 8415 return ast_context()->ReturnInstruction(result, expr->id()); | 8512 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8416 } | 8513 } |
| 8417 | 8514 |
| 8418 // Cases handled below depend on collected type feedback. They should | 8515 // Cases handled below depend on collected type feedback. They should |
| 8419 // soft deoptimize when there is no type feedback. | 8516 // soft deoptimize when there is no type feedback. |
| 8420 if (combined_type->Is(Type::None())) { | 8517 if (combined_type->Is(Type::None())) { |
| 8421 AddSoftDeoptimize(); | 8518 AddSoftDeoptimize(); |
| 8422 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8519 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 8423 } | 8520 } |
| (...skipping 1721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10145 if (ShouldProduceTraceOutput()) { | 10242 if (ShouldProduceTraceOutput()) { |
| 10146 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10243 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 10147 } | 10244 } |
| 10148 | 10245 |
| 10149 #ifdef DEBUG | 10246 #ifdef DEBUG |
| 10150 graph_->Verify(false); // No full verify. | 10247 graph_->Verify(false); // No full verify. |
| 10151 #endif | 10248 #endif |
| 10152 } | 10249 } |
| 10153 | 10250 |
| 10154 } } // namespace v8::internal | 10251 } } // namespace v8::internal |
| OLD | NEW |