| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
| 15 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 16 | 16 |
| 17 #define __ compiler->assembler()-> | 17 #define __ compiler->assembler()-> |
| 18 | 18 |
| 19 namespace dart { | 19 namespace dart { |
| 20 | 20 |
| 21 DECLARE_FLAG(int, optimization_counter_threshold); | 21 DECLARE_FLAG(int, optimization_counter_threshold); |
| 22 DECLARE_FLAG(bool, trace_functions); | 22 DECLARE_FLAG(bool, trace_functions); |
| 23 | 23 |
| 24 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 24 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 25 computation()->EmitNativeCode(compiler); | 25 computation()->EmitNativeCode(compiler); |
| 26 __ pushq(locs()->out().reg()); | 26 if (locs()->out().kind() == Location::kRegister) { |
| 27 // TODO(vegorov): this should really happen only for comparisons fused |
| 28 // with branches. Currrently IR does not provide an easy way to remove |
| 29 // instructions from the graph so we just leave fused comparison in it |
| 30 // but change its result location to be NoLocation. |
| 31 __ pushq(locs()->out().reg()); |
| 32 } |
| 27 } | 33 } |
| 28 | 34 |
| 29 | 35 |
| 30 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 36 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
| 31 const intptr_t kNumInputs = 1; | 37 const intptr_t kNumInputs = 1; |
| 32 const intptr_t kNumTemps = 1; | 38 const intptr_t kNumTemps = 1; |
| 33 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 39 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 34 locs->set_in(0, Location::RegisterLocation(RAX)); | 40 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 35 locs->set_temp(0, Location::RequiresRegister()); | 41 locs->set_temp(0, Location::RequiresRegister()); |
| 36 return locs; | 42 return locs; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 171 } |
| 166 | 172 |
| 167 | 173 |
| 168 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 174 void AssertBooleanComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 169 Register obj = locs()->in(0).reg(); | 175 Register obj = locs()->in(0).reg(); |
| 170 Register result = locs()->out().reg(); | 176 Register result = locs()->out().reg(); |
| 171 | 177 |
| 172 // Check that the type of the value is allowed in conditional context. | 178 // Check that the type of the value is allowed in conditional context. |
| 173 // Call the runtime if the object is not bool::true or bool::false. | 179 // Call the runtime if the object is not bool::true or bool::false. |
| 174 Label done; | 180 Label done; |
| 175 __ CompareObject(obj, Bool::ZoneHandle(Bool::True())); | 181 __ CompareObject(obj, compiler->bool_true()); |
| 176 __ j(EQUAL, &done, Assembler::kNearJump); | 182 __ j(EQUAL, &done, Assembler::kNearJump); |
| 177 __ CompareObject(obj, Bool::ZoneHandle(Bool::False())); | 183 __ CompareObject(obj, compiler->bool_false()); |
| 178 __ j(EQUAL, &done, Assembler::kNearJump); | 184 __ j(EQUAL, &done, Assembler::kNearJump); |
| 179 | 185 |
| 180 __ pushq(Immediate(Smi::RawValue(token_index()))); // Source location. | 186 __ pushq(Immediate(Smi::RawValue(token_index()))); // Source location. |
| 181 __ pushq(obj); // Push the source object. | 187 __ pushq(obj); // Push the source object. |
| 182 compiler->GenerateCallRuntime(cid(), | 188 compiler->GenerateCallRuntime(cid(), |
| 183 token_index(), | 189 token_index(), |
| 184 try_index(), | 190 try_index(), |
| 185 kConditionTypeErrorRuntimeEntry); | 191 kConditionTypeErrorRuntimeEntry); |
| 186 // We should never return here. | 192 // We should never return here. |
| 187 __ int3(); | 193 __ int3(); |
| 188 | 194 |
| 189 __ Bind(&done); | 195 __ Bind(&done); |
| 190 ASSERT(obj == result); | 196 ASSERT(obj == result); |
| 191 } | 197 } |
| 192 | 198 |
| 193 | 199 |
| 194 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 200 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
| 195 LocationSummary* locs = new LocationSummary(2, 0); | 201 LocationSummary* locs = new LocationSummary(2, 0); |
| 196 locs->set_in(0, Location::RequiresRegister()); | 202 locs->set_in(0, Location::RequiresRegister()); |
| 197 locs->set_in(1, Location::RequiresRegister()); | 203 locs->set_in(1, Location::RequiresRegister()); |
| 198 locs->set_out(Location::RegisterLocation(RAX)); | 204 if (!is_fused_with_branch()) { |
| 205 locs->set_out(Location::RegisterLocation(RAX)); |
| 206 } |
| 199 return locs; | 207 return locs; |
| 200 } | 208 } |
| 201 | 209 |
| 202 | 210 |
| 203 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 211 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 204 Register left = locs()->in(0).reg(); | 212 Register left = locs()->in(0).reg(); |
| 205 Register right = locs()->in(1).reg(); | 213 Register right = locs()->in(1).reg(); |
| 206 Register result = locs()->out().reg(); | |
| 207 ASSERT(locs()->out().reg() == RAX); | |
| 208 | 214 |
| 209 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 210 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 211 const Immediate raw_null = | 215 const Immediate raw_null = |
| 212 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 216 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 213 Label done, load_true, non_null_compare; | 217 Label done, non_null_compare; |
| 214 | 218 |
| 215 __ cmpq(left, raw_null); | 219 __ cmpq(left, raw_null); |
| 216 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 220 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 217 // Comparison with NULL is "===". | 221 // Comparison with NULL is "===". |
| 218 __ cmpq(left, right); | 222 __ cmpq(left, right); |
| 219 __ j(EQUAL, &load_true, Assembler::kNearJump); | 223 if (!is_fused_with_branch()) { |
| 220 __ LoadObject(result, bool_false); | 224 Register result = locs()->out().reg(); |
| 221 __ jmp(&done, Assembler::kNearJump); | 225 Label load_true; |
| 222 __ Bind(&load_true); | 226 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 223 __ LoadObject(result, bool_true); | 227 __ LoadObject(result, compiler->bool_false()); |
| 228 __ jmp(&done, Assembler::kNearJump); |
| 229 __ Bind(&load_true); |
| 230 __ LoadObject(result, compiler->bool_true()); |
| 231 } else { |
| 232 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 233 } |
| 224 __ jmp(&done); | 234 __ jmp(&done); |
| 225 | 235 |
| 236 |
| 226 __ Bind(&non_null_compare); | 237 __ Bind(&non_null_compare); |
| 227 __ pushq(left); | 238 __ pushq(left); |
| 228 __ pushq(right); | 239 __ pushq(right); |
| 229 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 240 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 230 const int kNumberOfArguments = 2; | 241 const int kNumberOfArguments = 2; |
| 231 const Array& kNoArgumentNames = Array::Handle(); | 242 const Array& kNoArgumentNames = Array::Handle(); |
| 232 const int kNumArgumentsChecked = 1; | 243 const int kNumArgumentsChecked = 1; |
| 233 | 244 |
| 234 compiler->GenerateInstanceCall(cid(), | 245 compiler->GenerateInstanceCall(cid(), |
| 235 token_index(), | 246 token_index(), |
| 236 try_index(), | 247 try_index(), |
| 237 operator_name, | 248 operator_name, |
| 238 kNumberOfArguments, | 249 kNumberOfArguments, |
| 239 kNoArgumentNames, | 250 kNoArgumentNames, |
| 240 kNumArgumentsChecked); | 251 kNumArgumentsChecked); |
| 252 ASSERT(fused_with_branch() != NULL || locs()->out().reg() == RAX); |
| 253 |
| 254 if (fused_with_branch() != NULL) { |
| 255 __ CompareObject(RAX, compiler->bool_true()); |
| 256 fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 257 } |
| 258 |
| 241 __ Bind(&done); | 259 __ Bind(&done); |
| 242 } | 260 } |
| 243 | 261 |
| 244 | 262 |
| 263 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 264 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { |
| 265 const intptr_t kNumInputs = 2; |
| 266 const intptr_t kNumTemps = 1; |
| 267 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
| 268 summary->set_in(0, Location::RequiresRegister()); |
| 269 summary->set_in(1, Location::RequiresRegister()); |
| 270 if (!is_fused_with_branch()) { |
| 271 summary->set_out(Location::RequiresRegister()); |
| 272 } |
| 273 summary->set_temp(0, Location::RequiresRegister()); |
| 274 return summary; |
| 275 } |
| 276 ASSERT(!is_fused_with_branch()); |
| 277 ASSERT(operands_class_id() == kObject); |
| 278 return MakeCallSummary(); |
| 279 } |
| 280 |
| 281 |
| 245 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 282 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 246 switch (kind) { | 283 switch (kind) { |
| 247 case Token::kEQ: return EQUAL; | 284 case Token::kEQ: return EQUAL; |
| 248 case Token::kNE: return NOT_EQUAL; | 285 case Token::kNE: return NOT_EQUAL; |
| 249 case Token::kLT: return LESS; | 286 case Token::kLT: return LESS; |
| 250 case Token::kGT: return GREATER; | 287 case Token::kGT: return GREATER; |
| 251 case Token::kLTE: return LESS_EQUAL; | 288 case Token::kLTE: return LESS_EQUAL; |
| 252 case Token::kGTE: return GREATER_EQUAL; | 289 case Token::kGTE: return GREATER_EQUAL; |
| 253 default: | 290 default: |
| 254 UNREACHABLE(); | 291 UNREACHABLE(); |
| 255 return OVERFLOW; | 292 return OVERFLOW; |
| 256 } | 293 } |
| 257 } | 294 } |
| 258 | 295 |
| 259 | 296 |
| 260 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, | 297 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, |
| 261 RelationalOpComp* comp) { | 298 RelationalOpComp* comp) { |
| 262 Register left = comp->locs()->in(0).reg(); | 299 Register left = comp->locs()->in(0).reg(); |
| 263 Register right = comp->locs()->in(1).reg(); | 300 Register right = comp->locs()->in(1).reg(); |
| 264 Register result = comp->locs()->out().reg(); | |
| 265 Register temp = comp->locs()->temp(0).reg(); | 301 Register temp = comp->locs()->temp(0).reg(); |
| 266 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 302 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 267 comp->token_index(), | 303 comp->token_index(), |
| 268 comp->try_index(), | 304 comp->try_index(), |
| 269 kDeoptSmiCompareSmis, | 305 kDeoptSmiCompareSmis, |
| 270 left, | 306 left, |
| 271 right); | 307 right); |
| 272 __ movq(temp, left); | 308 __ movq(temp, left); |
| 273 __ orq(temp, right); | 309 __ orq(temp, right); |
| 274 __ testq(temp, Immediate(kSmiTagMask)); | 310 __ testq(temp, Immediate(kSmiTagMask)); |
| 275 __ j(NOT_ZERO, deopt); | 311 __ j(NOT_ZERO, deopt); |
| 276 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | |
| 277 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 278 Condition condition = TokenKindToSmiCondition(comp->kind()); | |
| 279 | 312 |
| 280 Label done, is_true; | 313 Condition true_condition = TokenKindToSmiCondition(comp->kind()); |
| 281 __ cmpq(left, right); | 314 __ cmpq(left, right); |
| 282 __ j(condition, &is_true); | 315 |
| 283 __ LoadObject(result, bool_false); | 316 if (comp->is_fused_with_branch()) { |
| 284 __ jmp(&done); | 317 comp->fused_with_branch()->EmitBranchOnCondition(compiler, true_condition); |
| 285 __ Bind(&is_true); | 318 } else { |
| 286 __ LoadObject(result, bool_true); | 319 Register result = comp->locs()->out().reg(); |
| 287 __ Bind(&done); | 320 Label done, is_true; |
| 321 __ j(true_condition, &is_true); |
| 322 __ LoadObject(result, compiler->bool_false()); |
| 323 __ jmp(&done); |
| 324 __ Bind(&is_true); |
| 325 __ LoadObject(result, compiler->bool_true()); |
| 326 __ Bind(&done); |
| 327 } |
| 288 } | 328 } |
| 289 | 329 |
| 290 | 330 |
| 291 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | |
| 292 if (operands_class_id() == kSmi) { | |
| 293 const intptr_t kNumInputs = 2; | |
| 294 const intptr_t kNumTemps = 1; | |
| 295 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
| 296 summary->set_in(0, Location::RequiresRegister()); | |
| 297 summary->set_in(1, Location::RequiresRegister()); | |
| 298 summary->set_out(Location::RequiresRegister()); | |
| 299 summary->set_temp(0, Location::RequiresRegister()); | |
| 300 return summary; | |
| 301 } | |
| 302 if (operands_class_id() == kDouble) { | |
| 303 const intptr_t kNumInputs = 2; | |
| 304 const intptr_t kNumTemps = 1; | |
| 305 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
| 306 summary->set_in(0, Location::RequiresRegister()); | |
| 307 summary->set_in(1, Location::RequiresRegister()); | |
| 308 summary->set_out(Location::RequiresRegister()); | |
| 309 summary->set_temp(0, Location::RequiresRegister()); | |
| 310 return summary; | |
| 311 } | |
| 312 ASSERT(operands_class_id() == kObject); | |
| 313 return MakeCallSummary(); | |
| 314 } | |
| 315 | |
| 316 | |
| 317 | |
| 318 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 331 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 319 switch (kind) { | 332 switch (kind) { |
| 320 case Token::kEQ: return EQUAL; | 333 case Token::kEQ: return EQUAL; |
| 321 case Token::kLT: return BELOW; | 334 case Token::kLT: return BELOW; |
| 322 case Token::kGT: return ABOVE; | 335 case Token::kGT: return ABOVE; |
| 323 case Token::kLTE: return BELOW_EQUAL; | 336 case Token::kLTE: return BELOW_EQUAL; |
| 324 case Token::kGTE: return ABOVE_EQUAL; | 337 case Token::kGTE: return ABOVE_EQUAL; |
| 325 default: | 338 default: |
| 326 UNREACHABLE(); | 339 UNREACHABLE(); |
| 327 return OVERFLOW; | 340 return OVERFLOW; |
| 328 } | 341 } |
| 329 } | 342 } |
| 330 | 343 |
| 331 | 344 |
| 332 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, | 345 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, |
| 333 RelationalOpComp* comp) { | 346 RelationalOpComp* comp) { |
| 334 Register left = comp->locs()->in(0).reg(); | 347 Register left = comp->locs()->in(0).reg(); |
| 335 Register right = comp->locs()->in(1).reg(); | 348 Register right = comp->locs()->in(1).reg(); |
| 336 Register result = comp->locs()->out().reg(); | |
| 337 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 349 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 338 Register temp = comp->locs()->temp(0).reg(); | 350 Register temp = comp->locs()->temp(0).reg(); |
| 339 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 351 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 340 comp->token_index(), | 352 comp->token_index(), |
| 341 comp->try_index(), | 353 comp->try_index(), |
| 342 kDeoptDoubleComparison, | 354 kDeoptDoubleComparison, |
| 343 left, | 355 left, |
| 344 right); | 356 right); |
| 345 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 357 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 346 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 358 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 347 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 359 |
| 348 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | |
| 349 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); | 360 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); |
| 350 Label is_false, is_true, done; | |
| 351 __ comisd(XMM0, XMM1); | 361 __ comisd(XMM0, XMM1); |
| 352 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; | 362 |
| 353 __ j(true_condition, &is_true, Assembler::kNearJump); | 363 if (comp->is_fused_with_branch()) { |
| 354 __ Bind(&is_false); | 364 BranchInstr* branch = comp->fused_with_branch(); |
| 355 __ LoadObject(result, bool_false); | 365 __ j(PARITY_EVEN, compiler->GetBlockLabel(branch->false_successor())); |
| 356 __ jmp(&done); | 366 branch->EmitBranchOnCondition(compiler, true_condition); |
| 357 __ Bind(&is_true); | 367 } else { |
| 358 __ LoadObject(result, bool_true); | 368 Register result = comp->locs()->out().reg(); |
| 359 __ Bind(&done); | 369 Label is_false, is_true, done; |
| 370 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); |
| 371 __ j(true_condition, &is_true, Assembler::kNearJump); |
| 372 __ Bind(&is_false); |
| 373 __ LoadObject(result, compiler->bool_false()); |
| 374 __ jmp(&done); |
| 375 __ Bind(&is_true); |
| 376 __ LoadObject(result, compiler->bool_true()); |
| 377 __ Bind(&done); |
| 378 } |
| 360 } | 379 } |
| 361 | 380 |
| 362 | 381 |
| 363 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 382 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 364 if (operands_class_id() == kSmi) { | 383 if (operands_class_id() == kSmi) { |
| 365 EmitSmiRelationalOp(compiler, this); | 384 EmitSmiRelationalOp(compiler, this); |
| 366 return; | 385 return; |
| 367 } | 386 } |
| 368 if (operands_class_id() == kDouble) { | 387 if (operands_class_id() == kDouble) { |
| 369 EmitDoubleRelationalOp(compiler, this); | 388 EmitDoubleRelationalOp(compiler, this); |
| (...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1448 __ DoubleNegate(XMM0); | 1467 __ DoubleNegate(XMM0); |
| 1449 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1468 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1450 } else { | 1469 } else { |
| 1451 UNREACHABLE(); | 1470 UNREACHABLE(); |
| 1452 } | 1471 } |
| 1453 } | 1472 } |
| 1454 | 1473 |
| 1455 | 1474 |
| 1456 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1475 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
| 1457 const intptr_t kNumInputs = 1; | 1476 const intptr_t kNumInputs = 1; |
| 1458 const intptr_t kNumTemps = 0; | |
| 1459 if (from() == kDouble) { | 1477 if (from() == kDouble) { |
| 1478 const intptr_t kNumTemps = 0; |
| 1460 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1479 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 1461 locs->set_in(0, Location::RequiresRegister()); | 1480 locs->set_in(0, Location::RequiresRegister()); |
| 1462 locs->set_out(Location::SameAsFirstInput()); | 1481 locs->set_out(Location::SameAsFirstInput()); |
| 1463 return locs; | 1482 return locs; |
| 1464 } else { | 1483 } else { |
| 1465 ASSERT(from() == kSmi); | 1484 ASSERT(from() == kSmi); |
| 1466 return LocationSummary::Make(kNumInputs, Location::RegisterLocation(RAX)); | 1485 return LocationSummary::Make(kNumInputs, Location::RegisterLocation(RAX)); |
| 1467 } | 1486 } |
| 1468 } | 1487 } |
| 1469 | 1488 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 __ cvtsi2sd(XMM0, value); | 1535 __ cvtsi2sd(XMM0, value); |
| 1517 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1536 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1518 } | 1537 } |
| 1519 | 1538 |
| 1520 | 1539 |
| 1521 } // namespace dart | 1540 } // namespace dart |
| 1522 | 1541 |
| 1523 #undef __ | 1542 #undef __ |
| 1524 | 1543 |
| 1525 #endif // defined TARGET_ARCH_X64 | 1544 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |