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 2900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2911 Register index = ToRegister(instr->index()); | 2911 Register index = ToRegister(instr->index()); |
2912 Register result = ToRegister(instr->result()); | 2912 Register result = ToRegister(instr->result()); |
2913 // There are two words between the frame pointer and the last argument. | 2913 // There are two words between the frame pointer and the last argument. |
2914 // Subtracting from length accounts for one of them add one more. | 2914 // Subtracting from length accounts for one of them add one more. |
2915 __ sub(length, length, index); | 2915 __ sub(length, length, index); |
2916 __ add(length, length, Operand(1)); | 2916 __ add(length, length, Operand(1)); |
2917 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); | 2917 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); |
2918 } | 2918 } |
2919 | 2919 |
2920 | 2920 |
2921 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2921 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
2922 Register elements = ToRegister(instr->elements()); | 2922 Register external_pointer = ToRegister(instr->elements()); |
2923 Register result = ToRegister(instr->result()); | 2923 Register key = no_reg; |
2924 Register scratch = scratch0(); | 2924 ElementsKind elements_kind = instr->elements_kind(); |
2925 Register store_base = scratch; | 2925 bool key_is_constant = instr->key()->IsConstantOperand(); |
2926 int offset = 0; | 2926 int constant_key = 0; |
| 2927 if (key_is_constant) { |
| 2928 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 2929 if (constant_key & 0xF0000000) { |
| 2930 Abort("array index constant value too big."); |
| 2931 } |
| 2932 } else { |
| 2933 key = ToRegister(instr->key()); |
| 2934 } |
| 2935 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| 2936 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| 2937 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 2938 int additional_offset = instr->additional_index() << element_size_shift; |
2927 | 2939 |
2928 if (instr->key()->IsConstantOperand()) { | 2940 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
2929 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 2941 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
2930 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + | 2942 CpuFeatures::Scope scope(VFP3); |
2931 instr->additional_index()); | 2943 DwVfpRegister result = ToDoubleRegister(instr->result()); |
2932 store_base = elements; | 2944 Operand operand = key_is_constant |
| 2945 ? Operand(constant_key << element_size_shift) |
| 2946 : Operand(key, LSL, shift_size); |
| 2947 __ add(scratch0(), external_pointer, operand); |
| 2948 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| 2949 __ vldr(result.low(), scratch0(), additional_offset); |
| 2950 __ vcvt_f64_f32(result, result.low()); |
| 2951 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
| 2952 __ vldr(result, scratch0(), additional_offset); |
| 2953 } |
2933 } else { | 2954 } else { |
2934 Register key = EmitLoadRegister(instr->key(), scratch0()); | 2955 Register result = ToRegister(instr->result()); |
2935 // Even though the HLoadKeyedFastElement instruction forces the input | 2956 MemOperand mem_operand = PrepareKeyedOperand( |
2936 // representation for the key to be an integer, the input gets replaced | 2957 key, external_pointer, key_is_constant, constant_key, |
2937 // during bound check elimination with the index argument to the bounds | 2958 element_size_shift, shift_size, |
2938 // check, which can be tagged, so that case must be handled here, too. | 2959 instr->additional_index(), additional_offset); |
2939 if (instr->hydrogen()->key()->representation().IsTagged()) { | 2960 switch (elements_kind) { |
2940 __ add(scratch, elements, | 2961 case EXTERNAL_BYTE_ELEMENTS: |
2941 Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); | 2962 __ ldrsb(result, mem_operand); |
2942 } else { | 2963 break; |
2943 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | 2964 case EXTERNAL_PIXEL_ELEMENTS: |
2944 } | 2965 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
2945 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); | 2966 __ ldrb(result, mem_operand); |
2946 } | 2967 break; |
2947 __ ldr(result, FieldMemOperand(store_base, offset)); | 2968 case EXTERNAL_SHORT_ELEMENTS: |
2948 | 2969 __ ldrsh(result, mem_operand); |
2949 // Check for the hole value. | 2970 break; |
2950 if (instr->hydrogen()->RequiresHoleCheck()) { | 2971 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
2951 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | 2972 __ ldrh(result, mem_operand); |
2952 __ tst(result, Operand(kSmiTagMask)); | 2973 break; |
2953 DeoptimizeIf(ne, instr->environment()); | 2974 case EXTERNAL_INT_ELEMENTS: |
2954 } else { | 2975 __ ldr(result, mem_operand); |
2955 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 2976 break; |
2956 __ cmp(result, scratch); | 2977 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
2957 DeoptimizeIf(eq, instr->environment()); | 2978 __ ldr(result, mem_operand); |
| 2979 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 2980 __ cmp(result, Operand(0x80000000)); |
| 2981 DeoptimizeIf(cs, instr->environment()); |
| 2982 } |
| 2983 break; |
| 2984 case EXTERNAL_FLOAT_ELEMENTS: |
| 2985 case EXTERNAL_DOUBLE_ELEMENTS: |
| 2986 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 2987 case FAST_HOLEY_ELEMENTS: |
| 2988 case FAST_HOLEY_SMI_ELEMENTS: |
| 2989 case FAST_DOUBLE_ELEMENTS: |
| 2990 case FAST_ELEMENTS: |
| 2991 case FAST_SMI_ELEMENTS: |
| 2992 case DICTIONARY_ELEMENTS: |
| 2993 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 2994 UNREACHABLE(); |
| 2995 break; |
2958 } | 2996 } |
2959 } | 2997 } |
2960 } | 2998 } |
2961 | 2999 |
2962 | 3000 |
2963 void LCodeGen::DoLoadKeyedFastDoubleElement( | 3001 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
2964 LLoadKeyedFastDoubleElement* instr) { | |
2965 Register elements = ToRegister(instr->elements()); | 3002 Register elements = ToRegister(instr->elements()); |
2966 bool key_is_constant = instr->key()->IsConstantOperand(); | 3003 bool key_is_constant = instr->key()->IsConstantOperand(); |
2967 Register key = no_reg; | 3004 Register key = no_reg; |
2968 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3005 DwVfpRegister result = ToDoubleRegister(instr->result()); |
2969 Register scratch = scratch0(); | 3006 Register scratch = scratch0(); |
2970 | 3007 |
2971 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); | 3008 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
2972 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | 3009 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
2973 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3010 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
2974 int constant_key = 0; | 3011 int constant_key = 0; |
(...skipping 21 matching lines...) Expand all Loading... |
2996 if (instr->hydrogen()->RequiresHoleCheck()) { | 3033 if (instr->hydrogen()->RequiresHoleCheck()) { |
2997 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | 3034 __ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
2998 __ cmp(scratch, Operand(kHoleNanUpper32)); | 3035 __ cmp(scratch, Operand(kHoleNanUpper32)); |
2999 DeoptimizeIf(eq, instr->environment()); | 3036 DeoptimizeIf(eq, instr->environment()); |
3000 } | 3037 } |
3001 | 3038 |
3002 __ vldr(result, elements, 0); | 3039 __ vldr(result, elements, 0); |
3003 } | 3040 } |
3004 | 3041 |
3005 | 3042 |
| 3043 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3044 Register elements = ToRegister(instr->elements()); |
| 3045 Register result = ToRegister(instr->result()); |
| 3046 Register scratch = scratch0(); |
| 3047 Register store_base = scratch; |
| 3048 int offset = 0; |
| 3049 |
| 3050 if (instr->key()->IsConstantOperand()) { |
| 3051 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| 3052 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| 3053 instr->additional_index()); |
| 3054 store_base = elements; |
| 3055 } else { |
| 3056 Register key = EmitLoadRegister(instr->key(), scratch0()); |
| 3057 // Even though the HLoadKeyed instruction forces the input |
| 3058 // representation for the key to be an integer, the input gets replaced |
| 3059 // during bound check elimination with the index argument to the bounds |
| 3060 // check, which can be tagged, so that case must be handled here, too. |
| 3061 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 3062 __ add(scratch, elements, |
| 3063 Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 3064 } else { |
| 3065 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
| 3066 } |
| 3067 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| 3068 } |
| 3069 __ ldr(result, FieldMemOperand(store_base, offset)); |
| 3070 |
| 3071 // Check for the hole value. |
| 3072 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3073 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| 3074 __ tst(result, Operand(kSmiTagMask)); |
| 3075 DeoptimizeIf(ne, instr->environment()); |
| 3076 } else { |
| 3077 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 3078 __ cmp(result, scratch); |
| 3079 DeoptimizeIf(eq, instr->environment()); |
| 3080 } |
| 3081 } |
| 3082 } |
| 3083 |
| 3084 |
| 3085 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 3086 if (instr->is_external()) { |
| 3087 DoLoadKeyedExternalArray(instr); |
| 3088 } else if (instr->hydrogen()->representation().IsDouble()) { |
| 3089 DoLoadKeyedFixedDoubleArray(instr); |
| 3090 } else { |
| 3091 DoLoadKeyedFixedArray(instr); |
| 3092 } |
| 3093 } |
| 3094 |
| 3095 |
3006 MemOperand LCodeGen::PrepareKeyedOperand(Register key, | 3096 MemOperand LCodeGen::PrepareKeyedOperand(Register key, |
3007 Register base, | 3097 Register base, |
3008 bool key_is_constant, | 3098 bool key_is_constant, |
3009 int constant_key, | 3099 int constant_key, |
3010 int element_size, | 3100 int element_size, |
3011 int shift_size, | 3101 int shift_size, |
3012 int additional_index, | 3102 int additional_index, |
3013 int additional_offset) { | 3103 int additional_offset) { |
3014 if (additional_index != 0 && !key_is_constant) { | 3104 if (additional_index != 0 && !key_is_constant) { |
3015 additional_index *= 1 << (element_size - shift_size); | 3105 additional_index *= 1 << (element_size - shift_size); |
(...skipping 16 matching lines...) Expand all Loading... |
3032 | 3122 |
3033 if (shift_size >= 0) { | 3123 if (shift_size >= 0) { |
3034 return MemOperand(base, scratch0(), LSL, shift_size); | 3124 return MemOperand(base, scratch0(), LSL, shift_size); |
3035 } else { | 3125 } else { |
3036 ASSERT_EQ(-1, shift_size); | 3126 ASSERT_EQ(-1, shift_size); |
3037 return MemOperand(base, scratch0(), LSR, 1); | 3127 return MemOperand(base, scratch0(), LSR, 1); |
3038 } | 3128 } |
3039 } | 3129 } |
3040 | 3130 |
3041 | 3131 |
3042 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | |
3043 LLoadKeyedSpecializedArrayElement* instr) { | |
3044 Register external_pointer = ToRegister(instr->external_pointer()); | |
3045 Register key = no_reg; | |
3046 ElementsKind elements_kind = instr->elements_kind(); | |
3047 bool key_is_constant = instr->key()->IsConstantOperand(); | |
3048 int constant_key = 0; | |
3049 if (key_is_constant) { | |
3050 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | |
3051 if (constant_key & 0xF0000000) { | |
3052 Abort("array index constant value too big."); | |
3053 } | |
3054 } else { | |
3055 key = ToRegister(instr->key()); | |
3056 } | |
3057 int element_size_shift = ElementsKindToShiftSize(elements_kind); | |
3058 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | |
3059 ? (element_size_shift - kSmiTagSize) : element_size_shift; | |
3060 int additional_offset = instr->additional_index() << element_size_shift; | |
3061 | |
3062 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | |
3063 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
3064 CpuFeatures::Scope scope(VFP3); | |
3065 DwVfpRegister result = ToDoubleRegister(instr->result()); | |
3066 Operand operand = key_is_constant | |
3067 ? Operand(constant_key << element_size_shift) | |
3068 : Operand(key, LSL, shift_size); | |
3069 __ add(scratch0(), external_pointer, operand); | |
3070 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
3071 __ vldr(result.low(), scratch0(), additional_offset); | |
3072 __ vcvt_f64_f32(result, result.low()); | |
3073 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | |
3074 __ vldr(result, scratch0(), additional_offset); | |
3075 } | |
3076 } else { | |
3077 Register result = ToRegister(instr->result()); | |
3078 MemOperand mem_operand = PrepareKeyedOperand( | |
3079 key, external_pointer, key_is_constant, constant_key, | |
3080 element_size_shift, shift_size, | |
3081 instr->additional_index(), additional_offset); | |
3082 switch (elements_kind) { | |
3083 case EXTERNAL_BYTE_ELEMENTS: | |
3084 __ ldrsb(result, mem_operand); | |
3085 break; | |
3086 case EXTERNAL_PIXEL_ELEMENTS: | |
3087 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3088 __ ldrb(result, mem_operand); | |
3089 break; | |
3090 case EXTERNAL_SHORT_ELEMENTS: | |
3091 __ ldrsh(result, mem_operand); | |
3092 break; | |
3093 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3094 __ ldrh(result, mem_operand); | |
3095 break; | |
3096 case EXTERNAL_INT_ELEMENTS: | |
3097 __ ldr(result, mem_operand); | |
3098 break; | |
3099 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3100 __ ldr(result, mem_operand); | |
3101 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | |
3102 __ cmp(result, Operand(0x80000000)); | |
3103 DeoptimizeIf(cs, instr->environment()); | |
3104 } | |
3105 break; | |
3106 case EXTERNAL_FLOAT_ELEMENTS: | |
3107 case EXTERNAL_DOUBLE_ELEMENTS: | |
3108 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
3109 case FAST_HOLEY_ELEMENTS: | |
3110 case FAST_HOLEY_SMI_ELEMENTS: | |
3111 case FAST_DOUBLE_ELEMENTS: | |
3112 case FAST_ELEMENTS: | |
3113 case FAST_SMI_ELEMENTS: | |
3114 case DICTIONARY_ELEMENTS: | |
3115 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
3116 UNREACHABLE(); | |
3117 break; | |
3118 } | |
3119 } | |
3120 } | |
3121 | |
3122 | |
3123 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3132 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
3124 ASSERT(ToRegister(instr->object()).is(r1)); | 3133 ASSERT(ToRegister(instr->object()).is(r1)); |
3125 ASSERT(ToRegister(instr->key()).is(r0)); | 3134 ASSERT(ToRegister(instr->key()).is(r0)); |
3126 | 3135 |
3127 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3136 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
3128 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3137 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
3129 } | 3138 } |
3130 | 3139 |
3131 | 3140 |
3132 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3141 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
(...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3993 __ mov(ip, Operand(constant_index)); | 4002 __ mov(ip, Operand(constant_index)); |
3994 } | 4003 } |
3995 __ cmp(ip, ToRegister(instr->length())); | 4004 __ cmp(ip, ToRegister(instr->length())); |
3996 } else { | 4005 } else { |
3997 __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); | 4006 __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); |
3998 } | 4007 } |
3999 DeoptimizeIf(hs, instr->environment()); | 4008 DeoptimizeIf(hs, instr->environment()); |
4000 } | 4009 } |
4001 | 4010 |
4002 | 4011 |
4003 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 4012 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4004 Register value = ToRegister(instr->value()); | 4013 Register external_pointer = ToRegister(instr->elements()); |
4005 Register elements = ToRegister(instr->object()); | |
4006 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | |
4007 Register scratch = scratch0(); | |
4008 Register store_base = scratch; | |
4009 int offset = 0; | |
4010 | |
4011 // Do the store. | |
4012 if (instr->key()->IsConstantOperand()) { | |
4013 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | |
4014 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | |
4015 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + | |
4016 instr->additional_index()); | |
4017 store_base = elements; | |
4018 } else { | |
4019 // Even though the HLoadKeyedFastElement instruction forces the input | |
4020 // representation for the key to be an integer, the input gets replaced | |
4021 // during bound check elimination with the index argument to the bounds | |
4022 // check, which can be tagged, so that case must be handled here, too. | |
4023 if (instr->hydrogen()->key()->representation().IsTagged()) { | |
4024 __ add(scratch, elements, | |
4025 Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); | |
4026 } else { | |
4027 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | |
4028 } | |
4029 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); | |
4030 } | |
4031 __ str(value, FieldMemOperand(store_base, offset)); | |
4032 | |
4033 if (instr->hydrogen()->NeedsWriteBarrier()) { | |
4034 HType type = instr->hydrogen()->value()->type(); | |
4035 SmiCheck check_needed = | |
4036 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
4037 // Compute address of modified element and store it into key register. | |
4038 __ add(key, store_base, Operand(offset - kHeapObjectTag)); | |
4039 __ RecordWrite(elements, | |
4040 key, | |
4041 value, | |
4042 kLRHasBeenSaved, | |
4043 kSaveFPRegs, | |
4044 EMIT_REMEMBERED_SET, | |
4045 check_needed); | |
4046 } | |
4047 } | |
4048 | |
4049 | |
4050 void LCodeGen::DoStoreKeyedFastDoubleElement( | |
4051 LStoreKeyedFastDoubleElement* instr) { | |
4052 DwVfpRegister value = ToDoubleRegister(instr->value()); | |
4053 Register elements = ToRegister(instr->elements()); | |
4054 Register key = no_reg; | |
4055 Register scratch = scratch0(); | |
4056 bool key_is_constant = instr->key()->IsConstantOperand(); | |
4057 int constant_key = 0; | |
4058 | |
4059 // Calculate the effective address of the slot in the array to store the | |
4060 // double value. | |
4061 if (key_is_constant) { | |
4062 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | |
4063 if (constant_key & 0xF0000000) { | |
4064 Abort("array index constant value too big."); | |
4065 } | |
4066 } else { | |
4067 key = ToRegister(instr->key()); | |
4068 } | |
4069 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); | |
4070 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | |
4071 ? (element_size_shift - kSmiTagSize) : element_size_shift; | |
4072 Operand operand = key_is_constant | |
4073 ? Operand((constant_key << element_size_shift) + | |
4074 FixedDoubleArray::kHeaderSize - kHeapObjectTag) | |
4075 : Operand(key, LSL, shift_size); | |
4076 __ add(scratch, elements, operand); | |
4077 if (!key_is_constant) { | |
4078 __ add(scratch, scratch, | |
4079 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | |
4080 } | |
4081 | |
4082 if (instr->NeedsCanonicalization()) { | |
4083 // Check for NaN. All NaNs must be canonicalized. | |
4084 __ VFPCompareAndSetFlags(value, value); | |
4085 // Only load canonical NaN if the comparison above set the overflow. | |
4086 __ Vmov(value, | |
4087 FixedDoubleArray::canonical_not_the_hole_nan_as_double(), | |
4088 no_reg, vs); | |
4089 } | |
4090 | |
4091 __ vstr(value, scratch, instr->additional_index() << element_size_shift); | |
4092 } | |
4093 | |
4094 | |
4095 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | |
4096 LStoreKeyedSpecializedArrayElement* instr) { | |
4097 | |
4098 Register external_pointer = ToRegister(instr->external_pointer()); | |
4099 Register key = no_reg; | 4014 Register key = no_reg; |
4100 ElementsKind elements_kind = instr->elements_kind(); | 4015 ElementsKind elements_kind = instr->elements_kind(); |
4101 bool key_is_constant = instr->key()->IsConstantOperand(); | 4016 bool key_is_constant = instr->key()->IsConstantOperand(); |
4102 int constant_key = 0; | 4017 int constant_key = 0; |
4103 if (key_is_constant) { | 4018 if (key_is_constant) { |
4104 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 4019 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
4105 if (constant_key & 0xF0000000) { | 4020 if (constant_key & 0xF0000000) { |
4106 Abort("array index constant value too big."); | 4021 Abort("array index constant value too big."); |
4107 } | 4022 } |
4108 } else { | 4023 } else { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4157 case FAST_HOLEY_SMI_ELEMENTS: | 4072 case FAST_HOLEY_SMI_ELEMENTS: |
4158 case DICTIONARY_ELEMENTS: | 4073 case DICTIONARY_ELEMENTS: |
4159 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4074 case NON_STRICT_ARGUMENTS_ELEMENTS: |
4160 UNREACHABLE(); | 4075 UNREACHABLE(); |
4161 break; | 4076 break; |
4162 } | 4077 } |
4163 } | 4078 } |
4164 } | 4079 } |
4165 | 4080 |
4166 | 4081 |
| 4082 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
| 4083 DwVfpRegister value = ToDoubleRegister(instr->value()); |
| 4084 Register elements = ToRegister(instr->elements()); |
| 4085 Register key = no_reg; |
| 4086 Register scratch = scratch0(); |
| 4087 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 4088 int constant_key = 0; |
| 4089 |
| 4090 // Calculate the effective address of the slot in the array to store the |
| 4091 // double value. |
| 4092 if (key_is_constant) { |
| 4093 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 4094 if (constant_key & 0xF0000000) { |
| 4095 Abort("array index constant value too big."); |
| 4096 } |
| 4097 } else { |
| 4098 key = ToRegister(instr->key()); |
| 4099 } |
| 4100 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| 4101 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| 4102 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 4103 Operand operand = key_is_constant |
| 4104 ? Operand((constant_key << element_size_shift) + |
| 4105 FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
| 4106 : Operand(key, LSL, shift_size); |
| 4107 __ add(scratch, elements, operand); |
| 4108 if (!key_is_constant) { |
| 4109 __ add(scratch, scratch, |
| 4110 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 4111 } |
| 4112 |
| 4113 if (instr->NeedsCanonicalization()) { |
| 4114 // Check for NaN. All NaNs must be canonicalized. |
| 4115 __ VFPCompareAndSetFlags(value, value); |
| 4116 // Only load canonical NaN if the comparison above set the overflow. |
| 4117 __ Vmov(value, |
| 4118 FixedDoubleArray::canonical_not_the_hole_nan_as_double(), |
| 4119 no_reg, vs); |
| 4120 } |
| 4121 |
| 4122 __ vstr(value, scratch, instr->additional_index() << element_size_shift); |
| 4123 } |
| 4124 |
| 4125 |
| 4126 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4127 Register value = ToRegister(instr->value()); |
| 4128 Register elements = ToRegister(instr->elements()); |
| 4129 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) |
| 4130 : no_reg; |
| 4131 Register scratch = scratch0(); |
| 4132 Register store_base = scratch; |
| 4133 int offset = 0; |
| 4134 |
| 4135 // Do the store. |
| 4136 if (instr->key()->IsConstantOperand()) { |
| 4137 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4138 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| 4139 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| 4140 instr->additional_index()); |
| 4141 store_base = elements; |
| 4142 } else { |
| 4143 // Even though the HLoadKeyed instruction forces the input |
| 4144 // representation for the key to be an integer, the input gets replaced |
| 4145 // during bound check elimination with the index argument to the bounds |
| 4146 // check, which can be tagged, so that case must be handled here, too. |
| 4147 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 4148 __ add(scratch, elements, |
| 4149 Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4150 } else { |
| 4151 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
| 4152 } |
| 4153 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| 4154 } |
| 4155 __ str(value, FieldMemOperand(store_base, offset)); |
| 4156 |
| 4157 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4158 HType type = instr->hydrogen()->value()->type(); |
| 4159 SmiCheck check_needed = |
| 4160 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4161 // Compute address of modified element and store it into key register. |
| 4162 __ add(key, store_base, Operand(offset - kHeapObjectTag)); |
| 4163 __ RecordWrite(elements, |
| 4164 key, |
| 4165 value, |
| 4166 kLRHasBeenSaved, |
| 4167 kSaveFPRegs, |
| 4168 EMIT_REMEMBERED_SET, |
| 4169 check_needed); |
| 4170 } |
| 4171 } |
| 4172 |
| 4173 |
| 4174 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
| 4175 // By cases: external, fast double |
| 4176 if (instr->is_external()) { |
| 4177 DoStoreKeyedExternalArray(instr); |
| 4178 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
| 4179 DoStoreKeyedFixedDoubleArray(instr); |
| 4180 } else { |
| 4181 DoStoreKeyedFixedArray(instr); |
| 4182 } |
| 4183 } |
| 4184 |
| 4185 |
4167 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 4186 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
4168 ASSERT(ToRegister(instr->object()).is(r2)); | 4187 ASSERT(ToRegister(instr->object()).is(r2)); |
4169 ASSERT(ToRegister(instr->key()).is(r1)); | 4188 ASSERT(ToRegister(instr->key()).is(r1)); |
4170 ASSERT(ToRegister(instr->value()).is(r0)); | 4189 ASSERT(ToRegister(instr->value()).is(r0)); |
4171 | 4190 |
4172 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4191 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
4173 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4192 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
4174 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4193 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
4175 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4194 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); |
4176 } | 4195 } |
(...skipping 1502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5679 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5698 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
5680 __ ldr(result, FieldMemOperand(scratch, | 5699 __ ldr(result, FieldMemOperand(scratch, |
5681 FixedArray::kHeaderSize - kPointerSize)); | 5700 FixedArray::kHeaderSize - kPointerSize)); |
5682 __ bind(&done); | 5701 __ bind(&done); |
5683 } | 5702 } |
5684 | 5703 |
5685 | 5704 |
5686 #undef __ | 5705 #undef __ |
5687 | 5706 |
5688 } } // namespace v8::internal | 5707 } } // namespace v8::internal |
OLD | NEW |