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 6573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6584 ASSERT(current_block() != NULL); | 6584 ASSERT(current_block() != NULL); |
6585 ASSERT(current_block()->HasPredecessor()); | 6585 ASSERT(current_block()->HasPredecessor()); |
6586 expr->RecordTypeFeedback(oracle(), zone()); | 6586 expr->RecordTypeFeedback(oracle(), zone()); |
6587 | 6587 |
6588 if (TryArgumentsAccess(expr)) return; | 6588 if (TryArgumentsAccess(expr)) return; |
6589 | 6589 |
6590 CHECK_ALIVE(VisitForValue(expr->obj())); | 6590 CHECK_ALIVE(VisitForValue(expr->obj())); |
6591 | 6591 |
6592 HInstruction* instr = NULL; | 6592 HInstruction* instr = NULL; |
6593 if (expr->AsProperty()->IsArrayLength()) { | 6593 if (expr->AsProperty()->IsArrayLength()) { |
6594 // Note that in the monomorphic case IsArrayLength() is false because we | |
6595 // handle that it with a regular property load IC. | |
6596 HValue* array = Pop(); | 6594 HValue* array = Pop(); |
6597 AddInstruction(new(zone()) HCheckNonSmi(array)); | 6595 AddInstruction(new(zone()) HCheckNonSmi(array)); |
6598 HInstruction* mapcheck = | 6596 HInstruction* mapcheck = |
6599 AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone())); | 6597 AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone())); |
6600 instr = new(zone()) HJSArrayLength(array, mapcheck); | 6598 instr = new(zone()) HJSArrayLength(array, mapcheck); |
6601 } else if (expr->IsStringLength()) { | 6599 } else if (expr->IsStringLength()) { |
6602 HValue* string = Pop(); | 6600 HValue* string = Pop(); |
6603 AddInstruction(new(zone()) HCheckNonSmi(string)); | 6601 AddInstruction(new(zone()) HCheckNonSmi(string)); |
6604 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 6602 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
6605 instr = new(zone()) HStringLength(string); | 6603 instr = new(zone()) HStringLength(string); |
(...skipping 15 matching lines...) Expand all Loading... |
6621 } else if (expr->key()->IsPropertyName()) { | 6619 } else if (expr->key()->IsPropertyName()) { |
6622 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 6620 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
6623 SmallMapList* types = expr->GetReceiverTypes(); | 6621 SmallMapList* types = expr->GetReceiverTypes(); |
6624 | 6622 |
6625 bool monomorphic = expr->IsMonomorphic(); | 6623 bool monomorphic = expr->IsMonomorphic(); |
6626 Handle<Map> map; | 6624 Handle<Map> map; |
6627 if (expr->IsMonomorphic()) { | 6625 if (expr->IsMonomorphic()) { |
6628 map = types->first(); | 6626 map = types->first(); |
6629 if (map->is_dictionary_map()) monomorphic = false; | 6627 if (map->is_dictionary_map()) monomorphic = false; |
6630 } | 6628 } |
6631 | 6629 if (monomorphic) { |
6632 // Try to see if this is an array length access. | 6630 Handle<JSFunction> getter; |
6633 if (name->Equals(isolate()->heap()->length_symbol())) { | 6631 Handle<JSObject> holder; |
6634 bool is_array = false; | 6632 if (LookupGetter(map, name, &getter, &holder)) { |
6635 bool fast_mode = false; | 6633 AddCheckConstantFunction(holder, Top(), map); |
6636 bool map_mode = false; | 6634 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
6637 HInstruction* mapcheck = NULL; | 6635 AddInstruction(new(zone()) HPushArgument(Pop())); |
6638 | 6636 instr = new(zone()) HCallConstantFunction(getter, 1); |
6639 if (expr->IsMonomorphic()) { | |
6640 // Even if there is more than one map they all must be element | |
6641 // transition maps, so checking just one is ok. | |
6642 if (map->instance_type() == JS_ARRAY_TYPE) { | |
6643 is_array = true; | |
6644 map_mode = true; | |
6645 fast_mode = IsFastElementsKind(map->elements_kind()); | |
6646 } | |
6647 } else { | 6637 } else { |
6648 // Since we will emit an instance check we have to conservatively | 6638 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); |
6649 // assume that some arrays will contain slow elements, so we set | |
6650 // fast_mode to false. | |
6651 map_mode = false; | |
6652 fast_mode = false; | |
6653 is_array = true; | |
6654 for (int i = 0; i < types->length(); i++) { | |
6655 Handle<Map> current_map = types->at(i); | |
6656 if (current_map->instance_type() != JS_ARRAY_TYPE) { | |
6657 is_array = false; | |
6658 break; | |
6659 } | |
6660 } | |
6661 } | 6639 } |
6662 | 6640 } else if (types != NULL && types->length() > 1) { |
6663 // It is an array length access so we produce a HJSArrayLength. | 6641 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); |
6664 if (is_array) { | 6642 } else { |
6665 HValue* array = Pop(); | 6643 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
6666 AddInstruction(new(zone()) HCheckNonSmi(array)); | |
6667 mapcheck = map_mode ? | |
6668 HInstruction::cast( | |
6669 new(zone()) HCheckMaps(array, map, zone(), NULL, | |
6670 ALLOW_ELEMENT_TRANSITION_MAPS)) : | |
6671 HInstruction::cast( | |
6672 HCheckInstanceType::NewIsJSArray(array, zone())); | |
6673 AddInstruction(mapcheck); | |
6674 instr = new(zone()) HJSArrayLength( | |
6675 array, mapcheck, fast_mode ? HType::Smi() : HType::Tagged()); | |
6676 } | |
6677 } | 6644 } |
6678 | 6645 |
6679 // We cannot know if it was an array length access so we handle it as | |
6680 // a regular property access. | |
6681 if (instr == NULL) { | |
6682 if (monomorphic) { | |
6683 Handle<JSFunction> getter; | |
6684 Handle<JSObject> holder; | |
6685 if (LookupGetter(map, name, &getter, &holder)) { | |
6686 AddCheckConstantFunction(holder, Top(), map); | |
6687 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; | |
6688 AddInstruction(new(zone()) HPushArgument(Pop())); | |
6689 instr = new(zone()) HCallConstantFunction(getter, 1); | |
6690 } else { | |
6691 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); | |
6692 } | |
6693 } else if (types != NULL && types->length() > 1) { | |
6694 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); | |
6695 } else { | |
6696 instr = BuildLoadNamedGeneric(Pop(), name, expr); | |
6697 } | |
6698 } | |
6699 } else { | 6646 } else { |
6700 CHECK_ALIVE(VisitForValue(expr->key())); | 6647 CHECK_ALIVE(VisitForValue(expr->key())); |
6701 | 6648 |
6702 HValue* key = Pop(); | 6649 HValue* key = Pop(); |
6703 HValue* obj = Pop(); | 6650 HValue* obj = Pop(); |
6704 | 6651 |
6705 bool has_side_effects = false; | 6652 bool has_side_effects = false; |
6706 HValue* load = HandleKeyedElementAccess( | 6653 HValue* load = HandleKeyedElementAccess( |
6707 obj, key, NULL, expr, expr->id(), expr->position(), | 6654 obj, key, NULL, expr, expr->id(), expr->position(), |
6708 false, // is_store | 6655 false, // is_store |
(...skipping 3397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10106 } | 10053 } |
10107 } | 10054 } |
10108 | 10055 |
10109 #ifdef DEBUG | 10056 #ifdef DEBUG |
10110 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10057 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10111 if (allocator_ != NULL) allocator_->Verify(); | 10058 if (allocator_ != NULL) allocator_->Verify(); |
10112 #endif | 10059 #endif |
10113 } | 10060 } |
10114 | 10061 |
10115 } } // namespace v8::internal | 10062 } } // namespace v8::internal |
OLD | NEW |