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 2709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2720 Register result = ToRegister(instr->result()); | 2720 Register result = ToRegister(instr->result()); |
2721 if (access.IsInobject()) { | 2721 if (access.IsInobject()) { |
2722 __ movq(result, FieldOperand(object, offset)); | 2722 __ movq(result, FieldOperand(object, offset)); |
2723 } else { | 2723 } else { |
2724 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2724 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
2725 __ movq(result, FieldOperand(result, offset)); | 2725 __ movq(result, FieldOperand(result, offset)); |
2726 } | 2726 } |
2727 } | 2727 } |
2728 | 2728 |
2729 | 2729 |
2730 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, | |
2731 Register object, | |
2732 Handle<Map> type, | |
2733 Handle<String> name, | |
2734 LEnvironment* env) { | |
2735 LookupResult lookup(isolate()); | |
2736 type->LookupDescriptor(NULL, *name, &lookup); | |
2737 ASSERT(lookup.IsFound() || lookup.IsCacheable()); | |
2738 if (lookup.IsField()) { | |
2739 int index = lookup.GetLocalFieldIndexFromMap(*type); | |
2740 int offset = index * kPointerSize; | |
2741 if (index < 0) { | |
2742 // Negative property indices are in-object properties, indexed | |
2743 // from the end of the fixed part of the object. | |
2744 __ movq(result, FieldOperand(object, offset + type->instance_size())); | |
2745 } else { | |
2746 // Non-negative property indices are in the properties array. | |
2747 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | |
2748 __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); | |
2749 } | |
2750 } else if (lookup.IsConstant()) { | |
2751 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate()); | |
2752 __ LoadObject(result, constant); | |
2753 } else { | |
2754 // Negative lookup. | |
2755 // Check prototypes. | |
2756 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); | |
2757 Heap* heap = type->GetHeap(); | |
2758 while (*current != heap->null_value()) { | |
2759 __ LoadHeapObject(result, current); | |
2760 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), | |
2761 Handle<Map>(current->map())); | |
2762 DeoptimizeIf(not_equal, env); | |
2763 current = | |
2764 Handle<HeapObject>(HeapObject::cast(current->map()->prototype())); | |
2765 } | |
2766 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | |
2767 } | |
2768 } | |
2769 | |
2770 | |
2771 // Check for cases where EmitLoadFieldOrConstantFunction needs to walk the | |
2772 // prototype chain, which causes unbounded code generation. | |
2773 static bool CompactEmit(SmallMapList* list, | |
2774 Handle<String> name, | |
2775 int i, | |
2776 Isolate* isolate) { | |
2777 Handle<Map> map = list->at(i); | |
2778 LookupResult lookup(isolate); | |
2779 map->LookupDescriptor(NULL, *name, &lookup); | |
2780 return lookup.IsField() || lookup.IsConstant(); | |
2781 } | |
2782 | |
2783 | |
2784 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | |
2785 Register object = ToRegister(instr->object()); | |
2786 Register result = ToRegister(instr->result()); | |
2787 | |
2788 int map_count = instr->hydrogen()->types()->length(); | |
2789 bool need_generic = instr->hydrogen()->need_generic(); | |
2790 | |
2791 if (map_count == 0 && !need_generic) { | |
2792 DeoptimizeIf(no_condition, instr->environment()); | |
2793 return; | |
2794 } | |
2795 Handle<String> name = instr->hydrogen()->name(); | |
2796 Label done; | |
2797 bool all_are_compact = true; | |
2798 for (int i = 0; i < map_count; ++i) { | |
2799 if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) { | |
2800 all_are_compact = false; | |
2801 break; | |
2802 } | |
2803 } | |
2804 for (int i = 0; i < map_count; ++i) { | |
2805 bool last = (i == map_count - 1); | |
2806 Handle<Map> map = instr->hydrogen()->types()->at(i); | |
2807 Label check_passed; | |
2808 __ CompareMap(object, map, &check_passed); | |
2809 if (last && !need_generic) { | |
2810 DeoptimizeIf(not_equal, instr->environment()); | |
2811 __ bind(&check_passed); | |
2812 EmitLoadFieldOrConstantFunction( | |
2813 result, object, map, name, instr->environment()); | |
2814 } else { | |
2815 Label next; | |
2816 bool compact = all_are_compact ? true : | |
2817 CompactEmit(instr->hydrogen()->types(), name, i, isolate()); | |
2818 __ j(not_equal, &next, compact ? Label::kNear : Label::kFar); | |
2819 __ bind(&check_passed); | |
2820 EmitLoadFieldOrConstantFunction( | |
2821 result, object, map, name, instr->environment()); | |
2822 __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar); | |
2823 __ bind(&next); | |
2824 } | |
2825 } | |
2826 if (need_generic) { | |
2827 __ Move(rcx, name); | |
2828 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
2829 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
2830 } | |
2831 __ bind(&done); | |
2832 } | |
2833 | |
2834 | |
2835 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2730 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
2836 ASSERT(ToRegister(instr->object()).is(rax)); | 2731 ASSERT(ToRegister(instr->object()).is(rax)); |
2837 ASSERT(ToRegister(instr->result()).is(rax)); | 2732 ASSERT(ToRegister(instr->result()).is(rax)); |
2838 | 2733 |
2839 __ Move(rcx, instr->name()); | 2734 __ Move(rcx, instr->name()); |
2840 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2735 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2841 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2736 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2842 } | 2737 } |
2843 | 2738 |
2844 | 2739 |
(...skipping 2749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5594 FixedArray::kHeaderSize - kPointerSize)); | 5489 FixedArray::kHeaderSize - kPointerSize)); |
5595 __ bind(&done); | 5490 __ bind(&done); |
5596 } | 5491 } |
5597 | 5492 |
5598 | 5493 |
5599 #undef __ | 5494 #undef __ |
5600 | 5495 |
5601 } } // namespace v8::internal | 5496 } } // namespace v8::internal |
5602 | 5497 |
5603 #endif // V8_TARGET_ARCH_X64 | 5498 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |