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 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 ElementsKind to_kind, | 1184 ElementsKind to_kind, |
1185 bool is_jsarray) { | 1185 bool is_jsarray) { |
1186 ASSERT(!IsFastHoleyElementsKind(from_kind) || | 1186 ASSERT(!IsFastHoleyElementsKind(from_kind) || |
1187 IsFastHoleyElementsKind(to_kind)); | 1187 IsFastHoleyElementsKind(to_kind)); |
1188 | 1188 |
1189 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { | 1189 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
1190 Add<HTrapAllocationMemento>(object); | 1190 Add<HTrapAllocationMemento>(object); |
1191 } | 1191 } |
1192 | 1192 |
1193 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { | 1193 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
1194 HInstruction* elements = AddLoadElements(object); | 1194 HInstruction* elements = AddLoadElements(object, NULL); |
1195 | 1195 |
1196 HInstruction* empty_fixed_array = Add<HConstant>( | 1196 HInstruction* empty_fixed_array = Add<HConstant>( |
1197 isolate()->factory()->empty_fixed_array()); | 1197 isolate()->factory()->empty_fixed_array()); |
1198 | 1198 |
1199 IfBuilder if_builder(this); | 1199 IfBuilder if_builder(this); |
1200 | 1200 |
1201 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); | 1201 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); |
1202 | 1202 |
1203 if_builder.Then(); | 1203 if_builder.Then(); |
1204 | 1204 |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1693 } | 1693 } |
1694 | 1694 |
1695 // Create an allocation site info if requested. | 1695 // Create an allocation site info if requested. |
1696 if (mode == TRACK_ALLOCATION_SITE) { | 1696 if (mode == TRACK_ALLOCATION_SITE) { |
1697 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); | 1697 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); |
1698 } | 1698 } |
1699 | 1699 |
1700 if (length > 0) { | 1700 if (length > 0) { |
1701 // Get hold of the elements array of the boilerplate and setup the | 1701 // Get hold of the elements array of the boilerplate and setup the |
1702 // elements pointer in the resulting object. | 1702 // elements pointer in the resulting object. |
1703 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 1703 HValue* boilerplate_elements = AddLoadElements(boilerplate, NULL); |
1704 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); | 1704 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); |
1705 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 1705 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
1706 object_elements); | 1706 object_elements); |
1707 | 1707 |
1708 // Copy the elements array header. | 1708 // Copy the elements array header. |
1709 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1709 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
1710 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 1710 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
1711 Add<HStoreNamedField>(object_elements, access, | 1711 Add<HStoreNamedField>(object_elements, access, |
1712 Add<HLoadNamedField>(boilerplate_elements, access)); | 1712 Add<HLoadNamedField>(boilerplate_elements, access)); |
1713 } | 1713 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 constructor_function_(constructor_function) { | 1826 constructor_function_(constructor_function) { |
1827 } | 1827 } |
1828 | 1828 |
1829 | 1829 |
1830 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { | 1830 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { |
1831 if (kind_ == GetInitialFastElementsKind()) { | 1831 if (kind_ == GetInitialFastElementsKind()) { |
1832 // No need for a context lookup if the kind_ matches the initial | 1832 // No need for a context lookup if the kind_ matches the initial |
1833 // map, because we can just load the map in that case. | 1833 // map, because we can just load the map in that case. |
1834 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1834 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1835 return builder()->AddInstruction( | 1835 return builder()->AddInstruction( |
1836 builder()->BuildLoadNamedField(constructor_function_, access)); | 1836 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); |
1837 } | 1837 } |
1838 | 1838 |
1839 HInstruction* native_context = builder()->BuildGetNativeContext(); | 1839 HInstruction* native_context = builder()->BuildGetNativeContext(); |
1840 HInstruction* index = builder()->Add<HConstant>( | 1840 HInstruction* index = builder()->Add<HConstant>( |
1841 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1841 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
1842 | 1842 |
1843 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1843 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
1844 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1844 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1845 | 1845 |
1846 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1846 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
1847 | 1847 |
1848 return builder()->Add<HLoadKeyed>( | 1848 return builder()->Add<HLoadKeyed>( |
1849 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1849 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1850 } | 1850 } |
1851 | 1851 |
1852 | 1852 |
1853 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1853 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
1854 // Find the map near the constructor function | 1854 // Find the map near the constructor function |
1855 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1855 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1856 return builder()->AddInstruction( | 1856 return builder()->AddInstruction( |
1857 builder()->BuildLoadNamedField(constructor_function_, access)); | 1857 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); |
1858 } | 1858 } |
1859 | 1859 |
1860 | 1860 |
1861 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1861 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
1862 HValue* length_node) { | 1862 HValue* length_node) { |
1863 ASSERT(length_node != NULL); | 1863 ASSERT(length_node != NULL); |
1864 | 1864 |
1865 int base_size = JSArray::kSize; | 1865 int base_size = JSArray::kSize; |
1866 if (mode_ == TRACK_ALLOCATION_SITE) { | 1866 if (mode_ == TRACK_ALLOCATION_SITE) { |
1867 base_size += AllocationMemento::kSize; | 1867 base_size += AllocationMemento::kSize; |
(...skipping 2423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4291 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 4291 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
4292 // end, we want to quit creating allocation site info after a certain number | 4292 // end, we want to quit creating allocation site info after a certain number |
4293 // of GCs for a call site. | 4293 // of GCs for a call site. |
4294 AllocationSiteMode mode = AllocationSite::GetMode( | 4294 AllocationSiteMode mode = AllocationSite::GetMode( |
4295 boilerplate_elements_kind); | 4295 boilerplate_elements_kind); |
4296 | 4296 |
4297 // Check whether to use fast or slow deep-copying for boilerplate. | 4297 // Check whether to use fast or slow deep-copying for boilerplate. |
4298 int data_size = 0; | 4298 int data_size = 0; |
4299 int pointer_size = 0; | 4299 int pointer_size = 0; |
4300 int max_properties = kMaxFastLiteralProperties; | 4300 int max_properties = kMaxFastLiteralProperties; |
| 4301 HCheckMaps* type_check = NULL; |
4301 if (IsFastLiteral(original_boilerplate_object, | 4302 if (IsFastLiteral(original_boilerplate_object, |
4302 kMaxFastLiteralDepth, | 4303 kMaxFastLiteralDepth, |
4303 &max_properties, | 4304 &max_properties, |
4304 &data_size, | 4305 &data_size, |
4305 &pointer_size)) { | 4306 &pointer_size)) { |
4306 if (mode == TRACK_ALLOCATION_SITE) { | 4307 if (mode == TRACK_ALLOCATION_SITE) { |
4307 pointer_size += AllocationMemento::kSize; | 4308 pointer_size += AllocationMemento::kSize; |
4308 } | 4309 } |
4309 | 4310 |
4310 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | 4311 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); |
(...skipping 17 matching lines...) Expand all Loading... |
4328 | 4329 |
4329 Runtime::FunctionId function_id = (expr->depth() > 1) | 4330 Runtime::FunctionId function_id = (expr->depth() > 1) |
4330 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4331 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
4331 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 4332 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
4332 Runtime::FunctionForId(function_id), | 4333 Runtime::FunctionForId(function_id), |
4333 3); | 4334 3); |
4334 | 4335 |
4335 // De-opt if elements kind changed from boilerplate_elements_kind. | 4336 // De-opt if elements kind changed from boilerplate_elements_kind. |
4336 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4337 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
4337 isolate()); | 4338 isolate()); |
4338 Add<HCheckMaps>(literal, map, top_info()); | 4339 type_check = Add<HCheckMaps>(literal, map, top_info()); |
4339 } | 4340 } |
4340 | 4341 |
4341 // The array is expected in the bailout environment during computation | 4342 // The array is expected in the bailout environment during computation |
4342 // of the property values and is the value of the entire expression. | 4343 // of the property values and is the value of the entire expression. |
4343 Push(literal); | 4344 Push(literal); |
4344 // The literal index is on the stack, too. | 4345 // The literal index is on the stack, too. |
4345 Push(Add<HConstant>(expr->literal_index())); | 4346 Push(Add<HConstant>(expr->literal_index())); |
4346 | 4347 |
4347 HInstruction* elements = NULL; | 4348 HInstruction* elements = NULL; |
4348 | 4349 |
4349 for (int i = 0; i < length; i++) { | 4350 for (int i = 0; i < length; i++) { |
4350 Expression* subexpr = subexprs->at(i); | 4351 Expression* subexpr = subexprs->at(i); |
4351 // If the subexpression is a literal or a simple materialized literal it | 4352 // If the subexpression is a literal or a simple materialized literal it |
4352 // is already set in the cloned array. | 4353 // is already set in the cloned array. |
4353 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 4354 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
4354 | 4355 |
4355 CHECK_ALIVE(VisitForValue(subexpr)); | 4356 CHECK_ALIVE(VisitForValue(subexpr)); |
4356 HValue* value = Pop(); | 4357 HValue* value = Pop(); |
4357 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); | 4358 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); |
4358 | 4359 |
4359 elements = AddLoadElements(literal); | 4360 elements = AddLoadElements(literal, type_check); |
4360 | 4361 |
4361 HValue* key = Add<HConstant>(i); | 4362 HValue* key = Add<HConstant>(i); |
4362 | 4363 |
4363 switch (boilerplate_elements_kind) { | 4364 switch (boilerplate_elements_kind) { |
4364 case FAST_SMI_ELEMENTS: | 4365 case FAST_SMI_ELEMENTS: |
4365 case FAST_HOLEY_SMI_ELEMENTS: | 4366 case FAST_HOLEY_SMI_ELEMENTS: |
4366 case FAST_ELEMENTS: | 4367 case FAST_ELEMENTS: |
4367 case FAST_HOLEY_ELEMENTS: | 4368 case FAST_HOLEY_ELEMENTS: |
4368 case FAST_DOUBLE_ELEMENTS: | 4369 case FAST_DOUBLE_ELEMENTS: |
4369 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 4370 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4403 if (!is_store) return false; | 4404 if (!is_store) return false; |
4404 | 4405 |
4405 // 2nd chance: A store into a non-existent field can still be inlined if we | 4406 // 2nd chance: A store into a non-existent field can still be inlined if we |
4406 // have a matching transition and some room left in the object. | 4407 // have a matching transition and some room left in the object. |
4407 type->LookupTransition(NULL, *name, lookup); | 4408 type->LookupTransition(NULL, *name, lookup); |
4408 return lookup->IsTransitionToField(*type) && | 4409 return lookup->IsTransitionToField(*type) && |
4409 (type->unused_property_fields() > 0); | 4410 (type->unused_property_fields() > 0); |
4410 } | 4411 } |
4411 | 4412 |
4412 | 4413 |
4413 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { | 4414 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, |
| 4415 Handle<Map> map) { |
4414 BuildCheckHeapObject(object); | 4416 BuildCheckHeapObject(object); |
4415 Add<HCheckMaps>(object, map, top_info()); | 4417 return Add<HCheckMaps>(object, map, top_info()); |
4416 } | 4418 } |
4417 | 4419 |
4418 | 4420 |
4419 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 4421 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
4420 HValue* object, | 4422 HValue* object, |
4421 Handle<String> name, | 4423 Handle<String> name, |
4422 HValue* value, | 4424 HValue* value, |
4423 Handle<Map> map, | 4425 Handle<Map> map, |
4424 LookupResult* lookup) { | 4426 LookupResult* lookup) { |
4425 ASSERT(lookup->IsFound()); | 4427 ASSERT(lookup->IsFound()); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4571 // In-objectness did not match. | 4573 // In-objectness did not match. |
4572 break; | 4574 break; |
4573 } | 4575 } |
4574 access = access.WithRepresentation( | 4576 access = access.WithRepresentation( |
4575 access.representation().generalize(new_access.representation())); | 4577 access.representation().generalize(new_access.representation())); |
4576 } | 4578 } |
4577 | 4579 |
4578 if (count == types->length()) { | 4580 if (count == types->length()) { |
4579 // Everything matched; can use monomorphic load. | 4581 // Everything matched; can use monomorphic load. |
4580 BuildCheckHeapObject(object); | 4582 BuildCheckHeapObject(object); |
4581 Add<HCheckMaps>(object, types); | 4583 HCheckMaps* type_check = Add<HCheckMaps>(object, types); |
4582 return BuildLoadNamedField(object, access); | 4584 return BuildLoadNamedField(object, access, type_check); |
4583 } | 4585 } |
4584 | 4586 |
4585 if (count != 0) return NULL; | 4587 if (count != 0) return NULL; |
4586 | 4588 |
4587 // Second chance: the property is on the prototype and all maps have the | 4589 // Second chance: the property is on the prototype and all maps have the |
4588 // same prototype. | 4590 // same prototype. |
4589 Handle<Map> map(types->at(0)); | 4591 Handle<Map> map(types->at(0)); |
4590 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; | 4592 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; |
4591 | 4593 |
4592 Handle<Object> prototype(map->prototype(), isolate()); | 4594 Handle<Object> prototype(map->prototype(), isolate()); |
4593 for (count = 1; count < types->length(); ++count) { | 4595 for (count = 1; count < types->length(); ++count) { |
4594 Handle<Map> test_map(types->at(count)); | 4596 Handle<Map> test_map(types->at(count)); |
4595 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; | 4597 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; |
4596 if (test_map->prototype() != *prototype) return NULL; | 4598 if (test_map->prototype() != *prototype) return NULL; |
4597 } | 4599 } |
4598 | 4600 |
4599 LookupInPrototypes(map, name, &lookup); | 4601 LookupInPrototypes(map, name, &lookup); |
4600 if (!lookup.IsField()) return NULL; | 4602 if (!lookup.IsField()) return NULL; |
4601 | 4603 |
4602 BuildCheckHeapObject(object); | 4604 BuildCheckHeapObject(object); |
4603 Add<HCheckMaps>(object, types); | 4605 HCheckMaps* type_check = Add<HCheckMaps>(object, types); |
4604 | 4606 |
4605 Handle<JSObject> holder(lookup.holder()); | 4607 Handle<JSObject> holder(lookup.holder()); |
4606 Handle<Map> holder_map(holder->map()); | 4608 Handle<Map> holder_map(holder->map()); |
4607 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); | 4609 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); |
4608 HValue* holder_value = Add<HConstant>(holder); | 4610 HValue* holder_value = Add<HConstant>(holder); |
4609 return BuildLoadNamedField(holder_value, | 4611 return BuildLoadNamedField(holder_value, |
4610 HObjectAccess::ForField(holder_map, &lookup, name)); | 4612 HObjectAccess::ForField(holder_map, &lookup, name), type_check); |
4611 } | 4613 } |
4612 | 4614 |
4613 | 4615 |
4614 // Returns true if an instance of this map can never find a property with this | 4616 // Returns true if an instance of this map can never find a property with this |
4615 // name in its prototype chain. This means all prototypes up to the top are | 4617 // name in its prototype chain. This means all prototypes up to the top are |
4616 // fast and don't have the name in them. It would be good if we could optimize | 4618 // fast and don't have the name in them. It would be good if we could optimize |
4617 // polymorphic loads where the property is sometimes found in the prototype | 4619 // polymorphic loads where the property is sometimes found in the prototype |
4618 // chain. | 4620 // chain. |
4619 static bool PrototypeChainCanNeverResolve( | 4621 static bool PrototypeChainCanNeverResolve( |
4620 Handle<Map> map, Handle<String> name) { | 4622 Handle<Map> map, Handle<String> name) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4675 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4677 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
4676 HCompareMap* compare = | 4678 HCompareMap* compare = |
4677 new(zone()) HCompareMap(object, map, if_true, if_false); | 4679 new(zone()) HCompareMap(object, map, if_true, if_false); |
4678 current_block()->Finish(compare); | 4680 current_block()->Finish(compare); |
4679 | 4681 |
4680 set_current_block(if_true); | 4682 set_current_block(if_true); |
4681 | 4683 |
4682 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. | 4684 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. |
4683 if (lookup.IsField()) { | 4685 if (lookup.IsField()) { |
4684 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); | 4686 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); |
4685 HLoadNamedField* load = BuildLoadNamedField(object, access); | 4687 HLoadNamedField* load = BuildLoadNamedField(object, access, compare); |
4686 load->set_position(expr->position()); | 4688 load->set_position(expr->position()); |
4687 AddInstruction(load); | 4689 AddInstruction(load); |
4688 if (!ast_context()->IsEffect()) Push(load); | 4690 if (!ast_context()->IsEffect()) Push(load); |
4689 } else if (lookup.IsConstant()) { | 4691 } else if (lookup.IsConstant()) { |
4690 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 4692 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
4691 HConstant* hconstant = Add<HConstant>(constant); | 4693 HConstant* hconstant = Add<HConstant>(constant); |
4692 if (!ast_context()->IsEffect()) Push(hconstant); | 4694 if (!ast_context()->IsEffect()) Push(hconstant); |
4693 } else { | 4695 } else { |
4694 ASSERT(!lookup.IsFound()); | 4696 ASSERT(!lookup.IsFound()); |
4695 if (map->prototype()->IsJSObject()) { | 4697 if (map->prototype()->IsJSObject()) { |
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5412 HValue* object, | 5414 HValue* object, |
5413 Handle<String> name, | 5415 Handle<String> name, |
5414 Property* expr, | 5416 Property* expr, |
5415 Handle<Map> map) { | 5417 Handle<Map> map) { |
5416 // Handle a load from a known field. | 5418 // Handle a load from a known field. |
5417 ASSERT(!map->is_dictionary_map()); | 5419 ASSERT(!map->is_dictionary_map()); |
5418 | 5420 |
5419 // Handle access to various length properties | 5421 // Handle access to various length properties |
5420 if (name->Equals(isolate()->heap()->length_string())) { | 5422 if (name->Equals(isolate()->heap()->length_string())) { |
5421 if (map->instance_type() == JS_ARRAY_TYPE) { | 5423 if (map->instance_type() == JS_ARRAY_TYPE) { |
5422 AddCheckMap(object, map); | 5424 HCheckMaps* type_check = AddCheckMap(object, map); |
5423 return New<HLoadNamedField>(object, | 5425 return New<HLoadNamedField>(object, |
5424 HObjectAccess::ForArrayLength(map->elements_kind())); | 5426 HObjectAccess::ForArrayLength(map->elements_kind()), type_check); |
5425 } | 5427 } |
5426 } | 5428 } |
5427 | 5429 |
5428 LookupResult lookup(isolate()); | 5430 LookupResult lookup(isolate()); |
5429 map->LookupDescriptor(NULL, *name, &lookup); | 5431 map->LookupDescriptor(NULL, *name, &lookup); |
5430 if (lookup.IsField()) { | 5432 if (lookup.IsField()) { |
5431 AddCheckMap(object, map); | 5433 HCheckMaps* type_check = AddCheckMap(object, map); |
5432 return BuildLoadNamedField(object, | 5434 return BuildLoadNamedField(object, |
5433 HObjectAccess::ForField(map, &lookup, name)); | 5435 HObjectAccess::ForField(map, &lookup, name), type_check); |
5434 } | 5436 } |
5435 | 5437 |
5436 // Handle a load of a constant known function. | 5438 // Handle a load of a constant known function. |
5437 if (lookup.IsConstant()) { | 5439 if (lookup.IsConstant()) { |
5438 AddCheckMap(object, map); | 5440 AddCheckMap(object, map); |
5439 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 5441 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
5440 return New<HConstant>(constant); | 5442 return New<HConstant>(constant); |
5441 } | 5443 } |
5442 | 5444 |
5443 // Handle a load from a known field somewhere in the prototype chain. | 5445 // Handle a load from a known field somewhere in the prototype chain. |
5444 LookupInPrototypes(map, name, &lookup); | 5446 LookupInPrototypes(map, name, &lookup); |
5445 if (lookup.IsField()) { | 5447 if (lookup.IsField()) { |
5446 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5448 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5447 Handle<JSObject> holder(lookup.holder()); | 5449 Handle<JSObject> holder(lookup.holder()); |
5448 Handle<Map> holder_map(holder->map()); | 5450 Handle<Map> holder_map(holder->map()); |
5449 AddCheckMap(object, map); | 5451 HCheckMaps* type_check = AddCheckMap(object, map); |
5450 BuildCheckPrototypeMaps(prototype, holder); | 5452 BuildCheckPrototypeMaps(prototype, holder); |
5451 HValue* holder_value = Add<HConstant>(holder); | 5453 HValue* holder_value = Add<HConstant>(holder); |
5452 return BuildLoadNamedField(holder_value, | 5454 return BuildLoadNamedField(holder_value, |
5453 HObjectAccess::ForField(holder_map, &lookup, name)); | 5455 HObjectAccess::ForField(holder_map, &lookup, name), type_check); |
5454 } | 5456 } |
5455 | 5457 |
5456 // Handle a load of a constant function somewhere in the prototype chain. | 5458 // Handle a load of a constant function somewhere in the prototype chain. |
5457 if (lookup.IsConstant()) { | 5459 if (lookup.IsConstant()) { |
5458 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5460 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5459 Handle<JSObject> holder(lookup.holder()); | 5461 Handle<JSObject> holder(lookup.holder()); |
5460 Handle<Map> holder_map(holder->map()); | 5462 Handle<Map> holder_map(holder->map()); |
5461 AddCheckMap(object, map); | 5463 AddCheckMap(object, map); |
5462 BuildCheckPrototypeMaps(prototype, holder); | 5464 BuildCheckPrototypeMaps(prototype, holder); |
5463 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); | 5465 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
(...skipping 4363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9827 if (ShouldProduceTraceOutput()) { | 9829 if (ShouldProduceTraceOutput()) { |
9828 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9830 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9829 } | 9831 } |
9830 | 9832 |
9831 #ifdef DEBUG | 9833 #ifdef DEBUG |
9832 graph_->Verify(false); // No full verify. | 9834 graph_->Verify(false); // No full verify. |
9833 #endif | 9835 #endif |
9834 } | 9836 } |
9835 | 9837 |
9836 } } // namespace v8::internal | 9838 } } // namespace v8::internal |
OLD | NEW |