| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/x64/lithium-codegen-x64.h" | 9 #include "src/x64/lithium-codegen-x64.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 2876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2887 scratch, | 2887 scratch, |
| 2888 kSaveFPRegs, | 2888 kSaveFPRegs, |
| 2889 EMIT_REMEMBERED_SET, | 2889 EMIT_REMEMBERED_SET, |
| 2890 check_needed); | 2890 check_needed); |
| 2891 } | 2891 } |
| 2892 | 2892 |
| 2893 __ bind(&skip_assignment); | 2893 __ bind(&skip_assignment); |
| 2894 } | 2894 } |
| 2895 | 2895 |
| 2896 | 2896 |
| 2897 #ifdef DEBUG |
| 2898 void LCodeGen::EmitCheckMap(Register object, Handle<Map> map) { |
| 2899 __ CompareMap(object, map); |
| 2900 __ Check(equal, kObjectAccessCheckFailed); |
| 2901 } |
| 2902 |
| 2903 |
| 2904 void LCodeGen::EmitCheckInstanceType(Register object, InstanceType type, |
| 2905 Condition condition) { |
| 2906 __ movp(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset)); |
| 2907 __ CmpInstanceType(kScratchRegister, type); |
| 2908 __ Check(condition, kObjectAccessCheckFailed); |
| 2909 } |
| 2910 |
| 2911 |
| 2912 void LCodeGen::EmitObjectAccessVerification(HObjectAccess* access, |
| 2913 Register object, |
| 2914 bool is_store) { |
| 2915 if (!FLAG_debug_code) return; |
| 2916 Comment(";;; HObjectAccess check <%d>", static_cast<int>(access->purpose())); |
| 2917 switch (access->purpose()) { |
| 2918 case HObjectAccess::FOR_HEAP_NUMBER_VALUE: |
| 2919 case HObjectAccess::FOR_HEAP_NUMBER_VALUE_HIGHEST_BITS: |
| 2920 case HObjectAccess::FOR_HEAP_NUMBER_VALUE_LOWEST_BITS: |
| 2921 EmitCheckMap(object, isolate()->factory()->heap_number_map()); |
| 2922 break; |
| 2923 |
| 2924 case HObjectAccess::FOR_ALLOCATION_MEMENTO_SITE: |
| 2925 EmitCheckMap(object, isolate()->factory()->allocation_memento_map()); |
| 2926 break; |
| 2927 |
| 2928 case HObjectAccess::FOR_ALLOCATION_SITE_OFFSET: |
| 2929 EmitCheckMap(object, isolate()->factory()->allocation_site_map()); |
| 2930 break; |
| 2931 |
| 2932 case HObjectAccess::FOR_CODE_OFFSET: |
| 2933 case HObjectAccess::FOR_OPTIMIZED_CODE_MAP: |
| 2934 EmitCheckMap(object, isolate()->factory()->shared_function_info_map()); |
| 2935 break; |
| 2936 |
| 2937 case HObjectAccess::FOR_MAP_INSTANCE_SIZE: |
| 2938 case HObjectAccess::FOR_MAP_INSTANCE_TYPE: |
| 2939 EmitCheckMap(object, isolate()->factory()->meta_map()); |
| 2940 break; |
| 2941 |
| 2942 case HObjectAccess::FOR_CELL_VALUE: |
| 2943 case HObjectAccess::FOR_PROPERTY_CELL_VALUE: |
| 2944 EmitCheckMap(object, isolate()->factory()->cell_map()); |
| 2945 break; |
| 2946 |
| 2947 case HObjectAccess::FOR_CONTEXT_SLOT: |
| 2948 EmitCheckInstanceType(object, FIXED_ARRAY_TYPE); |
| 2949 break; |
| 2950 |
| 2951 case HObjectAccess::FOR_CODE_ENTRY_POINTER: |
| 2952 case HObjectAccess::FOR_FUNCTION_CONTEXT_POINTER: |
| 2953 case HObjectAccess::FOR_LITERALS_POINTER: |
| 2954 case HObjectAccess::FOR_NEXT_FUNCTION_LINK_POINTER: |
| 2955 case HObjectAccess::FOR_PROTOTYPE_OR_INITIAL_MAP: |
| 2956 case HObjectAccess::FOR_SHARED_FUNCTION_INFO_POINTER: |
| 2957 EmitCheckInstanceType(object, JS_FUNCTION_TYPE); |
| 2958 break; |
| 2959 |
| 2960 case HObjectAccess::FOR_ARRAY_LENGTH: |
| 2961 case HObjectAccess::FOR_JSARRAY_OFFSET: |
| 2962 EmitCheckInstanceType(object, JS_ARRAY_TYPE); |
| 2963 break; |
| 2964 |
| 2965 case HObjectAccess::FOR_JSTYPEDARRAY_LENGTH: |
| 2966 EmitCheckInstanceType(object, JS_TYPED_ARRAY_TYPE); |
| 2967 break; |
| 2968 |
| 2969 case HObjectAccess::FOR_JSARRAYBUFFER_BACKING_STORE: |
| 2970 case HObjectAccess::FOR_JSARRAYBUFFER_BYTE_LENGTH: |
| 2971 case HObjectAccess::FOR_JSARRAYBUFFER_WEAK_FIRST_VIEW: |
| 2972 EmitCheckInstanceType(object, JS_ARRAY_BUFFER_TYPE); |
| 2973 break; |
| 2974 |
| 2975 case HObjectAccess::FOR_STRING_HASH_FIELD: |
| 2976 case HObjectAccess::FOR_STRING_LENGTH: |
| 2977 EmitCheckInstanceType(object, FIRST_NONSTRING_TYPE, below); |
| 2978 break; |
| 2979 |
| 2980 case HObjectAccess::FOR_ELEMENTS_POINTER: |
| 2981 case HObjectAccess::FOR_PROPERTIES_POINTER: |
| 2982 EmitCheckInstanceType(object, FIRST_JS_OBJECT_TYPE, above_equal); |
| 2983 break; |
| 2984 |
| 2985 case HObjectAccess::FOR_JSARRAYBUFFERVIEW_BUFFER: |
| 2986 case HObjectAccess::FOR_JSARRAYBUFFERVIEW_BYTE_LENGTH: |
| 2987 case HObjectAccess::FOR_JSARRAYBUFFERVIEW_BYTE_OFFSET: |
| 2988 case HObjectAccess::FOR_JSARRAYBUFFERVIEW_WEAK_NEXT: { |
| 2989 Label ok; |
| 2990 __ movp(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset)); |
| 2991 __ CmpInstanceType(kScratchRegister, JS_TYPED_ARRAY_TYPE); |
| 2992 __ j(equal, &ok, Label::kNear); |
| 2993 __ CmpInstanceType(kScratchRegister, JS_DATA_VIEW_TYPE); |
| 2994 __ j(equal, &ok, Label::kNear); |
| 2995 __ Abort(kObjectAccessCheckFailed); |
| 2996 __ bind(&ok); |
| 2997 break; |
| 2998 } |
| 2999 case HObjectAccess::FOR_EXTERNAL_ARRAY_EXTERNAL_POINTER: { |
| 3000 Label ok, bad; |
| 3001 __ movp(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset)); |
| 3002 __ CmpInstanceType(kScratchRegister, FIRST_EXTERNAL_ARRAY_TYPE); |
| 3003 __ j(below, &bad, Label::kNear); |
| 3004 __ CmpInstanceType(kScratchRegister, LAST_EXTERNAL_ARRAY_TYPE); |
| 3005 __ j(below_equal, &ok, Label::kNear); |
| 3006 __ bind(&bad); |
| 3007 __ Abort(kObjectAccessCheckFailed); |
| 3008 __ bind(&ok); |
| 3009 break; |
| 3010 } |
| 3011 case HObjectAccess::FOR_FIXED_ARRAY_HEADER: |
| 3012 if (access->offset() == 0) break; // Setting the map. |
| 3013 // Else fall through. |
| 3014 case HObjectAccess::FOR_FIXED_ARRAY_LENGTH: { |
| 3015 Label ok, bad; |
| 3016 __ movp(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset)); |
| 3017 __ CmpInstanceType(kScratchRegister, FIRST_FIXED_ARRAY_TYPE); |
| 3018 __ j(below, &bad, Label::kNear); |
| 3019 __ CmpInstanceType(kScratchRegister, LAST_FIXED_ARRAY_TYPE); |
| 3020 __ j(below_equal, &ok, Label::kNear); |
| 3021 __ bind(&bad); |
| 3022 __ Abort(kObjectAccessCheckFailed); |
| 3023 __ bind(&ok); |
| 3024 break; |
| 3025 } |
| 3026 case HObjectAccess::FOR_CONS_STRING_FIRST: |
| 3027 case HObjectAccess::FOR_CONS_STRING_SECOND: { |
| 3028 Label ok; |
| 3029 __ CompareMap(object, isolate()->factory()->cons_string_map()); |
| 3030 __ j(equal, &ok, Label::kNear); |
| 3031 __ CompareMap(object, isolate()->factory()->cons_ascii_string_map()); |
| 3032 __ j(equal, &ok, Label::kNear); |
| 3033 __ Abort(kObjectAccessCheckFailed); |
| 3034 __ bind(&ok); |
| 3035 break; |
| 3036 } |
| 3037 |
| 3038 case HObjectAccess::FOR_CELL_PAYLOAD: { |
| 3039 Label ok; |
| 3040 __ CompareMap(object, isolate()->factory()->cell_map()); |
| 3041 __ j(equal, &ok, Label::kNear); |
| 3042 __ CompareMap(object, isolate()->factory()->global_property_cell_map()); |
| 3043 __ j(equal, &ok, Label::kNear); |
| 3044 __ Abort(kObjectAccessCheckFailed); |
| 3045 __ bind(&ok); |
| 3046 break; |
| 3047 } |
| 3048 |
| 3049 case HObjectAccess::FOR_BACKING_STORE_OFFSET: { |
| 3050 ASSERT(!access->IsInobject()); |
| 3051 // Load backing store. |
| 3052 __ movp(kScratchRegister, |
| 3053 FieldOperand(object, JSObject::kPropertiesOffset)); |
| 3054 // Load backing store length, with implicit Smi untagging. |
| 3055 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 3056 __ movl(kScratchRegister, |
| 3057 FieldOperand(kScratchRegister, |
| 3058 FixedArray::kLengthOffset + kPointerSize / 2)); |
| 3059 // The loaded length does not include the backing store's header size, |
| 3060 // but access->offset() does. |
| 3061 ASSERT(access->offset() >= FixedArray::kHeaderSize); |
| 3062 int accessed_index = |
| 3063 (access->offset() - FixedArray::kHeaderSize) / kPointerSize; |
| 3064 __ cmpl(kScratchRegister, Immediate(accessed_index)); |
| 3065 __ Check(above, kObjectAccessCheckFailed); |
| 3066 break; |
| 3067 } |
| 3068 case HObjectAccess::FOR_FIELD: { |
| 3069 ASSERT(access->IsInobject()); |
| 3070 Label ok; |
| 3071 __ movp(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset)); |
| 3072 // Some objects have variable instance size (e.g. FixedArray). |
| 3073 // To check those, we'd need an equivalent of HeapObject::SizeFromMap. |
| 3074 // For now we just skip such objects. |
| 3075 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceSizeOffset), |
| 3076 Immediate(kVariableSizeSentinel)); |
| 3077 __ j(equal, &ok, Label::kNear); |
| 3078 |
| 3079 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceSizeOffset), |
| 3080 Immediate(access->offset() / kPointerSize)); |
| 3081 __ Check(above, kObjectAccessCheckFailed); |
| 3082 __ bind(&ok); |
| 3083 break; |
| 3084 } |
| 3085 case HObjectAccess::FOR_GLOBAL_OBJECT_NATIVE_CONTEXT: |
| 3086 case HObjectAccess::FOR_MAP: |
| 3087 // Unimplemented. That's OK for now. |
| 3088 break; |
| 3089 |
| 3090 case HObjectAccess::FOR_ALLOCATION_SITE_LIST: |
| 3091 case HObjectAccess::FOR_COUNTER: |
| 3092 // External. Handled differently. |
| 3093 case HObjectAccess::UNKNOWN_PURPOSE: |
| 3094 // Don't use UNKNOWN_PURPOSE. |
| 3095 UNREACHABLE(); |
| 3096 break; |
| 3097 } |
| 3098 } |
| 3099 #endif |
| 3100 |
| 3101 |
| 2897 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3102 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2898 HObjectAccess access = instr->hydrogen()->access(); | 3103 HObjectAccess access = instr->hydrogen()->access(); |
| 2899 int offset = access.offset(); | 3104 int offset = access.offset(); |
| 2900 | 3105 |
| 2901 if (access.IsExternalMemory()) { | 3106 if (access.IsExternalMemory()) { |
| 2902 Register result = ToRegister(instr->result()); | 3107 Register result = ToRegister(instr->result()); |
| 2903 if (instr->object()->IsConstantOperand()) { | 3108 if (instr->object()->IsConstantOperand()) { |
| 2904 ASSERT(result.is(rax)); | 3109 ASSERT(result.is(rax)); |
| 2905 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); | 3110 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); |
| 2906 } else { | 3111 } else { |
| 2907 Register object = ToRegister(instr->object()); | 3112 Register object = ToRegister(instr->object()); |
| 2908 __ Load(result, MemOperand(object, offset), access.representation()); | 3113 __ Load(result, MemOperand(object, offset), access.representation()); |
| 2909 } | 3114 } |
| 2910 return; | 3115 return; |
| 2911 } | 3116 } |
| 2912 | 3117 |
| 2913 Register object = ToRegister(instr->object()); | 3118 Register object = ToRegister(instr->object()); |
| 3119 #ifdef DEBUG |
| 3120 EmitObjectAccessVerification(&access, object, false); |
| 3121 #endif |
| 2914 if (instr->hydrogen()->representation().IsDouble()) { | 3122 if (instr->hydrogen()->representation().IsDouble()) { |
| 2915 XMMRegister result = ToDoubleRegister(instr->result()); | 3123 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2916 __ movsd(result, FieldOperand(object, offset)); | 3124 __ movsd(result, FieldOperand(object, offset)); |
| 2917 return; | 3125 return; |
| 2918 } | 3126 } |
| 2919 | 3127 |
| 2920 Register result = ToRegister(instr->result()); | 3128 Register result = ToRegister(instr->result()); |
| 2921 if (!access.IsInobject()) { | 3129 if (!access.IsInobject()) { |
| 2922 __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 3130 __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2923 object = result; | 3131 object = result; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3024 } else { | 3232 } else { |
| 3025 __ subl(length, ToOperand(instr->index())); | 3233 __ subl(length, ToOperand(instr->index())); |
| 3026 } | 3234 } |
| 3027 StackArgumentsAccessor args(arguments, length, | 3235 StackArgumentsAccessor args(arguments, length, |
| 3028 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 3236 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 3029 __ movp(result, args.GetArgumentOperand(0)); | 3237 __ movp(result, args.GetArgumentOperand(0)); |
| 3030 } | 3238 } |
| 3031 } | 3239 } |
| 3032 | 3240 |
| 3033 | 3241 |
| 3242 #ifdef DEBUG |
| 3243 void LCodeGen::EmitKeyedAccessVerification(LOperand* elements, |
| 3244 Operand operand) { |
| 3245 if (!FLAG_debug_code) return; |
| 3246 Register elements_reg = ToRegister(elements); |
| 3247 Register length_scratch = kScratchRegister; |
| 3248 Register access_scratch = r11; |
| 3249 __ Push(access_scratch); |
| 3250 // 64-bit platforms make it easy :-) |
| 3251 STATIC_ASSERT(kPointerSize == kDoubleSize); |
| 3252 const int kHeaderSize = FixedArrayBase::kHeaderSize; |
| 3253 STATIC_ASSERT(kHeaderSize == FixedArray::kHeaderSize); |
| 3254 STATIC_ASSERT(kHeaderSize == FixedDoubleArray::kHeaderSize); |
| 3255 STATIC_ASSERT(kHeaderSize == FixedTypedArrayBase::kHeaderSize); |
| 3256 |
| 3257 // Load elements length, with implicit Smi untagging. |
| 3258 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 3259 __ movl(length_scratch, |
| 3260 FieldOperand(elements_reg, |
| 3261 FixedArrayBase::kLengthOffset + kPointerSize / 2)); |
| 3262 // Multiply with pointer size and add header size to get the object length. |
| 3263 __ leaq(length_scratch, |
| 3264 Operand(length_scratch, times_pointer_size, |
| 3265 kHeaderSize - kHeapObjectTag)); |
| 3266 // Compute the actually accessed offset in access_scratch. |
| 3267 __ leaq(access_scratch, operand); |
| 3268 __ subq(access_scratch, elements_reg); |
| 3269 __ cmpq(length_scratch, access_scratch); |
| 3270 __ Check(above, kObjectAccessCheckFailed); |
| 3271 __ Pop(access_scratch); |
| 3272 } |
| 3273 #endif |
| 3274 |
| 3275 |
| 3034 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 3276 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
| 3035 ElementsKind elements_kind = instr->elements_kind(); | 3277 ElementsKind elements_kind = instr->elements_kind(); |
| 3036 LOperand* key = instr->key(); | 3278 LOperand* key = instr->key(); |
| 3037 Operand operand(BuildFastArrayOperand( | 3279 Operand operand(BuildFastArrayOperand( |
| 3038 instr->elements(), | 3280 instr->elements(), |
| 3039 key, | 3281 key, |
| 3040 elements_kind, | 3282 elements_kind, |
| 3041 instr->base_offset())); | 3283 instr->base_offset())); |
| 3042 | 3284 |
| 3285 #ifdef DEBUG |
| 3286 // TODO(jkummerow): Support external elements too. |
| 3287 if (!IsExternalArrayElementsKind(elements_kind)) { |
| 3288 EmitKeyedAccessVerification(instr->elements(), operand); |
| 3289 } |
| 3290 #endif |
| 3291 |
| 3043 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 3292 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3044 elements_kind == FLOAT32_ELEMENTS) { | 3293 elements_kind == FLOAT32_ELEMENTS) { |
| 3045 XMMRegister result(ToDoubleRegister(instr->result())); | 3294 XMMRegister result(ToDoubleRegister(instr->result())); |
| 3046 __ movss(result, operand); | 3295 __ movss(result, operand); |
| 3047 __ cvtss2sd(result, result); | 3296 __ cvtss2sd(result, result); |
| 3048 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 3297 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 3049 elements_kind == FLOAT64_ELEMENTS) { | 3298 elements_kind == FLOAT64_ELEMENTS) { |
| 3050 __ movsd(ToDoubleRegister(instr->result()), operand); | 3299 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 3051 } else { | 3300 } else { |
| 3052 Register result(ToRegister(instr->result())); | 3301 Register result(ToRegister(instr->result())); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3111 instr->base_offset() + sizeof(kHoleNanLower32)); | 3360 instr->base_offset() + sizeof(kHoleNanLower32)); |
| 3112 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 3361 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 3113 DeoptimizeIf(equal, instr->environment()); | 3362 DeoptimizeIf(equal, instr->environment()); |
| 3114 } | 3363 } |
| 3115 | 3364 |
| 3116 Operand double_load_operand = BuildFastArrayOperand( | 3365 Operand double_load_operand = BuildFastArrayOperand( |
| 3117 instr->elements(), | 3366 instr->elements(), |
| 3118 key, | 3367 key, |
| 3119 FAST_DOUBLE_ELEMENTS, | 3368 FAST_DOUBLE_ELEMENTS, |
| 3120 instr->base_offset()); | 3369 instr->base_offset()); |
| 3370 #ifdef DEBUG |
| 3371 EmitKeyedAccessVerification(instr->elements(), double_load_operand); |
| 3372 #endif |
| 3121 __ movsd(result, double_load_operand); | 3373 __ movsd(result, double_load_operand); |
| 3122 } | 3374 } |
| 3123 | 3375 |
| 3124 | 3376 |
| 3125 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3377 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3126 HLoadKeyed* hinstr = instr->hydrogen(); | 3378 HLoadKeyed* hinstr = instr->hydrogen(); |
| 3127 Register result = ToRegister(instr->result()); | 3379 Register result = ToRegister(instr->result()); |
| 3128 LOperand* key = instr->key(); | 3380 LOperand* key = instr->key(); |
| 3129 bool requires_hole_check = hinstr->RequiresHoleCheck(); | 3381 bool requires_hole_check = hinstr->RequiresHoleCheck(); |
| 3130 Representation representation = hinstr->representation(); | 3382 Representation representation = hinstr->representation(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3142 offset), | 3394 offset), |
| 3143 Representation::Smi()); | 3395 Representation::Smi()); |
| 3144 __ AssertSmi(scratch); | 3396 __ AssertSmi(scratch); |
| 3145 } | 3397 } |
| 3146 // Read int value directly from upper half of the smi. | 3398 // Read int value directly from upper half of the smi. |
| 3147 STATIC_ASSERT(kSmiTag == 0); | 3399 STATIC_ASSERT(kSmiTag == 0); |
| 3148 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 3400 ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 3149 offset += kPointerSize / 2; | 3401 offset += kPointerSize / 2; |
| 3150 } | 3402 } |
| 3151 | 3403 |
| 3152 __ Load(result, | 3404 Operand operand = BuildFastArrayOperand(instr->elements(), |
| 3153 BuildFastArrayOperand(instr->elements(), | 3405 key, |
| 3154 key, | 3406 FAST_ELEMENTS, |
| 3155 FAST_ELEMENTS, | 3407 offset); |
| 3156 offset), | 3408 #ifdef DEBUG |
| 3157 representation); | 3409 EmitKeyedAccessVerification(instr->elements(), operand); |
| 3410 #endif |
| 3411 __ Load(result, operand, representation); |
| 3158 | 3412 |
| 3159 // Check for the hole value. | 3413 // Check for the hole value. |
| 3160 if (requires_hole_check) { | 3414 if (requires_hole_check) { |
| 3161 if (IsFastSmiElementsKind(hinstr->elements_kind())) { | 3415 if (IsFastSmiElementsKind(hinstr->elements_kind())) { |
| 3162 Condition smi = __ CheckSmi(result); | 3416 Condition smi = __ CheckSmi(result); |
| 3163 DeoptimizeIf(NegateCondition(smi), instr->environment()); | 3417 DeoptimizeIf(NegateCondition(smi), instr->environment()); |
| 3164 } else { | 3418 } else { |
| 3165 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 3419 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 3166 DeoptimizeIf(equal, instr->environment()); | 3420 DeoptimizeIf(equal, instr->environment()); |
| 3167 } | 3421 } |
| (...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3994 __ store_rax(ToExternalReference(object)); | 4248 __ store_rax(ToExternalReference(object)); |
| 3995 } else { | 4249 } else { |
| 3996 Register object = ToRegister(instr->object()); | 4250 Register object = ToRegister(instr->object()); |
| 3997 __ Store(MemOperand(object, offset), value, representation); | 4251 __ Store(MemOperand(object, offset), value, representation); |
| 3998 } | 4252 } |
| 3999 return; | 4253 return; |
| 4000 } | 4254 } |
| 4001 | 4255 |
| 4002 Register object = ToRegister(instr->object()); | 4256 Register object = ToRegister(instr->object()); |
| 4003 __ AssertNotSmi(object); | 4257 __ AssertNotSmi(object); |
| 4258 #ifdef DEBUG |
| 4259 EmitObjectAccessVerification(&access, object, true); |
| 4260 #endif |
| 4004 | 4261 |
| 4005 ASSERT(!representation.IsSmi() || | 4262 ASSERT(!representation.IsSmi() || |
| 4006 !instr->value()->IsConstantOperand() || | 4263 !instr->value()->IsConstantOperand() || |
| 4007 IsInteger32Constant(LConstantOperand::cast(instr->value()))); | 4264 IsInteger32Constant(LConstantOperand::cast(instr->value()))); |
| 4008 if (representation.IsDouble()) { | 4265 if (representation.IsDouble()) { |
| 4009 ASSERT(access.IsInobject()); | 4266 ASSERT(access.IsInobject()); |
| 4010 ASSERT(!hinstr->has_transition()); | 4267 ASSERT(!hinstr->has_transition()); |
| 4011 ASSERT(!hinstr->NeedsWriteBarrier()); | 4268 ASSERT(!hinstr->NeedsWriteBarrier()); |
| 4012 XMMRegister value = ToDoubleRegister(instr->value()); | 4269 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4013 __ movsd(FieldOperand(object, offset), value); | 4270 __ movsd(FieldOperand(object, offset), value); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4167 | 4424 |
| 4168 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4425 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4169 ElementsKind elements_kind = instr->elements_kind(); | 4426 ElementsKind elements_kind = instr->elements_kind(); |
| 4170 LOperand* key = instr->key(); | 4427 LOperand* key = instr->key(); |
| 4171 Operand operand(BuildFastArrayOperand( | 4428 Operand operand(BuildFastArrayOperand( |
| 4172 instr->elements(), | 4429 instr->elements(), |
| 4173 key, | 4430 key, |
| 4174 elements_kind, | 4431 elements_kind, |
| 4175 instr->base_offset())); | 4432 instr->base_offset())); |
| 4176 | 4433 |
| 4434 #ifdef DEBUG |
| 4435 if (!IsExternalArrayElementsKind(elements_kind)) { |
| 4436 EmitKeyedAccessVerification(instr->elements(), operand); |
| 4437 } |
| 4438 #endif |
| 4439 |
| 4177 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 4440 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4178 elements_kind == FLOAT32_ELEMENTS) { | 4441 elements_kind == FLOAT32_ELEMENTS) { |
| 4179 XMMRegister value(ToDoubleRegister(instr->value())); | 4442 XMMRegister value(ToDoubleRegister(instr->value())); |
| 4180 __ cvtsd2ss(value, value); | 4443 __ cvtsd2ss(value, value); |
| 4181 __ movss(operand, value); | 4444 __ movss(operand, value); |
| 4182 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 4445 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 4183 elements_kind == FLOAT64_ELEMENTS) { | 4446 elements_kind == FLOAT64_ELEMENTS) { |
| 4184 __ movsd(operand, ToDoubleRegister(instr->value())); | 4447 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 4185 } else { | 4448 } else { |
| 4186 Register value(ToRegister(instr->value())); | 4449 Register value(ToRegister(instr->value())); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4238 __ movq(value, kScratchRegister); | 4501 __ movq(value, kScratchRegister); |
| 4239 | 4502 |
| 4240 __ bind(&have_value); | 4503 __ bind(&have_value); |
| 4241 } | 4504 } |
| 4242 | 4505 |
| 4243 Operand double_store_operand = BuildFastArrayOperand( | 4506 Operand double_store_operand = BuildFastArrayOperand( |
| 4244 instr->elements(), | 4507 instr->elements(), |
| 4245 key, | 4508 key, |
| 4246 FAST_DOUBLE_ELEMENTS, | 4509 FAST_DOUBLE_ELEMENTS, |
| 4247 instr->base_offset()); | 4510 instr->base_offset()); |
| 4248 | 4511 #ifdef DEBUG |
| 4512 EmitKeyedAccessVerification(instr->elements(), double_store_operand); |
| 4513 #endif |
| 4249 __ movsd(double_store_operand, value); | 4514 __ movsd(double_store_operand, value); |
| 4250 } | 4515 } |
| 4251 | 4516 |
| 4252 | 4517 |
| 4253 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4518 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4254 HStoreKeyed* hinstr = instr->hydrogen(); | 4519 HStoreKeyed* hinstr = instr->hydrogen(); |
| 4255 LOperand* key = instr->key(); | 4520 LOperand* key = instr->key(); |
| 4256 int offset = instr->base_offset(); | 4521 int offset = instr->base_offset(); |
| 4257 Representation representation = hinstr->value()->representation(); | 4522 Representation representation = hinstr->value()->representation(); |
| 4258 | 4523 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4273 STATIC_ASSERT(kSmiTag == 0); | 4538 STATIC_ASSERT(kSmiTag == 0); |
| 4274 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 4539 ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 4275 offset += kPointerSize / 2; | 4540 offset += kPointerSize / 2; |
| 4276 } | 4541 } |
| 4277 | 4542 |
| 4278 Operand operand = | 4543 Operand operand = |
| 4279 BuildFastArrayOperand(instr->elements(), | 4544 BuildFastArrayOperand(instr->elements(), |
| 4280 key, | 4545 key, |
| 4281 FAST_ELEMENTS, | 4546 FAST_ELEMENTS, |
| 4282 offset); | 4547 offset); |
| 4548 #ifdef DEBUG |
| 4549 EmitKeyedAccessVerification(instr->elements(), operand); |
| 4550 #endif |
| 4283 if (instr->value()->IsRegister()) { | 4551 if (instr->value()->IsRegister()) { |
| 4284 __ Store(operand, ToRegister(instr->value()), representation); | 4552 __ Store(operand, ToRegister(instr->value()), representation); |
| 4285 } else { | 4553 } else { |
| 4286 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4554 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4287 if (IsInteger32Constant(operand_value)) { | 4555 if (IsInteger32Constant(operand_value)) { |
| 4288 int32_t value = ToInteger32(operand_value); | 4556 int32_t value = ToInteger32(operand_value); |
| 4289 if (representation.IsSmi()) { | 4557 if (representation.IsSmi()) { |
| 4290 __ Move(operand, Smi::FromInt(value)); | 4558 __ Move(operand, Smi::FromInt(value)); |
| 4291 | 4559 |
| 4292 } else { | 4560 } else { |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5683 __ bind(deferred->exit()); | 5951 __ bind(deferred->exit()); |
| 5684 __ bind(&done); | 5952 __ bind(&done); |
| 5685 } | 5953 } |
| 5686 | 5954 |
| 5687 | 5955 |
| 5688 #undef __ | 5956 #undef __ |
| 5689 | 5957 |
| 5690 } } // namespace v8::internal | 5958 } } // namespace v8::internal |
| 5691 | 5959 |
| 5692 #endif // V8_TARGET_ARCH_X64 | 5960 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |