Chromium Code Reviews| 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::EmitObjectAccessChecks(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. | |
|
Igor Sheludko
2014/06/05 09:04:30
STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
Jakob Kummerow
2014/06/05 14:33:31
Done.
| |
| 3055 __ movl(kScratchRegister, | |
| 3056 FieldOperand(kScratchRegister, | |
| 3057 FixedArray::kLengthOffset + kPointerSize / 2)); | |
| 3058 // The loaded length does not include the backing store's header size, | |
| 3059 // but access->offset() does. | |
| 3060 ASSERT(access->offset() >= FixedArray::kHeaderSize); | |
| 3061 int accessed_index = | |
| 3062 (access->offset() - FixedArray::kHeaderSize) / kPointerSize; | |
| 3063 __ cmpl(kScratchRegister, Immediate(accessed_index)); | |
| 3064 __ Check(above, kObjectAccessCheckFailed); | |
| 3065 break; | |
| 3066 } | |
| 3067 case HObjectAccess::FOR_FIELD: { | |
| 3068 ASSERT(access->IsInobject()); | |
| 3069 Label ok; | |
| 3070 __ movp(kScratchRegister, FieldOperand(object, HeapObject::kMapOffset)); | |
| 3071 // Some objects have variable instance size (e.g. FixedArray). | |
| 3072 // To check those, we'd need an equivalent of HeapObject::SizeFromMap. | |
| 3073 // For now we just skip such objects. | |
| 3074 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceSizeOffset), | |
| 3075 Immediate(kVariableSizeSentinel)); | |
| 3076 __ j(equal, &ok, Label::kNear); | |
| 3077 | |
| 3078 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceSizeOffset), | |
| 3079 Immediate(access->offset() / kPointerSize)); | |
| 3080 __ Check(above, kObjectAccessCheckFailed); | |
| 3081 __ bind(&ok); | |
| 3082 break; | |
| 3083 } | |
| 3084 case HObjectAccess::FOR_GLOBAL_OBJECT_NATIVE_CONTEXT: | |
| 3085 case HObjectAccess::FOR_MAP: | |
| 3086 // Unimplemented. That's OK for now. | |
| 3087 break; | |
| 3088 | |
| 3089 case HObjectAccess::FOR_ALLOCATION_SITE_LIST: | |
| 3090 case HObjectAccess::FOR_COUNTER: | |
| 3091 // External. Handled differently. | |
| 3092 case HObjectAccess::UNKNOWN_PURPOSE: | |
| 3093 // Don't use UNKNOWN_PURPOSE. | |
|
Igor Sheludko
2014/06/05 09:04:30
default:
Jakob Kummerow
2014/06/05 14:33:31
Nope. We generally don't use "default:" cases when
| |
| 3094 UNREACHABLE(); | |
| 3095 break; | |
| 3096 } | |
| 3097 } | |
| 3098 #endif | |
| 3099 | |
| 3100 | |
| 2897 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3101 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2898 HObjectAccess access = instr->hydrogen()->access(); | 3102 HObjectAccess access = instr->hydrogen()->access(); |
| 2899 int offset = access.offset(); | 3103 int offset = access.offset(); |
| 2900 | 3104 |
| 2901 if (access.IsExternalMemory()) { | 3105 if (access.IsExternalMemory()) { |
| 2902 Register result = ToRegister(instr->result()); | 3106 Register result = ToRegister(instr->result()); |
| 2903 if (instr->object()->IsConstantOperand()) { | 3107 if (instr->object()->IsConstantOperand()) { |
| 2904 ASSERT(result.is(rax)); | 3108 ASSERT(result.is(rax)); |
| 2905 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); | 3109 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); |
| 2906 } else { | 3110 } else { |
| 2907 Register object = ToRegister(instr->object()); | 3111 Register object = ToRegister(instr->object()); |
| 2908 __ Load(result, MemOperand(object, offset), access.representation()); | 3112 __ Load(result, MemOperand(object, offset), access.representation()); |
| 2909 } | 3113 } |
| 2910 return; | 3114 return; |
| 2911 } | 3115 } |
| 2912 | 3116 |
| 2913 Register object = ToRegister(instr->object()); | 3117 Register object = ToRegister(instr->object()); |
| 3118 #ifdef DEBUG | |
| 3119 EmitObjectAccessChecks(&access, object, false); | |
| 3120 #endif | |
| 2914 if (instr->hydrogen()->representation().IsDouble()) { | 3121 if (instr->hydrogen()->representation().IsDouble()) { |
| 2915 XMMRegister result = ToDoubleRegister(instr->result()); | 3122 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2916 __ movsd(result, FieldOperand(object, offset)); | 3123 __ movsd(result, FieldOperand(object, offset)); |
| 2917 return; | 3124 return; |
| 2918 } | 3125 } |
| 2919 | 3126 |
| 2920 Register result = ToRegister(instr->result()); | 3127 Register result = ToRegister(instr->result()); |
| 2921 if (!access.IsInobject()) { | 3128 if (!access.IsInobject()) { |
| 2922 __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 3129 __ movp(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2923 object = result; | 3130 object = result; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3024 } else { | 3231 } else { |
| 3025 __ subl(length, ToOperand(instr->index())); | 3232 __ subl(length, ToOperand(instr->index())); |
| 3026 } | 3233 } |
| 3027 StackArgumentsAccessor args(arguments, length, | 3234 StackArgumentsAccessor args(arguments, length, |
| 3028 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 3235 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 3029 __ movp(result, args.GetArgumentOperand(0)); | 3236 __ movp(result, args.GetArgumentOperand(0)); |
| 3030 } | 3237 } |
| 3031 } | 3238 } |
| 3032 | 3239 |
| 3033 | 3240 |
| 3241 #ifdef DEBUG | |
| 3242 void LCodeGen::EmitKeyedAccessCheck(LOperand* elements, Operand operand) { | |
| 3243 if (!FLAG_debug_code) return; | |
| 3244 Register elements_reg = ToRegister(elements); | |
| 3245 Register length_scratch = kScratchRegister; | |
| 3246 Register access_scratch = r11; | |
| 3247 __ Push(access_scratch); | |
| 3248 // 64-bit platforms make it easy :-) | |
| 3249 STATIC_ASSERT(kPointerSize == kDoubleSize); | |
| 3250 const int kHeaderSize = FixedArrayBase::kHeaderSize; | |
| 3251 STATIC_ASSERT(kHeaderSize == FixedArray::kHeaderSize); | |
| 3252 STATIC_ASSERT(kHeaderSize == FixedDoubleArray::kHeaderSize); | |
| 3253 STATIC_ASSERT(kHeaderSize == FixedTypedArrayBase::kHeaderSize); | |
| 3254 | |
| 3255 // Load elements length, with implicit Smi untagging. | |
|
Igor Sheludko
2014/06/05 09:04:30
STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32);
Jakob Kummerow
2014/06/05 14:33:31
Done.
| |
| 3256 __ movl(length_scratch, | |
| 3257 FieldOperand(elements_reg, | |
| 3258 FixedArrayBase::kLengthOffset + kPointerSize / 2)); | |
| 3259 // Multiply with pointer size and add header size to get the object length. | |
| 3260 __ leaq(length_scratch, | |
| 3261 Operand(length_scratch, times_pointer_size, | |
| 3262 kHeaderSize - kHeapObjectTag)); | |
| 3263 // Compute the actually accessed offset in access_scratch. | |
| 3264 __ leaq(access_scratch, operand); | |
| 3265 __ subq(access_scratch, elements_reg); | |
| 3266 __ cmpq(length_scratch, access_scratch); | |
| 3267 __ Check(above, kObjectAccessCheckFailed); | |
| 3268 __ Pop(access_scratch); | |
| 3269 } | |
| 3270 #endif | |
| 3271 | |
| 3272 | |
| 3034 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 3273 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
| 3035 ElementsKind elements_kind = instr->elements_kind(); | 3274 ElementsKind elements_kind = instr->elements_kind(); |
| 3036 LOperand* key = instr->key(); | 3275 LOperand* key = instr->key(); |
| 3037 Operand operand(BuildFastArrayOperand( | 3276 Operand operand(BuildFastArrayOperand( |
| 3038 instr->elements(), | 3277 instr->elements(), |
| 3039 key, | 3278 key, |
| 3040 elements_kind, | 3279 elements_kind, |
| 3041 instr->base_offset())); | 3280 instr->base_offset())); |
| 3042 | 3281 |
| 3282 #ifdef DEBUG | |
| 3283 // TODO(jkummerow): Support external elements too. | |
| 3284 if (!IsExternalArrayElementsKind(elements_kind)) { | |
| 3285 EmitKeyedAccessCheck(instr->elements(), operand); | |
| 3286 } | |
| 3287 #endif | |
| 3288 | |
| 3043 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 3289 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3044 elements_kind == FLOAT32_ELEMENTS) { | 3290 elements_kind == FLOAT32_ELEMENTS) { |
| 3045 XMMRegister result(ToDoubleRegister(instr->result())); | 3291 XMMRegister result(ToDoubleRegister(instr->result())); |
| 3046 __ movss(result, operand); | 3292 __ movss(result, operand); |
| 3047 __ cvtss2sd(result, result); | 3293 __ cvtss2sd(result, result); |
| 3048 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 3294 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 3049 elements_kind == FLOAT64_ELEMENTS) { | 3295 elements_kind == FLOAT64_ELEMENTS) { |
| 3050 __ movsd(ToDoubleRegister(instr->result()), operand); | 3296 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 3051 } else { | 3297 } else { |
| 3052 Register result(ToRegister(instr->result())); | 3298 Register result(ToRegister(instr->result())); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3111 instr->base_offset() + sizeof(kHoleNanLower32)); | 3357 instr->base_offset() + sizeof(kHoleNanLower32)); |
| 3112 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 3358 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 3113 DeoptimizeIf(equal, instr->environment()); | 3359 DeoptimizeIf(equal, instr->environment()); |
| 3114 } | 3360 } |
| 3115 | 3361 |
| 3116 Operand double_load_operand = BuildFastArrayOperand( | 3362 Operand double_load_operand = BuildFastArrayOperand( |
| 3117 instr->elements(), | 3363 instr->elements(), |
| 3118 key, | 3364 key, |
| 3119 FAST_DOUBLE_ELEMENTS, | 3365 FAST_DOUBLE_ELEMENTS, |
| 3120 instr->base_offset()); | 3366 instr->base_offset()); |
| 3367 #ifdef DEBUG | |
| 3368 EmitKeyedAccessCheck(instr->elements(), double_load_operand); | |
| 3369 #endif | |
| 3121 __ movsd(result, double_load_operand); | 3370 __ movsd(result, double_load_operand); |
| 3122 } | 3371 } |
| 3123 | 3372 |
| 3124 | 3373 |
| 3125 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3374 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3126 HLoadKeyed* hinstr = instr->hydrogen(); | 3375 HLoadKeyed* hinstr = instr->hydrogen(); |
| 3127 Register result = ToRegister(instr->result()); | 3376 Register result = ToRegister(instr->result()); |
| 3128 LOperand* key = instr->key(); | 3377 LOperand* key = instr->key(); |
| 3129 bool requires_hole_check = hinstr->RequiresHoleCheck(); | 3378 bool requires_hole_check = hinstr->RequiresHoleCheck(); |
| 3130 Representation representation = hinstr->representation(); | 3379 Representation representation = hinstr->representation(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 3142 offset), | 3391 offset), |
| 3143 Representation::Smi()); | 3392 Representation::Smi()); |
| 3144 __ AssertSmi(scratch); | 3393 __ AssertSmi(scratch); |
| 3145 } | 3394 } |
| 3146 // Read int value directly from upper half of the smi. | 3395 // Read int value directly from upper half of the smi. |
| 3147 STATIC_ASSERT(kSmiTag == 0); | 3396 STATIC_ASSERT(kSmiTag == 0); |
| 3148 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 3397 ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 3149 offset += kPointerSize / 2; | 3398 offset += kPointerSize / 2; |
| 3150 } | 3399 } |
| 3151 | 3400 |
| 3152 __ Load(result, | 3401 Operand operand = BuildFastArrayOperand(instr->elements(), |
| 3153 BuildFastArrayOperand(instr->elements(), | 3402 key, |
| 3154 key, | 3403 FAST_ELEMENTS, |
| 3155 FAST_ELEMENTS, | 3404 offset); |
| 3156 offset), | 3405 #ifdef DEBUG |
| 3157 representation); | 3406 EmitKeyedAccessCheck(instr->elements(), operand); |
| 3407 #endif | |
| 3408 __ Load(result, operand, representation); | |
| 3158 | 3409 |
| 3159 // Check for the hole value. | 3410 // Check for the hole value. |
| 3160 if (requires_hole_check) { | 3411 if (requires_hole_check) { |
| 3161 if (IsFastSmiElementsKind(hinstr->elements_kind())) { | 3412 if (IsFastSmiElementsKind(hinstr->elements_kind())) { |
| 3162 Condition smi = __ CheckSmi(result); | 3413 Condition smi = __ CheckSmi(result); |
| 3163 DeoptimizeIf(NegateCondition(smi), instr->environment()); | 3414 DeoptimizeIf(NegateCondition(smi), instr->environment()); |
| 3164 } else { | 3415 } else { |
| 3165 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 3416 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 3166 DeoptimizeIf(equal, instr->environment()); | 3417 DeoptimizeIf(equal, instr->environment()); |
| 3167 } | 3418 } |
| (...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3994 __ store_rax(ToExternalReference(object)); | 4245 __ store_rax(ToExternalReference(object)); |
| 3995 } else { | 4246 } else { |
| 3996 Register object = ToRegister(instr->object()); | 4247 Register object = ToRegister(instr->object()); |
| 3997 __ Store(MemOperand(object, offset), value, representation); | 4248 __ Store(MemOperand(object, offset), value, representation); |
| 3998 } | 4249 } |
| 3999 return; | 4250 return; |
| 4000 } | 4251 } |
| 4001 | 4252 |
| 4002 Register object = ToRegister(instr->object()); | 4253 Register object = ToRegister(instr->object()); |
| 4003 __ AssertNotSmi(object); | 4254 __ AssertNotSmi(object); |
| 4255 #ifdef DEBUG | |
| 4256 EmitObjectAccessChecks(&access, object, true); | |
| 4257 #endif | |
| 4258 | |
|
Igor Sheludko
2014/06/05 09:04:30
Extra empty line?
Jakob Kummerow
2014/06/05 14:33:31
Done.
| |
| 4004 | 4259 |
| 4005 ASSERT(!representation.IsSmi() || | 4260 ASSERT(!representation.IsSmi() || |
| 4006 !instr->value()->IsConstantOperand() || | 4261 !instr->value()->IsConstantOperand() || |
| 4007 IsInteger32Constant(LConstantOperand::cast(instr->value()))); | 4262 IsInteger32Constant(LConstantOperand::cast(instr->value()))); |
| 4008 if (representation.IsDouble()) { | 4263 if (representation.IsDouble()) { |
| 4009 ASSERT(access.IsInobject()); | 4264 ASSERT(access.IsInobject()); |
| 4010 ASSERT(!hinstr->has_transition()); | 4265 ASSERT(!hinstr->has_transition()); |
| 4011 ASSERT(!hinstr->NeedsWriteBarrier()); | 4266 ASSERT(!hinstr->NeedsWriteBarrier()); |
| 4012 XMMRegister value = ToDoubleRegister(instr->value()); | 4267 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4013 __ movsd(FieldOperand(object, offset), value); | 4268 __ movsd(FieldOperand(object, offset), value); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4167 | 4422 |
| 4168 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4423 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4169 ElementsKind elements_kind = instr->elements_kind(); | 4424 ElementsKind elements_kind = instr->elements_kind(); |
| 4170 LOperand* key = instr->key(); | 4425 LOperand* key = instr->key(); |
| 4171 Operand operand(BuildFastArrayOperand( | 4426 Operand operand(BuildFastArrayOperand( |
| 4172 instr->elements(), | 4427 instr->elements(), |
| 4173 key, | 4428 key, |
| 4174 elements_kind, | 4429 elements_kind, |
| 4175 instr->base_offset())); | 4430 instr->base_offset())); |
| 4176 | 4431 |
| 4432 #ifdef DEBUG | |
| 4433 if (!IsExternalArrayElementsKind(elements_kind)) { | |
| 4434 EmitKeyedAccessCheck(instr->elements(), operand); | |
| 4435 } | |
| 4436 #endif | |
| 4437 | |
| 4177 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 4438 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4178 elements_kind == FLOAT32_ELEMENTS) { | 4439 elements_kind == FLOAT32_ELEMENTS) { |
| 4179 XMMRegister value(ToDoubleRegister(instr->value())); | 4440 XMMRegister value(ToDoubleRegister(instr->value())); |
| 4180 __ cvtsd2ss(value, value); | 4441 __ cvtsd2ss(value, value); |
| 4181 __ movss(operand, value); | 4442 __ movss(operand, value); |
| 4182 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 4443 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 4183 elements_kind == FLOAT64_ELEMENTS) { | 4444 elements_kind == FLOAT64_ELEMENTS) { |
| 4184 __ movsd(operand, ToDoubleRegister(instr->value())); | 4445 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 4185 } else { | 4446 } else { |
| 4186 Register value(ToRegister(instr->value())); | 4447 Register value(ToRegister(instr->value())); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4238 __ movq(value, kScratchRegister); | 4499 __ movq(value, kScratchRegister); |
| 4239 | 4500 |
| 4240 __ bind(&have_value); | 4501 __ bind(&have_value); |
| 4241 } | 4502 } |
| 4242 | 4503 |
| 4243 Operand double_store_operand = BuildFastArrayOperand( | 4504 Operand double_store_operand = BuildFastArrayOperand( |
| 4244 instr->elements(), | 4505 instr->elements(), |
| 4245 key, | 4506 key, |
| 4246 FAST_DOUBLE_ELEMENTS, | 4507 FAST_DOUBLE_ELEMENTS, |
| 4247 instr->base_offset()); | 4508 instr->base_offset()); |
| 4248 | 4509 #ifdef DEBUG |
| 4510 EmitKeyedAccessCheck(instr->elements(), double_store_operand); | |
| 4511 #endif | |
| 4249 __ movsd(double_store_operand, value); | 4512 __ movsd(double_store_operand, value); |
| 4250 } | 4513 } |
| 4251 | 4514 |
| 4252 | 4515 |
| 4253 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4516 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4254 HStoreKeyed* hinstr = instr->hydrogen(); | 4517 HStoreKeyed* hinstr = instr->hydrogen(); |
| 4255 LOperand* key = instr->key(); | 4518 LOperand* key = instr->key(); |
| 4256 int offset = instr->base_offset(); | 4519 int offset = instr->base_offset(); |
| 4257 Representation representation = hinstr->value()->representation(); | 4520 Representation representation = hinstr->value()->representation(); |
| 4258 | 4521 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 4273 STATIC_ASSERT(kSmiTag == 0); | 4536 STATIC_ASSERT(kSmiTag == 0); |
| 4274 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 4537 ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 4275 offset += kPointerSize / 2; | 4538 offset += kPointerSize / 2; |
| 4276 } | 4539 } |
| 4277 | 4540 |
| 4278 Operand operand = | 4541 Operand operand = |
| 4279 BuildFastArrayOperand(instr->elements(), | 4542 BuildFastArrayOperand(instr->elements(), |
| 4280 key, | 4543 key, |
| 4281 FAST_ELEMENTS, | 4544 FAST_ELEMENTS, |
| 4282 offset); | 4545 offset); |
| 4546 #ifdef DEBUG | |
| 4547 EmitKeyedAccessCheck(instr->elements(), operand); | |
| 4548 #endif | |
| 4283 if (instr->value()->IsRegister()) { | 4549 if (instr->value()->IsRegister()) { |
| 4284 __ Store(operand, ToRegister(instr->value()), representation); | 4550 __ Store(operand, ToRegister(instr->value()), representation); |
| 4285 } else { | 4551 } else { |
| 4286 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4552 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4287 if (IsInteger32Constant(operand_value)) { | 4553 if (IsInteger32Constant(operand_value)) { |
| 4288 int32_t value = ToInteger32(operand_value); | 4554 int32_t value = ToInteger32(operand_value); |
| 4289 if (representation.IsSmi()) { | 4555 if (representation.IsSmi()) { |
| 4290 __ Move(operand, Smi::FromInt(value)); | 4556 __ Move(operand, Smi::FromInt(value)); |
| 4291 | 4557 |
| 4292 } else { | 4558 } else { |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5683 __ bind(deferred->exit()); | 5949 __ bind(deferred->exit()); |
| 5684 __ bind(&done); | 5950 __ bind(&done); |
| 5685 } | 5951 } |
| 5686 | 5952 |
| 5687 | 5953 |
| 5688 #undef __ | 5954 #undef __ |
| 5689 | 5955 |
| 5690 } } // namespace v8::internal | 5956 } } // namespace v8::internal |
| 5691 | 5957 |
| 5692 #endif // V8_TARGET_ARCH_X64 | 5958 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |