| 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 |