| 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 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 1027 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 1028 ASSERT(current_block() != NULL); | 1028 ASSERT(current_block() != NULL); |
| 1029 current_block()->AddInstruction(instr); | 1029 current_block()->AddInstruction(instr); |
| 1030 if (graph()->IsInsideNoSideEffectsScope()) { | 1030 if (graph()->IsInsideNoSideEffectsScope()) { |
| 1031 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 1031 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
| 1032 } | 1032 } |
| 1033 return instr; | 1033 return instr; |
| 1034 } | 1034 } |
| 1035 | 1035 |
| 1036 | 1036 |
| 1037 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, | 1037 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
| 1038 HValue* context) { | |
| 1039 if (FLAG_native_code_counters && counter->Enabled()) { | 1038 if (FLAG_native_code_counters && counter->Enabled()) { |
| 1040 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 1039 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
| 1041 HValue* old_value = Add<HLoadNamedField>(reference, | 1040 HValue* old_value = Add<HLoadNamedField>(reference, |
| 1042 HObjectAccess::ForCounter()); | 1041 HObjectAccess::ForCounter()); |
| 1043 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); | 1042 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); |
| 1044 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 1043 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
| 1045 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), | 1044 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
| 1046 new_value); | 1045 new_value); |
| 1047 } | 1046 } |
| 1048 } | 1047 } |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1819 } | 1818 } |
| 1820 } | 1819 } |
| 1821 | 1820 |
| 1822 if_nil.CaptureContinuation(continuation); | 1821 if_nil.CaptureContinuation(continuation); |
| 1823 } | 1822 } |
| 1824 | 1823 |
| 1825 | 1824 |
| 1826 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, | 1825 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, |
| 1827 int previous_object_size, | 1826 int previous_object_size, |
| 1828 HValue* alloc_site) { | 1827 HValue* alloc_site) { |
| 1829 // TODO(mvstanton): ASSERT altered to CHECK to diagnose chromium bug 284577 | 1828 ASSERT(alloc_site != NULL); |
| 1830 CHECK(alloc_site != NULL); | |
| 1831 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( | 1829 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( |
| 1832 previous_object, previous_object_size); | 1830 previous_object, previous_object_size); |
| 1833 Handle<Map> alloc_memento_map( | 1831 Handle<Map> alloc_memento_map( |
| 1834 isolate()->heap()->allocation_memento_map()); | 1832 isolate()->heap()->allocation_memento_map()); |
| 1835 AddStoreMapConstant(alloc_memento, alloc_memento_map); | 1833 AddStoreMapConstant(alloc_memento, alloc_memento_map); |
| 1836 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); | 1834 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); |
| 1837 Add<HStoreNamedField>(alloc_memento, access, alloc_site); | 1835 Add<HStoreNamedField>(alloc_memento, access, alloc_site); |
| 1838 return alloc_memento; | 1836 return alloc_memento; |
| 1839 } | 1837 } |
| 1840 | 1838 |
| (...skipping 2159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4000 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 3998 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
| 4001 literals, | 3999 literals, |
| 4002 expr->pattern(), | 4000 expr->pattern(), |
| 4003 expr->flags(), | 4001 expr->flags(), |
| 4004 expr->literal_index()); | 4002 expr->literal_index()); |
| 4005 return ast_context()->ReturnInstruction(instr, expr->id()); | 4003 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4006 } | 4004 } |
| 4007 | 4005 |
| 4008 | 4006 |
| 4009 static bool CanInlinePropertyAccess(Map* type) { | 4007 static bool CanInlinePropertyAccess(Map* type) { |
| 4010 return !type->is_dictionary_map() && !type->has_named_interceptor(); | 4008 return type->IsJSObjectMap() && |
| 4009 !type->is_dictionary_map() && |
| 4010 !type->has_named_interceptor(); |
| 4011 } | 4011 } |
| 4012 | 4012 |
| 4013 | 4013 |
| 4014 static void LookupInPrototypes(Handle<Map> map, | 4014 static void LookupInPrototypes(Handle<Map> map, |
| 4015 Handle<String> name, | 4015 Handle<String> name, |
| 4016 LookupResult* lookup) { | 4016 LookupResult* lookup) { |
| 4017 while (map->prototype()->IsJSObject()) { | 4017 while (map->prototype()->IsJSObject()) { |
| 4018 Handle<JSObject> holder(JSObject::cast(map->prototype())); | 4018 Handle<JSObject> holder(JSObject::cast(map->prototype())); |
| 4019 map = Handle<Map>(holder->map()); | 4019 map = Handle<Map>(holder->map()); |
| 4020 if (!CanInlinePropertyAccess(*map)) break; | 4020 if (!CanInlinePropertyAccess(*map)) break; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4165 HInstruction* literal; | 4165 HInstruction* literal; |
| 4166 | 4166 |
| 4167 // Check whether to use fast or slow deep-copying for boilerplate. | 4167 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4168 int max_properties = kMaxFastLiteralProperties; | 4168 int max_properties = kMaxFastLiteralProperties; |
| 4169 Handle<Object> boilerplate(closure->literals()->get( | 4169 Handle<Object> boilerplate(closure->literals()->get( |
| 4170 expr->literal_index()), isolate()); | 4170 expr->literal_index()), isolate()); |
| 4171 if (boilerplate->IsJSObject() && | 4171 if (boilerplate->IsJSObject() && |
| 4172 IsFastLiteral(Handle<JSObject>::cast(boilerplate), | 4172 IsFastLiteral(Handle<JSObject>::cast(boilerplate), |
| 4173 kMaxFastLiteralDepth, | 4173 kMaxFastLiteralDepth, |
| 4174 &max_properties)) { | 4174 &max_properties)) { |
| 4175 Handle<JSObject> boilerplate_object = | 4175 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); |
| 4176 Handle<JSObject>::cast(boilerplate); | |
| 4177 | 4176 |
| 4178 literal = BuildFastLiteral(boilerplate_object, | 4177 literal = BuildFastLiteral(boilerplate_object, |
| 4179 Handle<Object>::null(), | 4178 Handle<Object>::null(), |
| 4180 DONT_TRACK_ALLOCATION_SITE); | 4179 DONT_TRACK_ALLOCATION_SITE); |
| 4181 } else { | 4180 } else { |
| 4182 NoObservableSideEffectsScope no_effects(this); | 4181 NoObservableSideEffectsScope no_effects(this); |
| 4183 Handle<FixedArray> closure_literals(closure->literals(), isolate()); | 4182 Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
| 4184 Handle<FixedArray> constant_properties = expr->constant_properties(); | 4183 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 4185 int literal_index = expr->literal_index(); | 4184 int literal_index = expr->literal_index(); |
| 4186 int flags = expr->fast_elements() | 4185 int flags = expr->fast_elements() |
| (...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5129 | 5128 |
| 5130 case Variable::LOOKUP: | 5129 case Variable::LOOKUP: |
| 5131 return Bailout(kCompoundAssignmentToLookupSlot); | 5130 return Bailout(kCompoundAssignmentToLookupSlot); |
| 5132 } | 5131 } |
| 5133 return ast_context()->ReturnValue(Pop()); | 5132 return ast_context()->ReturnValue(Pop()); |
| 5134 | 5133 |
| 5135 } else if (prop != NULL) { | 5134 } else if (prop != NULL) { |
| 5136 CHECK_ALIVE(VisitForValue(prop->obj())); | 5135 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5137 HValue* object = Top(); | 5136 HValue* object = Top(); |
| 5138 HValue* key = NULL; | 5137 HValue* key = NULL; |
| 5139 if ((!prop->IsStringLength() && | 5138 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || |
| 5140 !prop->IsFunctionPrototype() && | |
| 5141 !prop->key()->IsPropertyName()) || | |
| 5142 prop->IsStringAccess()) { | 5139 prop->IsStringAccess()) { |
| 5143 CHECK_ALIVE(VisitForValue(prop->key())); | 5140 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5144 key = Top(); | 5141 key = Top(); |
| 5145 } | 5142 } |
| 5146 | 5143 |
| 5147 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); | 5144 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); |
| 5148 | 5145 |
| 5149 CHECK_ALIVE(VisitForValue(expr->value())); | 5146 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5150 HValue* right = Pop(); | 5147 HValue* right = Pop(); |
| 5151 HValue* left = Pop(); | 5148 HValue* left = Pop(); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5376 HCheckMaps* checked_object = AddCheckMap(object, map); | 5373 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 5377 return New<HLoadNamedField>( | 5374 return New<HLoadNamedField>( |
| 5378 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); | 5375 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); |
| 5379 } | 5376 } |
| 5380 } | 5377 } |
| 5381 | 5378 |
| 5382 LookupResult lookup(isolate()); | 5379 LookupResult lookup(isolate()); |
| 5383 map->LookupDescriptor(NULL, *name, &lookup); | 5380 map->LookupDescriptor(NULL, *name, &lookup); |
| 5384 if (lookup.IsField()) { | 5381 if (lookup.IsField()) { |
| 5385 HCheckMaps* checked_object = AddCheckMap(object, map); | 5382 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 5383 ASSERT(map->IsJSObjectMap()); |
| 5386 return BuildLoadNamedField( | 5384 return BuildLoadNamedField( |
| 5387 checked_object, HObjectAccess::ForField(map, &lookup, name)); | 5385 checked_object, HObjectAccess::ForField(map, &lookup, name)); |
| 5388 } | 5386 } |
| 5389 | 5387 |
| 5390 // Handle a load of a constant known function. | 5388 // Handle a load of a constant known function. |
| 5391 if (lookup.IsConstant()) { | 5389 if (lookup.IsConstant()) { |
| 5392 AddCheckMap(object, map); | 5390 AddCheckMap(object, map); |
| 5393 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 5391 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
| 5394 return New<HConstant>(constant); | 5392 return New<HConstant>(constant); |
| 5395 } | 5393 } |
| 5396 | 5394 |
| 5395 if (lookup.IsFound()) { |
| 5396 // Cannot handle the property, do a generic load instead. |
| 5397 HValue* context = environment()->context(); |
| 5398 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 5399 } |
| 5400 |
| 5397 // Handle a load from a known field somewhere in the prototype chain. | 5401 // Handle a load from a known field somewhere in the prototype chain. |
| 5398 LookupInPrototypes(map, name, &lookup); | 5402 LookupInPrototypes(map, name, &lookup); |
| 5399 if (lookup.IsField()) { | 5403 if (lookup.IsField()) { |
| 5400 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5404 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 5401 Handle<JSObject> holder(lookup.holder()); | 5405 Handle<JSObject> holder(lookup.holder()); |
| 5402 Handle<Map> holder_map(holder->map()); | 5406 Handle<Map> holder_map(holder->map()); |
| 5403 AddCheckMap(object, map); | 5407 AddCheckMap(object, map); |
| 5404 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder); | 5408 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder); |
| 5405 return BuildLoadNamedField( | 5409 return BuildLoadNamedField( |
| 5406 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name)); | 5410 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name)); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5479 // much faster than transitioning the elements to the worst case, trading a | 5483 // much faster than transitioning the elements to the worst case, trading a |
| 5480 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. | 5484 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. |
| 5481 bool has_double_maps = false; | 5485 bool has_double_maps = false; |
| 5482 bool has_smi_or_object_maps = false; | 5486 bool has_smi_or_object_maps = false; |
| 5483 bool has_js_array_access = false; | 5487 bool has_js_array_access = false; |
| 5484 bool has_non_js_array_access = false; | 5488 bool has_non_js_array_access = false; |
| 5485 bool has_seen_holey_elements = false; | 5489 bool has_seen_holey_elements = false; |
| 5486 Handle<Map> most_general_consolidated_map; | 5490 Handle<Map> most_general_consolidated_map; |
| 5487 for (int i = 0; i < maps->length(); ++i) { | 5491 for (int i = 0; i < maps->length(); ++i) { |
| 5488 Handle<Map> map = maps->at(i); | 5492 Handle<Map> map = maps->at(i); |
| 5493 if (!map->IsJSObjectMap()) return NULL; |
| 5489 // Don't allow mixing of JSArrays with JSObjects. | 5494 // Don't allow mixing of JSArrays with JSObjects. |
| 5490 if (map->instance_type() == JS_ARRAY_TYPE) { | 5495 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 5491 if (has_non_js_array_access) return NULL; | 5496 if (has_non_js_array_access) return NULL; |
| 5492 has_js_array_access = true; | 5497 has_js_array_access = true; |
| 5493 } else if (has_js_array_access) { | 5498 } else if (has_js_array_access) { |
| 5494 return NULL; | 5499 return NULL; |
| 5495 } else { | 5500 } else { |
| 5496 has_non_js_array_access = true; | 5501 has_non_js_array_access = true; |
| 5497 } | 5502 } |
| 5498 // Don't allow mixed, incompatible elements kinds. | 5503 // Don't allow mixed, incompatible elements kinds. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5531 consolidated_elements_kind, | 5536 consolidated_elements_kind, |
| 5532 false, NEVER_RETURN_HOLE, STANDARD_STORE); | 5537 false, NEVER_RETURN_HOLE, STANDARD_STORE); |
| 5533 return instr; | 5538 return instr; |
| 5534 } | 5539 } |
| 5535 | 5540 |
| 5536 | 5541 |
| 5537 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 5542 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
| 5538 HValue* object, | 5543 HValue* object, |
| 5539 HValue* key, | 5544 HValue* key, |
| 5540 HValue* val, | 5545 HValue* val, |
| 5541 Expression* prop, | 5546 SmallMapList* maps, |
| 5542 BailoutId ast_id, | 5547 BailoutId ast_id, |
| 5543 int position, | 5548 int position, |
| 5544 bool is_store, | 5549 bool is_store, |
| 5545 KeyedAccessStoreMode store_mode, | 5550 KeyedAccessStoreMode store_mode, |
| 5546 bool* has_side_effects) { | 5551 bool* has_side_effects) { |
| 5547 *has_side_effects = false; | 5552 *has_side_effects = false; |
| 5548 BuildCheckHeapObject(object); | 5553 BuildCheckHeapObject(object); |
| 5549 SmallMapList* maps = prop->GetReceiverTypes(); | |
| 5550 | 5554 |
| 5551 if (!is_store) { | 5555 if (!is_store) { |
| 5552 HInstruction* consolidated_load = | 5556 HInstruction* consolidated_load = |
| 5553 TryBuildConsolidatedElementLoad(object, key, val, maps); | 5557 TryBuildConsolidatedElementLoad(object, key, val, maps); |
| 5554 if (consolidated_load != NULL) { | 5558 if (consolidated_load != NULL) { |
| 5555 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 5559 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
| 5556 if (position != RelocInfo::kNoPosition) { | 5560 if (position != RelocInfo::kNoPosition) { |
| 5557 consolidated_load->set_position(position); | 5561 consolidated_load->set_position(position); |
| 5558 } | 5562 } |
| 5559 return consolidated_load; | 5563 return consolidated_load; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5595 untransitionable_maps.Add(map); | 5599 untransitionable_maps.Add(map); |
| 5596 } | 5600 } |
| 5597 } | 5601 } |
| 5598 | 5602 |
| 5599 // If only one map is left after transitioning, handle this case | 5603 // If only one map is left after transitioning, handle this case |
| 5600 // monomorphically. | 5604 // monomorphically. |
| 5601 ASSERT(untransitionable_maps.length() >= 1); | 5605 ASSERT(untransitionable_maps.length() >= 1); |
| 5602 if (untransitionable_maps.length() == 1) { | 5606 if (untransitionable_maps.length() == 1) { |
| 5603 Handle<Map> untransitionable_map = untransitionable_maps[0]; | 5607 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
| 5604 HInstruction* instr = NULL; | 5608 HInstruction* instr = NULL; |
| 5605 if (untransitionable_map->has_slow_elements_kind()) { | 5609 if (untransitionable_map->has_slow_elements_kind() || |
| 5610 !untransitionable_map->IsJSObjectMap()) { |
| 5606 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 5611 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
| 5607 : BuildLoadKeyedGeneric(object, key)); | 5612 : BuildLoadKeyedGeneric(object, key)); |
| 5608 } else { | 5613 } else { |
| 5609 instr = BuildMonomorphicElementAccess( | 5614 instr = BuildMonomorphicElementAccess( |
| 5610 object, key, val, transition, untransitionable_map, is_store, | 5615 object, key, val, transition, untransitionable_map, is_store, |
| 5611 store_mode); | 5616 store_mode); |
| 5612 } | 5617 } |
| 5613 *has_side_effects |= instr->HasObservableSideEffects(); | 5618 *has_side_effects |= instr->HasObservableSideEffects(); |
| 5614 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5619 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 5615 return is_store ? NULL : instr; | 5620 return is_store ? NULL : instr; |
| 5616 } | 5621 } |
| 5617 | 5622 |
| 5618 HBasicBlock* join = graph()->CreateBasicBlock(); | 5623 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 5619 | 5624 |
| 5620 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 5625 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
| 5621 Handle<Map> map = untransitionable_maps[i]; | 5626 Handle<Map> map = untransitionable_maps[i]; |
| 5627 if (!map->IsJSObjectMap()) continue; |
| 5622 ElementsKind elements_kind = map->elements_kind(); | 5628 ElementsKind elements_kind = map->elements_kind(); |
| 5623 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 5629 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
| 5624 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 5630 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
| 5625 HCompareMap* mapcompare = | 5631 HCompareMap* mapcompare = |
| 5626 new(zone()) HCompareMap(object, map, this_map, other_map); | 5632 new(zone()) HCompareMap(object, map, this_map, other_map); |
| 5627 current_block()->Finish(mapcompare); | 5633 current_block()->Finish(mapcompare); |
| 5628 | 5634 |
| 5629 set_current_block(this_map); | 5635 set_current_block(this_map); |
| 5630 HInstruction* access = NULL; | 5636 HInstruction* access = NULL; |
| 5631 if (IsDictionaryElementsKind(elements_kind)) { | 5637 if (IsDictionaryElementsKind(elements_kind)) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5684 Handle<Map> map = types->first(); | 5690 Handle<Map> map = types->first(); |
| 5685 if (map->has_slow_elements_kind()) { | 5691 if (map->has_slow_elements_kind()) { |
| 5686 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 5692 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
| 5687 : BuildLoadKeyedGeneric(obj, key); | 5693 : BuildLoadKeyedGeneric(obj, key); |
| 5688 AddInstruction(instr); | 5694 AddInstruction(instr); |
| 5689 } else { | 5695 } else { |
| 5690 BuildCheckHeapObject(obj); | 5696 BuildCheckHeapObject(obj); |
| 5691 instr = BuildMonomorphicElementAccess( | 5697 instr = BuildMonomorphicElementAccess( |
| 5692 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5698 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
| 5693 } | 5699 } |
| 5694 } else if (expr->GetReceiverTypes() != NULL && | 5700 } else if (types != NULL && !types->is_empty()) { |
| 5695 !expr->GetReceiverTypes()->is_empty()) { | |
| 5696 return HandlePolymorphicElementAccess( | 5701 return HandlePolymorphicElementAccess( |
| 5697 obj, key, val, expr, ast_id, position, is_store, | 5702 obj, key, val, types, ast_id, position, is_store, |
| 5698 expr->GetStoreMode(), has_side_effects); | 5703 expr->GetStoreMode(), has_side_effects); |
| 5699 } else { | 5704 } else { |
| 5700 if (is_store) { | 5705 if (is_store) { |
| 5701 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5706 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
| 5702 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 5707 Add<HDeoptimize>("Insufficient type feedback for keyed store", |
| 5703 Deoptimizer::SOFT); | 5708 Deoptimizer::SOFT); |
| 5704 } | 5709 } |
| 5705 instr = BuildStoreKeyedGeneric(obj, key, val); | 5710 instr = BuildStoreKeyedGeneric(obj, key, val); |
| 5706 } else { | 5711 } else { |
| 5707 if (expr->AsProperty()->IsUninitialized()) { | 5712 if (expr->AsProperty()->IsUninitialized()) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5813 HValue* object, | 5818 HValue* object, |
| 5814 HValue* key, | 5819 HValue* key, |
| 5815 int position) { | 5820 int position) { |
| 5816 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 5821 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
| 5817 Push(object); | 5822 Push(object); |
| 5818 if (key != NULL) Push(key); | 5823 if (key != NULL) Push(key); |
| 5819 BuildLoad(expr, position, expr->LoadId()); | 5824 BuildLoad(expr, position, expr->LoadId()); |
| 5820 } | 5825 } |
| 5821 | 5826 |
| 5822 | 5827 |
| 5828 static bool AreStringTypes(SmallMapList* types) { |
| 5829 if (types == NULL || types->length() == 0) return false; |
| 5830 for (int i = 0; i < types->length(); i++) { |
| 5831 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
| 5832 } |
| 5833 return true; |
| 5834 } |
| 5835 |
| 5836 |
| 5823 void HOptimizedGraphBuilder::BuildLoad(Property* expr, | 5837 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
| 5824 int position, | 5838 int position, |
| 5825 BailoutId ast_id) { | 5839 BailoutId ast_id) { |
| 5826 HInstruction* instr = NULL; | 5840 HInstruction* instr = NULL; |
| 5827 if (expr->IsStringLength()) { | 5841 if (expr->IsStringAccess()) { |
| 5828 HValue* string = Pop(); | |
| 5829 BuildCheckHeapObject(string); | |
| 5830 HInstruction* checkstring = | |
| 5831 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | |
| 5832 instr = BuildLoadStringLength(string, checkstring); | |
| 5833 } else if (expr->IsStringAccess()) { | |
| 5834 HValue* index = Pop(); | 5842 HValue* index = Pop(); |
| 5835 HValue* string = Pop(); | 5843 HValue* string = Pop(); |
| 5836 HValue* context = environment()->context(); | 5844 HValue* context = environment()->context(); |
| 5837 HInstruction* char_code = | 5845 HInstruction* char_code = |
| 5838 BuildStringCharCodeAt(string, index); | 5846 BuildStringCharCodeAt(string, index); |
| 5839 AddInstruction(char_code); | 5847 AddInstruction(char_code); |
| 5840 instr = HStringCharFromCode::New(zone(), context, char_code); | 5848 instr = HStringCharFromCode::New(zone(), context, char_code); |
| 5841 | 5849 |
| 5842 } else if (expr->IsFunctionPrototype()) { | 5850 } else if (expr->IsFunctionPrototype()) { |
| 5843 HValue* function = Pop(); | 5851 HValue* function = Pop(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5859 AddCheckConstantFunction(holder, Top(), map); | 5867 AddCheckConstantFunction(holder, Top(), map); |
| 5860 if (FLAG_inline_accessors && | 5868 if (FLAG_inline_accessors && |
| 5861 TryInlineGetter(getter, ast_id, expr->LoadId())) { | 5869 TryInlineGetter(getter, ast_id, expr->LoadId())) { |
| 5862 return; | 5870 return; |
| 5863 } | 5871 } |
| 5864 Add<HPushArgument>(Pop()); | 5872 Add<HPushArgument>(Pop()); |
| 5865 instr = new(zone()) HCallConstantFunction(getter, 1); | 5873 instr = new(zone()) HCallConstantFunction(getter, 1); |
| 5866 } else { | 5874 } else { |
| 5867 instr = BuildLoadNamedMonomorphic(Pop(), name, map); | 5875 instr = BuildLoadNamedMonomorphic(Pop(), name, map); |
| 5868 } | 5876 } |
| 5877 } else if (AreStringTypes(types) && |
| 5878 name->Equals(isolate()->heap()->length_string())) { |
| 5879 BuildCheckHeapObject(Pop()); |
| 5880 HValue* checked_object = |
| 5881 AddInstruction(HCheckInstanceType::NewIsString(object, zone())); |
| 5882 instr = BuildLoadStringLength(object, checked_object); |
| 5869 } else if (types != NULL && types->length() > 1) { | 5883 } else if (types != NULL && types->length() > 1) { |
| 5870 return HandlePolymorphicLoadNamedField( | 5884 return HandlePolymorphicLoadNamedField( |
| 5871 position, ast_id, Pop(), types, name); | 5885 position, ast_id, Pop(), types, name); |
| 5872 } else { | 5886 } else { |
| 5873 instr = BuildLoadNamedGeneric(Pop(), name, expr); | 5887 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
| 5874 } | 5888 } |
| 5875 | 5889 |
| 5876 } else { | 5890 } else { |
| 5877 HValue* key = Pop(); | 5891 HValue* key = Pop(); |
| 5878 HValue* obj = Pop(); | 5892 HValue* obj = Pop(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5899 | 5913 |
| 5900 | 5914 |
| 5901 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 5915 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
| 5902 ASSERT(!HasStackOverflow()); | 5916 ASSERT(!HasStackOverflow()); |
| 5903 ASSERT(current_block() != NULL); | 5917 ASSERT(current_block() != NULL); |
| 5904 ASSERT(current_block()->HasPredecessor()); | 5918 ASSERT(current_block()->HasPredecessor()); |
| 5905 | 5919 |
| 5906 if (TryArgumentsAccess(expr)) return; | 5920 if (TryArgumentsAccess(expr)) return; |
| 5907 | 5921 |
| 5908 CHECK_ALIVE(VisitForValue(expr->obj())); | 5922 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 5909 if ((!expr->IsStringLength() && | 5923 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || |
| 5910 !expr->IsFunctionPrototype() && | |
| 5911 !expr->key()->IsPropertyName()) || | |
| 5912 expr->IsStringAccess()) { | 5924 expr->IsStringAccess()) { |
| 5913 CHECK_ALIVE(VisitForValue(expr->key())); | 5925 CHECK_ALIVE(VisitForValue(expr->key())); |
| 5914 } | 5926 } |
| 5915 | 5927 |
| 5916 BuildLoad(expr, expr->position(), expr->id()); | 5928 BuildLoad(expr, expr->position(), expr->id()); |
| 5917 } | 5929 } |
| 5918 | 5930 |
| 5919 | 5931 |
| 5920 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 5932 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
| 5921 CompilationInfo* info) { | 5933 CompilationInfo* info) { |
| (...skipping 1630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7552 } | 7564 } |
| 7553 | 7565 |
| 7554 // Argument of the count operation is a property. | 7566 // Argument of the count operation is a property. |
| 7555 ASSERT(prop != NULL); | 7567 ASSERT(prop != NULL); |
| 7556 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7568 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 7557 | 7569 |
| 7558 CHECK_ALIVE(VisitForValue(prop->obj())); | 7570 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7559 HValue* object = Top(); | 7571 HValue* object = Top(); |
| 7560 | 7572 |
| 7561 HValue* key = NULL; | 7573 HValue* key = NULL; |
| 7562 if ((!prop->IsStringLength() && | 7574 if ((!prop->IsFunctionPrototype() && !prop->key()->IsPropertyName()) || |
| 7563 !prop->IsFunctionPrototype() && | |
| 7564 !prop->key()->IsPropertyName()) || | |
| 7565 prop->IsStringAccess()) { | 7575 prop->IsStringAccess()) { |
| 7566 CHECK_ALIVE(VisitForValue(prop->key())); | 7576 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7567 key = Top(); | 7577 key = Top(); |
| 7568 } | 7578 } |
| 7569 | 7579 |
| 7570 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); | 7580 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); |
| 7571 | 7581 |
| 7572 after = BuildIncrement(returns_original_input, expr); | 7582 after = BuildIncrement(returns_original_input, expr); |
| 7573 | 7583 |
| 7574 if (returns_original_input) { | 7584 if (returns_original_input) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 7604 BuildCheckHeapObject(string); | 7614 BuildCheckHeapObject(string); |
| 7605 HValue* checkstring = | 7615 HValue* checkstring = |
| 7606 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 7616 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 7607 HInstruction* length = BuildLoadStringLength(string, checkstring); | 7617 HInstruction* length = BuildLoadStringLength(string, checkstring); |
| 7608 AddInstruction(length); | 7618 AddInstruction(length); |
| 7609 HInstruction* checked_index = Add<HBoundsCheck>(index, length); | 7619 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
| 7610 return New<HStringCharCodeAt>(string, checked_index); | 7620 return New<HStringCharCodeAt>(string, checked_index); |
| 7611 } | 7621 } |
| 7612 | 7622 |
| 7613 | 7623 |
| 7614 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 7624 // Checks if the given shift amounts have following forms: |
| 7625 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa). |
| 7615 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 7626 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
| 7616 HValue* const32_minus_sa) { | 7627 HValue* const32_minus_sa) { |
| 7628 if (sa->IsConstant() && const32_minus_sa->IsConstant()) { |
| 7629 const HConstant* c1 = HConstant::cast(sa); |
| 7630 const HConstant* c2 = HConstant::cast(const32_minus_sa); |
| 7631 return c1->HasInteger32Value() && c2->HasInteger32Value() && |
| 7632 (c1->Integer32Value() + c2->Integer32Value() == 32); |
| 7633 } |
| 7617 if (!const32_minus_sa->IsSub()) return false; | 7634 if (!const32_minus_sa->IsSub()) return false; |
| 7618 HSub* sub = HSub::cast(const32_minus_sa); | 7635 HSub* sub = HSub::cast(const32_minus_sa); |
| 7619 if (sa != sub->right()) return false; | 7636 if (sa != sub->right()) return false; |
| 7620 HValue* const32 = sub->left(); | 7637 HValue* const32 = sub->left(); |
| 7621 if (!const32->IsConstant() || | 7638 if (!const32->IsConstant() || |
| 7622 HConstant::cast(const32)->Integer32Value() != 32) { | 7639 HConstant::cast(const32)->Integer32Value() != 32) { |
| 7623 return false; | 7640 return false; |
| 7624 } | 7641 } |
| 7625 return (sub->right() == sa); | 7642 return (sub->right() == sa); |
| 7626 } | 7643 } |
| (...skipping 2055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9682 if (ShouldProduceTraceOutput()) { | 9699 if (ShouldProduceTraceOutput()) { |
| 9683 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9700 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9684 } | 9701 } |
| 9685 | 9702 |
| 9686 #ifdef DEBUG | 9703 #ifdef DEBUG |
| 9687 graph_->Verify(false); // No full verify. | 9704 graph_->Verify(false); // No full verify. |
| 9688 #endif | 9705 #endif |
| 9689 } | 9706 } |
| 9690 | 9707 |
| 9691 } } // namespace v8::internal | 9708 } } // namespace v8::internal |
| OLD | NEW |