| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 3036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3047 } else if (right_cid == kSmiCid) { | 3047 } else if (right_cid == kSmiCid) { |
| 3048 __ tsti(left, Immediate(kSmiTagMask)); | 3048 __ tsti(left, Immediate(kSmiTagMask)); |
| 3049 } else { | 3049 } else { |
| 3050 __ orr(TMP, left, Operand(right)); | 3050 __ orr(TMP, left, Operand(right)); |
| 3051 __ tsti(TMP, Immediate(kSmiTagMask)); | 3051 __ tsti(TMP, Immediate(kSmiTagMask)); |
| 3052 } | 3052 } |
| 3053 __ b(deopt, EQ); | 3053 __ b(deopt, EQ); |
| 3054 } | 3054 } |
| 3055 | 3055 |
| 3056 | 3056 |
| 3057 LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate, | 3057 LocationSummary* BoxInstr::MakeLocationSummary(Isolate* isolate, |
| 3058 bool opt) const { | 3058 bool opt) const { |
| 3059 const intptr_t kNumInputs = 1; | 3059 const intptr_t kNumInputs = 1; |
| 3060 const intptr_t kNumTemps = 1; | 3060 const intptr_t kNumTemps = 1; |
| 3061 LocationSummary* summary = new(isolate) LocationSummary( | 3061 LocationSummary* summary = new(isolate) LocationSummary( |
| 3062 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3062 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3063 summary->set_in(0, Location::RequiresFpuRegister()); | 3063 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3064 summary->set_temp(0, Location::RequiresRegister()); | 3064 summary->set_temp(0, Location::RequiresRegister()); |
| 3065 summary->set_out(0, Location::RequiresRegister()); | 3065 summary->set_out(0, Location::RequiresRegister()); |
| 3066 return summary; | 3066 return summary; |
| 3067 } | 3067 } |
| 3068 | 3068 |
| 3069 | 3069 |
| 3070 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3070 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3071 const Register out_reg = locs()->out(0).reg(); | 3071 const Register out_reg = locs()->out(0).reg(); |
| 3072 const Register temp_reg = locs()->temp(0).reg(); | 3072 const Register temp_reg = locs()->temp(0).reg(); |
| 3073 const VRegister value = locs()->in(0).fpu_reg(); | 3073 const VRegister value = locs()->in(0).fpu_reg(); |
| 3074 | 3074 |
| 3075 BoxAllocationSlowPath::Allocate( | 3075 BoxAllocationSlowPath::Allocate( |
| 3076 compiler, this, compiler->double_class(), out_reg, temp_reg); | 3076 compiler, |
| 3077 __ StoreDFieldToOffset(value, out_reg, Double::value_offset(), PP); | 3077 this, |
| 3078 compiler->BoxClassFor(from_representation()), |
| 3079 out_reg, |
| 3080 temp_reg); |
| 3081 |
| 3082 switch (from_representation()) { |
| 3083 case kUnboxedDouble: |
| 3084 __ StoreDFieldToOffset(value, out_reg, ValueOffset(), PP); |
| 3085 break; |
| 3086 case kUnboxedFloat32x4: |
| 3087 case kUnboxedFloat64x2: |
| 3088 case kUnboxedInt32x4: |
| 3089 __ StoreQFieldToOffset(value, out_reg, ValueOffset(), PP); |
| 3090 break; |
| 3091 default: |
| 3092 UNREACHABLE(); |
| 3093 break; |
| 3094 } |
| 3078 } | 3095 } |
| 3079 | 3096 |
| 3080 | 3097 |
| 3081 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, | 3098 LocationSummary* UnboxInstr::MakeLocationSummary(Isolate* isolate, |
| 3082 bool opt) const { | 3099 bool opt) const { |
| 3083 const intptr_t kNumInputs = 1; | 3100 const intptr_t kNumInputs = 1; |
| 3084 const intptr_t kNumTemps = 0; | 3101 const intptr_t kNumTemps = 0; |
| 3085 LocationSummary* summary = new(isolate) LocationSummary( | 3102 LocationSummary* summary = new(isolate) LocationSummary( |
| 3086 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3103 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3087 summary->set_in(0, Location::RequiresRegister()); | 3104 summary->set_in(0, Location::RequiresRegister()); |
| 3088 summary->set_out(0, Location::RequiresFpuRegister()); | 3105 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3089 return summary; | 3106 return summary; |
| 3090 } | 3107 } |
| 3091 | 3108 |
| 3092 | 3109 |
| 3093 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3110 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 3094 CompileType* value_type = value()->Type(); | 3111 const Register box = locs()->in(0).reg(); |
| 3095 const intptr_t value_cid = value_type->ToCid(); | |
| 3096 const Register value = locs()->in(0).reg(); | |
| 3097 const VRegister result = locs()->out(0).fpu_reg(); | |
| 3098 | 3112 |
| 3099 if (value_cid == kDoubleCid) { | 3113 switch (representation()) { |
| 3100 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); | 3114 case kUnboxedMint: { |
| 3101 } else if (value_cid == kSmiCid) { | 3115 UNIMPLEMENTED(); |
| 3102 __ SmiUntag(TMP, value); // Untag input before conversion. | 3116 break; |
| 3103 __ scvtfdx(result, TMP); | 3117 } |
| 3118 |
| 3119 case kUnboxedDouble: { |
| 3120 const VRegister result = locs()->out(0).fpu_reg(); |
| 3121 __ LoadDFieldFromOffset(result, box, ValueOffset(), PP); |
| 3122 break; |
| 3123 } |
| 3124 |
| 3125 case kUnboxedFloat32x4: |
| 3126 case kUnboxedFloat64x2: |
| 3127 case kUnboxedInt32x4: { |
| 3128 const VRegister result = locs()->out(0).fpu_reg(); |
| 3129 __ LoadQFieldFromOffset(result, box, ValueOffset(), PP); |
| 3130 break; |
| 3131 } |
| 3132 |
| 3133 default: |
| 3134 UNREACHABLE(); |
| 3135 break; |
| 3136 } |
| 3137 } |
| 3138 |
| 3139 |
| 3140 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
| 3141 const Register box = locs()->in(0).reg(); |
| 3142 |
| 3143 switch (representation()) { |
| 3144 case kUnboxedMint: { |
| 3145 UNIMPLEMENTED(); |
| 3146 break; |
| 3147 } |
| 3148 |
| 3149 case kUnboxedDouble: { |
| 3150 const VRegister result = locs()->out(0).fpu_reg(); |
| 3151 __ SmiUntag(TMP, box); |
| 3152 __ scvtfdx(result, TMP); |
| 3153 break; |
| 3154 } |
| 3155 |
| 3156 default: |
| 3157 UNREACHABLE(); |
| 3158 break; |
| 3159 } |
| 3160 } |
| 3161 |
| 3162 |
| 3163 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3164 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3165 const intptr_t box_cid = BoxCid(); |
| 3166 |
| 3167 if (value_cid == box_cid) { |
| 3168 EmitLoadFromBox(compiler); |
| 3169 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3170 EmitSmiConversion(compiler); |
| 3104 } else { | 3171 } else { |
| 3172 const Register box = locs()->in(0).reg(); |
| 3105 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3173 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), |
| 3106 ICData::kDeoptBinaryDoubleOp); | 3174 ICData::kDeoptCheckClass); |
| 3107 if (value_type->is_nullable() && | 3175 Label is_smi; |
| 3108 (value_type->ToNullableCid() == kDoubleCid)) { | 3176 |
| 3109 __ CompareObject(value, Object::null_object(), PP); | 3177 if ((value()->Type()->ToNullableCid() == box_cid) && |
| 3178 value()->Type()->is_nullable()) { |
| 3179 __ CompareObject(box, Object::null_object(), PP); |
| 3110 __ b(deopt, EQ); | 3180 __ b(deopt, EQ); |
| 3111 // It must be double now. | |
| 3112 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); | |
| 3113 } else { | 3181 } else { |
| 3114 Label is_smi, done; | 3182 __ tsti(box, Immediate(kSmiTagMask)); |
| 3115 __ tsti(value, Immediate(kSmiTagMask)); | 3183 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); |
| 3116 __ b(&is_smi, EQ); | 3184 __ CompareClassId(box, box_cid, PP); |
| 3117 __ CompareClassId(value, kDoubleCid, PP); | |
| 3118 __ b(deopt, NE); | 3185 __ b(deopt, NE); |
| 3119 __ LoadDFieldFromOffset(result, value, Double::value_offset(), PP); | 3186 } |
| 3187 |
| 3188 EmitLoadFromBox(compiler); |
| 3189 |
| 3190 if (is_smi.IsLinked()) { |
| 3191 Label done; |
| 3120 __ b(&done); | 3192 __ b(&done); |
| 3121 __ Bind(&is_smi); | 3193 __ Bind(&is_smi); |
| 3122 __ SmiUntag(TMP, value); // Copy and untag. | 3194 EmitSmiConversion(compiler); |
| 3123 __ scvtfdx(result, TMP); | |
| 3124 __ Bind(&done); | 3195 __ Bind(&done); |
| 3125 } | 3196 } |
| 3126 } | 3197 } |
| 3127 } | 3198 } |
| 3128 | 3199 |
| 3129 | 3200 |
| 3130 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, | 3201 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Isolate* isolate, |
| 3131 bool opt) const { | 3202 bool opt) const { |
| 3203 ASSERT((from_representation() == kUnboxedInt32) || |
| 3204 (from_representation() == kUnboxedUint32)); |
| 3132 const intptr_t kNumInputs = 1; | 3205 const intptr_t kNumInputs = 1; |
| 3133 const intptr_t kNumTemps = 1; | 3206 const intptr_t kNumTemps = 0; |
| 3134 LocationSummary* summary = new(isolate) LocationSummary( | 3207 LocationSummary* summary = new(isolate) LocationSummary( |
| 3135 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3208 isolate, |
| 3136 summary->set_in(0, Location::RequiresFpuRegister()); | 3209 kNumInputs, |
| 3137 summary->set_temp(0, Location::RequiresRegister()); | 3210 kNumTemps, |
| 3211 LocationSummary::kNoCall); |
| 3212 summary->set_in(0, Location::RequiresRegister()); |
| 3138 summary->set_out(0, Location::RequiresRegister()); | 3213 summary->set_out(0, Location::RequiresRegister()); |
| 3139 return summary; | 3214 return summary; |
| 3140 } | 3215 } |
| 3141 | 3216 |
| 3142 | 3217 |
| 3143 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3218 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3144 const Register out_reg = locs()->out(0).reg(); | 3219 Register value = locs()->in(0).reg(); |
| 3145 const Register temp_reg = locs()->temp(0).reg(); | 3220 Register out = locs()->out(0).reg(); |
| 3146 const VRegister value = locs()->in(0).fpu_reg(); | 3221 ASSERT(value != out); |
| 3147 | 3222 |
| 3148 BoxAllocationSlowPath::Allocate( | 3223 ASSERT(kSmiTagSize == 1); |
| 3149 compiler, this, compiler->float32x4_class(), out_reg, temp_reg); | 3224 // TODO(vegorov) implement and use UBFM/SBFM for this. |
| 3150 __ StoreQFieldToOffset(value, out_reg, Float32x4::value_offset(), PP); | 3225 __ LslImmediate(out, value, 32); |
| 3226 if (from_representation() == kUnboxedInt32) { |
| 3227 __ AsrImmediate(out, out, 32 - kSmiTagSize); |
| 3228 } else { |
| 3229 ASSERT(from_representation() == kUnboxedUint32); |
| 3230 __ LsrImmediate(out, out, 32 - kSmiTagSize); |
| 3231 } |
| 3151 } | 3232 } |
| 3152 | 3233 |
| 3153 | 3234 |
| 3154 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, | 3235 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) |
| 3236 |
| 3237 |
| 3238 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate, |
| 3155 bool opt) const { | 3239 bool opt) const { |
| 3156 const intptr_t kNumInputs = 1; | 3240 const intptr_t kNumInputs = 1; |
| 3157 const intptr_t kNumTemps = 0; | 3241 const intptr_t kNumTemps = 0; |
| 3158 LocationSummary* summary = new(isolate) LocationSummary( | 3242 LocationSummary* summary = new(isolate) LocationSummary( |
| 3159 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3243 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3160 summary->set_in(0, Location::RequiresRegister()); | 3244 summary->set_in(0, Location::RequiresRegister()); |
| 3161 summary->set_out(0, Location::RequiresFpuRegister()); | |
| 3162 return summary; | |
| 3163 } | |
| 3164 | |
| 3165 | |
| 3166 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 3167 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 3168 const Register value = locs()->in(0).reg(); | |
| 3169 const VRegister result = locs()->out(0).fpu_reg(); | |
| 3170 | |
| 3171 if (value_cid != kFloat32x4Cid) { | |
| 3172 Label* deopt = | |
| 3173 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); | |
| 3174 __ tsti(value, Immediate(kSmiTagMask)); | |
| 3175 __ b(deopt, EQ); | |
| 3176 __ CompareClassId(value, kFloat32x4Cid, PP); | |
| 3177 __ b(deopt, NE); | |
| 3178 } | |
| 3179 | |
| 3180 __ LoadQFieldFromOffset(result, value, Float32x4::value_offset(), PP); | |
| 3181 } | |
| 3182 | |
| 3183 | |
| 3184 LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(Isolate* isolate, | |
| 3185 bool opt) const { | |
| 3186 const intptr_t kNumInputs = 1; | |
| 3187 const intptr_t kNumTemps = 1; | |
| 3188 LocationSummary* summary = new(isolate) LocationSummary( | |
| 3189 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | |
| 3190 summary->set_in(0, Location::RequiresFpuRegister()); | |
| 3191 summary->set_temp(0, Location::RequiresRegister()); | |
| 3192 summary->set_out(0, Location::RequiresRegister()); | 3245 summary->set_out(0, Location::RequiresRegister()); |
| 3193 return summary; | 3246 return summary; |
| 3194 } | 3247 } |
| 3195 | 3248 |
| 3196 | 3249 |
| 3197 void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3250 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3198 const Register out_reg = locs()->out(0).reg(); | 3251 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3199 const Register temp_reg = locs()->temp(0).reg(); | 3252 const Register out = locs()->out(0).reg(); |
| 3200 const VRegister value = locs()->in(0).fpu_reg(); | 3253 const Register value = locs()->in(0).reg(); |
| 3254 Label* deopt = CanDeoptimize() ? |
| 3255 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; |
| 3201 | 3256 |
| 3202 BoxAllocationSlowPath::Allocate( | 3257 if (value_cid == kSmiCid) { |
| 3203 compiler, this, compiler->float64x2_class(), out_reg, temp_reg); | 3258 __ SmiUntag(out, value); |
| 3204 __ StoreQFieldToOffset(value, out_reg, Float64x2::value_offset(), PP); | 3259 } else if (value_cid == kMintCid) { |
| 3260 __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP); |
| 3261 } else { |
| 3262 Label done; |
| 3263 __ SmiUntag(out, value); |
| 3264 __ TestImmediate(value, kSmiTagMask, PP); |
| 3265 __ b(&done, EQ); |
| 3266 __ CompareClassId(value, kMintCid, PP); |
| 3267 __ b(deopt, NE); |
| 3268 __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP); |
| 3269 __ Bind(&done); |
| 3270 } |
| 3271 |
| 3272 // TODO(vegorov): as it is implemented right now truncating unboxing would |
| 3273 // leave "garbage" in the higher word. |
| 3274 if (!is_truncating() && (deopt != NULL)) { |
| 3275 ASSERT(representation() == kUnboxedInt32); |
| 3276 __ cmp(out, Operand(out, SXTW, 0)); |
| 3277 __ b(deopt, NE); |
| 3278 } |
| 3205 } | 3279 } |
| 3206 | 3280 |
| 3207 | 3281 |
| 3208 LocationSummary* UnboxFloat64x2Instr::MakeLocationSummary(Isolate* isolate, | |
| 3209 bool opt) const { | |
| 3210 const intptr_t kNumInputs = 1; | |
| 3211 const intptr_t kNumTemps = 0; | |
| 3212 LocationSummary* summary = new(isolate) LocationSummary( | |
| 3213 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 3214 summary->set_in(0, Location::RequiresRegister()); | |
| 3215 summary->set_out(0, Location::RequiresFpuRegister()); | |
| 3216 return summary; | |
| 3217 } | |
| 3218 | |
| 3219 | |
| 3220 void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 3221 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 3222 const Register value = locs()->in(0).reg(); | |
| 3223 const VRegister result = locs()->out(0).fpu_reg(); | |
| 3224 | |
| 3225 if (value_cid != kFloat64x2Cid) { | |
| 3226 Label* deopt = | |
| 3227 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); | |
| 3228 __ tsti(value, Immediate(kSmiTagMask)); | |
| 3229 __ b(deopt, EQ); | |
| 3230 __ CompareClassId(value, kFloat64x2Cid, PP); | |
| 3231 __ b(deopt, NE); | |
| 3232 } | |
| 3233 | |
| 3234 __ LoadQFieldFromOffset(result, value, Float64x2::value_offset(), PP); | |
| 3235 } | |
| 3236 | |
| 3237 | |
| 3238 LocationSummary* BoxInt32x4Instr::MakeLocationSummary(Isolate* isolate, | |
| 3239 bool opt) const { | |
| 3240 const intptr_t kNumInputs = 1; | |
| 3241 const intptr_t kNumTemps = 1; | |
| 3242 LocationSummary* summary = new(isolate) LocationSummary( | |
| 3243 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | |
| 3244 summary->set_in(0, Location::RequiresFpuRegister()); | |
| 3245 summary->set_temp(0, Location::RequiresRegister()); | |
| 3246 summary->set_out(0, Location::RequiresRegister()); | |
| 3247 return summary; | |
| 3248 } | |
| 3249 | |
| 3250 | |
| 3251 void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 3252 const Register out_reg = locs()->out(0).reg(); | |
| 3253 const Register temp_reg = locs()->temp(0).reg(); | |
| 3254 const VRegister value = locs()->in(0).fpu_reg(); | |
| 3255 BoxAllocationSlowPath::Allocate( | |
| 3256 compiler, this, compiler->int32x4_class(), out_reg, temp_reg); | |
| 3257 __ StoreQFieldToOffset(value, out_reg, Int32x4::value_offset(), PP); | |
| 3258 } | |
| 3259 | |
| 3260 | |
| 3261 LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(Isolate* isolate, | |
| 3262 bool opt) const { | |
| 3263 const intptr_t kNumInputs = 1; | |
| 3264 const intptr_t kNumTemps = 0; | |
| 3265 LocationSummary* summary = new(isolate) LocationSummary( | |
| 3266 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 3267 summary->set_in(0, Location::RequiresRegister()); | |
| 3268 summary->set_out(0, Location::RequiresFpuRegister()); | |
| 3269 return summary; | |
| 3270 } | |
| 3271 | |
| 3272 | |
| 3273 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 3274 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 3275 const Register value = locs()->in(0).reg(); | |
| 3276 const VRegister result = locs()->out(0).fpu_reg(); | |
| 3277 | |
| 3278 if (value_cid != kInt32x4Cid) { | |
| 3279 Label* deopt = | |
| 3280 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); | |
| 3281 __ tsti(value, Immediate(kSmiTagMask)); | |
| 3282 __ b(deopt, EQ); | |
| 3283 __ CompareClassId(value, kInt32x4Cid, PP); | |
| 3284 __ b(deopt, NE); | |
| 3285 } | |
| 3286 | |
| 3287 __ LoadQFieldFromOffset(result, value, Int32x4::value_offset(), PP); | |
| 3288 } | |
| 3289 | |
| 3290 | |
| 3291 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, | 3282 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, |
| 3292 bool opt) const { | 3283 bool opt) const { |
| 3293 const intptr_t kNumInputs = 2; | 3284 const intptr_t kNumInputs = 2; |
| 3294 const intptr_t kNumTemps = 0; | 3285 const intptr_t kNumTemps = 0; |
| 3295 LocationSummary* summary = new(isolate) LocationSummary( | 3286 LocationSummary* summary = new(isolate) LocationSummary( |
| 3296 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3287 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3297 summary->set_in(0, Location::RequiresFpuRegister()); | 3288 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3298 summary->set_in(1, Location::RequiresFpuRegister()); | 3289 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3299 summary->set_out(0, Location::RequiresFpuRegister()); | 3290 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3300 return summary; | 3291 return summary; |
| (...skipping 1874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5175 } | 5166 } |
| 5176 } else { | 5167 } else { |
| 5177 const Register length = length_loc.reg(); | 5168 const Register length = length_loc.reg(); |
| 5178 const Register index = index_loc.reg(); | 5169 const Register index = index_loc.reg(); |
| 5179 __ CompareRegisters(index, length); | 5170 __ CompareRegisters(index, length); |
| 5180 __ b(deopt, CS); | 5171 __ b(deopt, CS); |
| 5181 } | 5172 } |
| 5182 } | 5173 } |
| 5183 | 5174 |
| 5184 | 5175 |
| 5185 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate, | |
| 5186 bool opt) const { | |
| 5187 UNIMPLEMENTED(); | |
| 5188 return NULL; | |
| 5189 } | |
| 5190 | |
| 5191 | |
| 5192 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5193 UNIMPLEMENTED(); | |
| 5194 } | |
| 5195 | |
| 5196 | |
| 5197 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, | |
| 5198 bool opt) const { | |
| 5199 UNIMPLEMENTED(); | |
| 5200 return NULL; | |
| 5201 } | |
| 5202 | |
| 5203 | |
| 5204 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5205 UNIMPLEMENTED(); | |
| 5206 } | |
| 5207 | |
| 5208 | |
| 5209 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, | 5176 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, |
| 5210 bool opt) const { | 5177 bool opt) const { |
| 5211 UNIMPLEMENTED(); | 5178 UNIMPLEMENTED(); |
| 5212 return NULL; | 5179 return NULL; |
| 5213 } | 5180 } |
| 5214 | 5181 |
| 5215 | 5182 |
| 5216 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5183 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5217 UNIMPLEMENTED(); | 5184 UNIMPLEMENTED(); |
| 5218 } | 5185 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5262 return CompileType::FromCid(kSmiCid); | 5229 return CompileType::FromCid(kSmiCid); |
| 5263 } | 5230 } |
| 5264 | 5231 |
| 5265 | 5232 |
| 5266 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5233 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) |
| 5267 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5234 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) |
| 5268 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5235 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) |
| 5269 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5236 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 5270 | 5237 |
| 5271 | 5238 |
| 5272 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, | |
| 5273 bool opt) const { | |
| 5274 const intptr_t kNumInputs = 1; | |
| 5275 const intptr_t kNumTemps = 0; | |
| 5276 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5277 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 5278 summary->set_in(0, Location::RequiresRegister()); | |
| 5279 summary->set_out(0, Location::RequiresRegister()); | |
| 5280 return summary; | |
| 5281 } | |
| 5282 | |
| 5283 | |
| 5284 void UnboxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5285 const intptr_t value_cid = value()->Type()->ToCid(); | |
| 5286 const Register out = locs()->out(0).reg(); | |
| 5287 const Register value = locs()->in(0).reg(); | |
| 5288 Label* deopt = CanDeoptimize() ? | |
| 5289 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | |
| 5290 | |
| 5291 if (value_cid == kSmiCid) { | |
| 5292 __ SmiUntag(out, value); | |
| 5293 } else if (value_cid == kMintCid) { | |
| 5294 __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP); | |
| 5295 } else { | |
| 5296 Label done; | |
| 5297 __ SmiUntag(out, value); | |
| 5298 __ TestImmediate(value, kSmiTagMask, PP); | |
| 5299 __ b(&done, EQ); | |
| 5300 __ CompareClassId(value, kMintCid, PP); | |
| 5301 __ b(deopt, NE); | |
| 5302 __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP); | |
| 5303 __ Bind(&done); | |
| 5304 } | |
| 5305 | |
| 5306 // TODO(vegorov): as it is implemented right now truncating unboxing would | |
| 5307 // leave "garbage" in the higher word. | |
| 5308 if (!is_truncating() && (deopt != NULL)) { | |
| 5309 ASSERT(representation() == kUnboxedInt32); | |
| 5310 __ cmp(out, Operand(out, SXTW, 0)); | |
| 5311 __ b(deopt, NE); | |
| 5312 } | |
| 5313 } | |
| 5314 | |
| 5315 | |
| 5316 LocationSummary* BoxIntNInstr::MakeLocationSummary(Isolate* isolate, | |
| 5317 bool opt) const { | |
| 5318 ASSERT((from_representation() == kUnboxedInt32) || | |
| 5319 (from_representation() == kUnboxedUint32)); | |
| 5320 const intptr_t kNumInputs = 1; | |
| 5321 const intptr_t kNumTemps = 0; | |
| 5322 LocationSummary* summary = new(isolate) LocationSummary( | |
| 5323 isolate, | |
| 5324 kNumInputs, | |
| 5325 kNumTemps, | |
| 5326 LocationSummary::kNoCall); | |
| 5327 summary->set_in(0, Location::RequiresRegister()); | |
| 5328 summary->set_out(0, Location::RequiresRegister()); | |
| 5329 return summary; | |
| 5330 } | |
| 5331 | |
| 5332 | |
| 5333 void BoxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
| 5334 Register value = locs()->in(0).reg(); | |
| 5335 Register out = locs()->out(0).reg(); | |
| 5336 ASSERT(value != out); | |
| 5337 | |
| 5338 ASSERT(kSmiTagSize == 1); | |
| 5339 // TODO(vegorov) implement and use UBFM/SBFM for this. | |
| 5340 __ LslImmediate(out, value, 32); | |
| 5341 if (from_representation() == kUnboxedInt32) { | |
| 5342 __ AsrImmediate(out, out, 32 - kSmiTagSize); | |
| 5343 } else { | |
| 5344 ASSERT(from_representation() == kUnboxedUint32); | |
| 5345 __ LsrImmediate(out, out, 32 - kSmiTagSize); | |
| 5346 } | |
| 5347 } | |
| 5348 | |
| 5349 | |
| 5350 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 5239 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 5351 bool opt) const { | 5240 bool opt) const { |
| 5352 const intptr_t kNumInputs = 1; | 5241 const intptr_t kNumInputs = 1; |
| 5353 const intptr_t kNumTemps = 0; | 5242 const intptr_t kNumTemps = 0; |
| 5354 LocationSummary* summary = new(isolate) LocationSummary( | 5243 LocationSummary* summary = new(isolate) LocationSummary( |
| 5355 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5244 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5356 if (from() == kUnboxedMint) { | 5245 if (from() == kUnboxedMint) { |
| 5357 UNREACHABLE(); | 5246 UNREACHABLE(); |
| 5358 } else if (to() == kUnboxedMint) { | 5247 } else if (to() == kUnboxedMint) { |
| 5359 UNREACHABLE(); | 5248 UNREACHABLE(); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5605 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 5494 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
| 5606 #if defined(DEBUG) | 5495 #if defined(DEBUG) |
| 5607 __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP); | 5496 __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP); |
| 5608 __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP); | 5497 __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP); |
| 5609 #endif | 5498 #endif |
| 5610 } | 5499 } |
| 5611 | 5500 |
| 5612 } // namespace dart | 5501 } // namespace dart |
| 5613 | 5502 |
| 5614 #endif // defined TARGET_ARCH_ARM64 | 5503 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |