OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 6595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6606 ASSERT(current_block() != NULL); | 6606 ASSERT(current_block() != NULL); |
6607 ASSERT(current_block()->HasPredecessor()); | 6607 ASSERT(current_block()->HasPredecessor()); |
6608 expr->RecordTypeFeedback(oracle(), zone()); | 6608 expr->RecordTypeFeedback(oracle(), zone()); |
6609 | 6609 |
6610 if (TryArgumentsAccess(expr)) return; | 6610 if (TryArgumentsAccess(expr)) return; |
6611 | 6611 |
6612 CHECK_ALIVE(VisitForValue(expr->obj())); | 6612 CHECK_ALIVE(VisitForValue(expr->obj())); |
6613 | 6613 |
6614 HInstruction* instr = NULL; | 6614 HInstruction* instr = NULL; |
6615 if (expr->AsProperty()->IsArrayLength()) { | 6615 if (expr->AsProperty()->IsArrayLength()) { |
| 6616 // Note that in the monomorphic case IsArrayLength() is false because we |
| 6617 // handle that it with a regular property load IC. |
6616 HValue* array = Pop(); | 6618 HValue* array = Pop(); |
6617 AddInstruction(new(zone()) HCheckNonSmi(array)); | 6619 AddInstruction(new(zone()) HCheckNonSmi(array)); |
6618 HInstruction* mapcheck = | 6620 HInstruction* mapcheck = |
6619 AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone())); | 6621 AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone())); |
6620 instr = new(zone()) HJSArrayLength(array, mapcheck); | 6622 instr = new(zone()) HJSArrayLength(array, mapcheck); |
6621 } else if (expr->IsStringLength()) { | 6623 } else if (expr->IsStringLength()) { |
6622 HValue* string = Pop(); | 6624 HValue* string = Pop(); |
6623 AddInstruction(new(zone()) HCheckNonSmi(string)); | 6625 AddInstruction(new(zone()) HCheckNonSmi(string)); |
6624 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 6626 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
6625 instr = new(zone()) HStringLength(string); | 6627 instr = new(zone()) HStringLength(string); |
(...skipping 15 matching lines...) Expand all Loading... |
6641 } else if (expr->key()->IsPropertyName()) { | 6643 } else if (expr->key()->IsPropertyName()) { |
6642 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6644 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
6643 SmallMapList* types = expr->GetReceiverTypes(); | 6645 SmallMapList* types = expr->GetReceiverTypes(); |
6644 | 6646 |
6645 bool monomorphic = expr->IsMonomorphic(); | 6647 bool monomorphic = expr->IsMonomorphic(); |
6646 Handle<Map> map; | 6648 Handle<Map> map; |
6647 if (expr->IsMonomorphic()) { | 6649 if (expr->IsMonomorphic()) { |
6648 map = types->first(); | 6650 map = types->first(); |
6649 if (map->is_dictionary_map()) monomorphic = false; | 6651 if (map->is_dictionary_map()) monomorphic = false; |
6650 } | 6652 } |
6651 if (monomorphic) { | 6653 |
6652 Handle<JSFunction> getter; | 6654 // Try to see if this is an array length access. |
6653 Handle<JSObject> holder; | 6655 if (name->Equals(isolate()->heap()->length_symbol())) { |
6654 if (LookupGetter(map, name, &getter, &holder)) { | 6656 bool is_array = false; |
6655 AddCheckConstantFunction(holder, Top(), map); | 6657 bool fast_mode = false; |
6656 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; | 6658 bool map_mode = false; |
6657 AddInstruction(new(zone()) HPushArgument(Pop())); | 6659 HInstruction* mapcheck = NULL; |
6658 instr = new(zone()) HCallConstantFunction(getter, 1); | 6660 |
| 6661 if (expr->IsMonomorphic()) { |
| 6662 // Even if there is more than one map they all must be element |
| 6663 // transition maps, so checking just one is ok. |
| 6664 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 6665 is_array = true; |
| 6666 map_mode = true; |
| 6667 fast_mode = IsFastElementsKind(map->elements_kind()); |
| 6668 } |
6659 } else { | 6669 } else { |
6660 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); | 6670 // Since we will emit an instance check we have to conservatively |
| 6671 // assume that some arrays will contain slow elements, so we set |
| 6672 // fast_mode to false. |
| 6673 map_mode = false; |
| 6674 fast_mode = false; |
| 6675 is_array = true; |
| 6676 for (int i = 0; i < types->length(); i++) { |
| 6677 Handle<Map> current_map = types->at(i); |
| 6678 if (!current_map->instance_type() == JS_ARRAY_TYPE) { |
| 6679 is_array = false; |
| 6680 break; |
| 6681 } |
| 6682 } |
6661 } | 6683 } |
6662 } else if (types != NULL && types->length() > 1) { | 6684 |
6663 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); | 6685 // It is an array length access so we produce a HJSArrayLength. |
6664 } else { | 6686 if (is_array) { |
6665 instr = BuildLoadNamedGeneric(Pop(), name, expr); | 6687 HValue* array = Pop(); |
| 6688 AddInstruction(new(zone()) HCheckNonSmi(array)); |
| 6689 mapcheck = map_mode ? |
| 6690 HInstruction::cast( |
| 6691 new(zone()) HCheckMaps(array, map, zone(), NULL, |
| 6692 ALLOW_ELEMENT_TRANSITION_MAPS)) : |
| 6693 HInstruction::cast( |
| 6694 HCheckInstanceType::NewIsJSArray(array, zone())); |
| 6695 AddInstruction(mapcheck); |
| 6696 instr = new(zone()) HJSArrayLength( |
| 6697 array, mapcheck, fast_mode ? HType::Smi() : HType::Tagged()); |
| 6698 } |
6666 } | 6699 } |
6667 | 6700 |
| 6701 // We cannot know if it was an array length access so we handle it as |
| 6702 // a regular property access. |
| 6703 if (instr == NULL) { |
| 6704 if (monomorphic) { |
| 6705 Handle<JSFunction> getter; |
| 6706 Handle<JSObject> holder; |
| 6707 if (LookupGetter(map, name, &getter, &holder)) { |
| 6708 AddCheckConstantFunction(holder, Top(), map); |
| 6709 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
| 6710 AddInstruction(new(zone()) HPushArgument(Pop())); |
| 6711 instr = new(zone()) HCallConstantFunction(getter, 1); |
| 6712 } else { |
| 6713 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); |
| 6714 } |
| 6715 } else if (types != NULL && types->length() > 1) { |
| 6716 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); |
| 6717 } else { |
| 6718 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
| 6719 } |
| 6720 } |
6668 } else { | 6721 } else { |
6669 CHECK_ALIVE(VisitForValue(expr->key())); | 6722 CHECK_ALIVE(VisitForValue(expr->key())); |
6670 | 6723 |
6671 HValue* key = Pop(); | 6724 HValue* key = Pop(); |
6672 HValue* obj = Pop(); | 6725 HValue* obj = Pop(); |
6673 | 6726 |
6674 bool has_side_effects = false; | 6727 bool has_side_effects = false; |
6675 HValue* load = HandleKeyedElementAccess( | 6728 HValue* load = HandleKeyedElementAccess( |
6676 obj, key, NULL, expr, expr->id(), expr->position(), | 6729 obj, key, NULL, expr, expr->id(), expr->position(), |
6677 false, // is_store | 6730 false, // is_store |
(...skipping 3333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10011 } | 10064 } |
10012 } | 10065 } |
10013 | 10066 |
10014 #ifdef DEBUG | 10067 #ifdef DEBUG |
10015 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10068 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10016 if (allocator_ != NULL) allocator_->Verify(); | 10069 if (allocator_ != NULL) allocator_->Verify(); |
10017 #endif | 10070 #endif |
10018 } | 10071 } |
10019 | 10072 |
10020 } } // namespace v8::internal | 10073 } } // namespace v8::internal |
OLD | NEW |