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" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 __ Bind(¬_yet_hot); | 81 __ Bind(¬_yet_hot); |
82 __ Bind(&already_optimized); | 82 __ Bind(&already_optimized); |
83 } | 83 } |
84 } | 84 } |
85 if (FLAG_trace_functions) { | 85 if (FLAG_trace_functions) { |
86 const Function& function = | 86 const Function& function = |
87 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 87 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
88 __ LoadObject(temp, function); | 88 __ LoadObject(temp, function); |
89 __ pushq(result); // Preserve result. | 89 __ pushq(result); // Preserve result. |
90 __ pushq(temp); | 90 __ pushq(temp); |
91 compiler->GenerateCallRuntime(AstNode::kNoId, | 91 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, |
92 0, | 92 0, |
93 CatchClauseNode::kInvalidTryIndex, | 93 CatchClauseNode::kInvalidTryIndex, |
94 kTraceFunctionExitRuntimeEntry); | 94 kTraceFunctionExitRuntimeEntry); |
95 __ popq(temp); // Remove argument. | 95 __ popq(temp); // Remove argument. |
96 __ popq(result); // Restore result. | 96 __ popq(result); // Restore result. |
97 } | 97 } |
98 __ LeaveFrame(); | 98 __ LeaveFrame(); |
99 __ ret(); | 99 __ ret(); |
100 | 100 |
101 // Generate 8 bytes of NOPs so that the debugger can patch the | 101 // Generate 8 bytes of NOPs so that the debugger can patch the |
102 // return pattern with a call to the debug stub. | 102 // return pattern with a call to the debug stub. |
103 // Note that the nop(8) byte pattern is not recognized by the debugger. | 103 // Note that the nop(8) byte pattern is not recognized by the debugger. |
104 __ nop(1); | 104 __ nop(1); |
105 __ nop(1); | 105 __ nop(1); |
106 __ nop(1); | 106 __ nop(1); |
107 __ nop(1); | 107 __ nop(1); |
108 __ nop(1); | 108 __ nop(1); |
109 __ nop(1); | 109 __ nop(1); |
110 __ nop(1); | 110 __ nop(1); |
111 __ nop(1); | 111 __ nop(1); |
112 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 112 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
113 cid(), | 113 deopt_id(), |
114 token_pos(), | 114 token_pos(), |
115 CatchClauseNode::kInvalidTryIndex); | 115 CatchClauseNode::kInvalidTryIndex); |
116 } | 116 } |
117 | 117 |
118 | 118 |
119 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 119 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
120 const intptr_t kNumInputs = 0; | 120 const intptr_t kNumInputs = 0; |
121 const intptr_t kNumTemps = 1; | 121 const intptr_t kNumTemps = 1; |
122 LocationSummary* result = | 122 LocationSummary* result = |
123 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 123 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 | 198 |
199 // Check that the type of the value is allowed in conditional context. | 199 // Check that the type of the value is allowed in conditional context. |
200 // Call the runtime if the object is not bool::true or bool::false. | 200 // Call the runtime if the object is not bool::true or bool::false. |
201 Label done; | 201 Label done; |
202 __ CompareObject(obj, compiler->bool_true()); | 202 __ CompareObject(obj, compiler->bool_true()); |
203 __ j(EQUAL, &done, Assembler::kNearJump); | 203 __ j(EQUAL, &done, Assembler::kNearJump); |
204 __ CompareObject(obj, compiler->bool_false()); | 204 __ CompareObject(obj, compiler->bool_false()); |
205 __ j(EQUAL, &done, Assembler::kNearJump); | 205 __ j(EQUAL, &done, Assembler::kNearJump); |
206 | 206 |
207 __ pushq(obj); // Push the source object. | 207 __ pushq(obj); // Push the source object. |
208 compiler->GenerateCallRuntime(cid(), | 208 compiler->GenerateCallRuntime(deopt_id(), |
209 token_pos(), | 209 token_pos(), |
210 try_index(), | 210 try_index(), |
211 kConditionTypeErrorRuntimeEntry); | 211 kConditionTypeErrorRuntimeEntry); |
212 // We should never return here. | 212 // We should never return here. |
213 __ int3(); | 213 __ int3(); |
214 | 214 |
215 __ Bind(&done); | 215 __ Bind(&done); |
216 ASSERT(obj == result); | 216 ASSERT(obj == result); |
217 } | 217 } |
218 | 218 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 268 } |
269 | 269 |
270 | 270 |
271 // Optional integer arguments can often be null. Null is not collected | 271 // Optional integer arguments can often be null. Null is not collected |
272 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well? | 272 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well? |
273 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 273 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
274 EqualityCompareComp* comp) { | 274 EqualityCompareComp* comp) { |
275 Register left = comp->locs()->in(0).reg(); | 275 Register left = comp->locs()->in(0).reg(); |
276 Register right = comp->locs()->in(1).reg(); | 276 Register right = comp->locs()->in(1).reg(); |
277 Register temp = comp->locs()->temp(0).reg(); | 277 Register temp = comp->locs()->temp(0).reg(); |
278 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 278 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
279 comp->token_pos(), | 279 comp->token_pos(), |
280 comp->try_index(), | 280 comp->try_index(), |
281 kDeoptSmiCompareSmi, | 281 kDeoptSmiCompareSmi, |
282 left, | 282 left, |
283 right); | 283 right); |
284 __ movq(temp, left); | 284 __ movq(temp, left); |
285 __ orq(temp, right); | 285 __ orq(temp, right); |
286 __ testq(temp, Immediate(kSmiTagMask)); | 286 __ testq(temp, Immediate(kSmiTagMask)); |
287 __ j(NOT_ZERO, deopt); | 287 __ j(NOT_ZERO, deopt); |
288 __ cmpq(left, right); | 288 __ cmpq(left, right); |
289 Register result = comp->locs()->out().reg(); | 289 Register result = comp->locs()->out().reg(); |
290 Label load_true, done; | 290 Label load_true, done; |
291 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump); | 291 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump); |
292 __ LoadObject(result, compiler->bool_false()); | 292 __ LoadObject(result, compiler->bool_false()); |
293 __ jmp(&done, Assembler::kNearJump); | 293 __ jmp(&done, Assembler::kNearJump); |
294 __ Bind(&load_true); | 294 __ Bind(&load_true); |
295 __ LoadObject(result, compiler->bool_true()); | 295 __ LoadObject(result, compiler->bool_true()); |
296 __ Bind(&done); | 296 __ Bind(&done); |
297 } | 297 } |
298 | 298 |
299 | 299 |
300 // TODO(srdjan): Add support for mixed Smi/Double equality | 300 // TODO(srdjan): Add support for mixed Smi/Double equality |
301 // (see LoadDoubleOrSmiToXmm). | 301 // (see LoadDoubleOrSmiToXmm). |
302 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, | 302 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, |
303 EqualityCompareComp* comp) { | 303 EqualityCompareComp* comp) { |
304 Register left = comp->locs()->in(0).reg(); | 304 Register left = comp->locs()->in(0).reg(); |
305 Register right = comp->locs()->in(1).reg(); | 305 Register right = comp->locs()->in(1).reg(); |
306 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 306 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
307 comp->token_pos(), | 307 comp->token_pos(), |
308 comp->try_index(), | 308 comp->try_index(), |
309 kDeoptDoubleCompareDouble, | 309 kDeoptDoubleCompareDouble, |
310 left, | 310 left, |
311 right); | 311 right); |
312 __ CompareClassId(left, kDouble); | 312 __ CompareClassId(left, kDouble); |
313 __ j(NOT_EQUAL, deopt); | 313 __ j(NOT_EQUAL, deopt); |
314 __ CompareClassId(right, kDouble); | 314 __ CompareClassId(right, kDouble); |
315 __ j(NOT_EQUAL, deopt); | 315 __ j(NOT_EQUAL, deopt); |
316 __ movsd(XMM0, FieldAddress(left, Double::value_offset())); | 316 __ movsd(XMM0, FieldAddress(left, Double::value_offset())); |
317 __ movsd(XMM1, FieldAddress(right, Double::value_offset())); | 317 __ movsd(XMM1, FieldAddress(right, Double::value_offset())); |
318 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()), | 318 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()), |
319 XMM0, XMM1, | 319 XMM0, XMM1, |
320 comp->locs()->out().reg()); | 320 comp->locs()->out().reg()); |
321 } | 321 } |
322 | 322 |
323 | 323 |
324 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 324 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
325 EqualityCompareComp* comp) { | 325 EqualityCompareComp* comp) { |
326 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 326 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
327 comp->cid(), | 327 comp->deopt_id(), |
328 comp->token_pos(), | 328 comp->token_pos(), |
329 comp->try_index()); | 329 comp->try_index()); |
330 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 330 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
331 const int kNumberOfArguments = 2; | 331 const int kNumberOfArguments = 2; |
332 const Array& kNoArgumentNames = Array::Handle(); | 332 const Array& kNoArgumentNames = Array::Handle(); |
333 const int kNumArgumentsChecked = 2; | 333 const int kNumArgumentsChecked = 2; |
334 | 334 |
335 compiler->GenerateInstanceCall(comp->cid(), | 335 compiler->GenerateInstanceCall(comp->deopt_id(), |
336 comp->token_pos(), | 336 comp->token_pos(), |
337 comp->try_index(), | 337 comp->try_index(), |
338 operator_name, | 338 operator_name, |
339 kNumberOfArguments, | 339 kNumberOfArguments, |
340 kNoArgumentNames, | 340 kNoArgumentNames, |
341 kNumArgumentsChecked); | 341 kNumArgumentsChecked); |
342 ASSERT(comp->locs()->out().reg() == RAX); | 342 ASSERT(comp->locs()->out().reg() == RAX); |
343 if (comp->kind() == Token::kNE) { | 343 if (comp->kind() == Token::kNE) { |
344 Label done, false_label; | 344 Label done, false_label; |
345 __ CompareObject(RAX, compiler->bool_true()); | 345 __ CompareObject(RAX, compiler->bool_true()); |
346 __ j(EQUAL, &false_label, Assembler::kNearJump); | 346 __ j(EQUAL, &false_label, Assembler::kNearJump); |
347 __ LoadObject(RAX, compiler->bool_true()); | 347 __ LoadObject(RAX, compiler->bool_true()); |
348 __ jmp(&done, Assembler::kNearJump); | 348 __ jmp(&done, Assembler::kNearJump); |
349 __ Bind(&false_label); | 349 __ Bind(&false_label); |
350 __ LoadObject(RAX, compiler->bool_false()); | 350 __ LoadObject(RAX, compiler->bool_false()); |
351 __ Bind(&done); | 351 __ Bind(&done); |
352 } | 352 } |
353 } | 353 } |
354 | 354 |
355 | 355 |
356 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 356 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
357 const ICData& orig_ic_data, | 357 const ICData& orig_ic_data, |
358 const LocationSummary& locs, | 358 const LocationSummary& locs, |
359 BranchInstr* branch, | 359 BranchInstr* branch, |
360 Token::Kind kind, | 360 Token::Kind kind, |
361 intptr_t cid, | 361 intptr_t deopt_id, |
362 intptr_t token_pos, | 362 intptr_t token_pos, |
363 intptr_t try_index) { | 363 intptr_t try_index) { |
364 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 364 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
365 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 365 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
366 ASSERT(ic_data.NumberOfChecks() > 0); | 366 ASSERT(ic_data.NumberOfChecks() > 0); |
367 ASSERT(ic_data.num_args_tested() == 1); | 367 ASSERT(ic_data.num_args_tested() == 1); |
368 Label* deopt = compiler->AddDeoptStub(cid, | 368 Label* deopt = compiler->AddDeoptStub(deopt_id, |
369 token_pos, | 369 token_pos, |
370 try_index, | 370 try_index, |
371 kDeoptEquality); | 371 kDeoptEquality); |
372 Register left = locs.in(0).reg(); | 372 Register left = locs.in(0).reg(); |
373 Register right = locs.in(1).reg(); | 373 Register right = locs.in(1).reg(); |
374 __ testq(left, Immediate(kSmiTagMask)); | 374 __ testq(left, Immediate(kSmiTagMask)); |
375 Register temp = locs.temp(0).reg(); | 375 Register temp = locs.temp(0).reg(); |
376 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 376 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
377 Label done, load_class_id; | 377 Label done, load_class_id; |
378 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 378 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
(...skipping 27 matching lines...) Expand all Loading... |
406 Label load_true; | 406 Label load_true; |
407 __ j(cond, &load_true, Assembler::kNearJump); | 407 __ j(cond, &load_true, Assembler::kNearJump); |
408 __ LoadObject(result, compiler->bool_false()); | 408 __ LoadObject(result, compiler->bool_false()); |
409 __ jmp(&done); | 409 __ jmp(&done); |
410 __ Bind(&load_true); | 410 __ Bind(&load_true); |
411 __ LoadObject(result, compiler->bool_true()); | 411 __ LoadObject(result, compiler->bool_true()); |
412 } | 412 } |
413 } else { | 413 } else { |
414 const int kNumberOfArguments = 2; | 414 const int kNumberOfArguments = 2; |
415 const Array& kNoArgumentNames = Array::Handle(); | 415 const Array& kNoArgumentNames = Array::Handle(); |
416 compiler->GenerateStaticCall(cid, | 416 compiler->GenerateStaticCall(deopt_id, |
417 token_pos, | 417 token_pos, |
418 try_index, | 418 try_index, |
419 target, | 419 target, |
420 kNumberOfArguments, | 420 kNumberOfArguments, |
421 kNoArgumentNames); | 421 kNoArgumentNames); |
422 if (branch == NULL) { | 422 if (branch == NULL) { |
423 if (kind == Token::kNE) { | 423 if (kind == Token::kNE) { |
424 Label false_label; | 424 Label false_label; |
425 __ CompareObject(RAX, compiler->bool_true()); | 425 __ CompareObject(RAX, compiler->bool_true()); |
426 __ j(EQUAL, &false_label, Assembler::kNearJump); | 426 __ j(EQUAL, &false_label, Assembler::kNearJump); |
(...skipping 18 matching lines...) Expand all Loading... |
445 | 445 |
446 | 446 |
447 // First test if receiver is NULL, in which case === is applied. | 447 // First test if receiver is NULL, in which case === is applied. |
448 // If type feedback was provided (lists of <class-id, target>), do a | 448 // If type feedback was provided (lists of <class-id, target>), do a |
449 // type by type check (either === or static call to the operator. | 449 // type by type check (either === or static call to the operator. |
450 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 450 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
451 const LocationSummary& locs, | 451 const LocationSummary& locs, |
452 Token::Kind kind, | 452 Token::Kind kind, |
453 BranchInstr* branch, | 453 BranchInstr* branch, |
454 const ICData& ic_data, | 454 const ICData& ic_data, |
455 intptr_t cid, | 455 intptr_t deopt_id, |
456 intptr_t token_pos, | 456 intptr_t token_pos, |
457 intptr_t try_index) { | 457 intptr_t try_index) { |
458 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 458 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
459 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 459 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
460 Register left = locs.in(0).reg(); | 460 Register left = locs.in(0).reg(); |
461 Register right = locs.in(1).reg(); | 461 Register right = locs.in(1).reg(); |
462 const Immediate raw_null = | 462 const Immediate raw_null = |
463 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 463 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
464 Label done, non_null_compare; | 464 Label done, non_null_compare; |
465 __ cmpq(left, raw_null); | 465 __ cmpq(left, raw_null); |
(...skipping 10 matching lines...) Expand all Loading... |
476 __ LoadObject(result, compiler->bool_false()); | 476 __ LoadObject(result, compiler->bool_false()); |
477 __ jmp(&done); | 477 __ jmp(&done); |
478 __ Bind(&load_true); | 478 __ Bind(&load_true); |
479 __ LoadObject(result, compiler->bool_true()); | 479 __ LoadObject(result, compiler->bool_true()); |
480 } | 480 } |
481 __ jmp(&done); | 481 __ jmp(&done); |
482 __ Bind(&non_null_compare); // Receiver is not null. | 482 __ Bind(&non_null_compare); // Receiver is not null. |
483 __ pushq(left); | 483 __ pushq(left); |
484 __ pushq(right); | 484 __ pushq(right); |
485 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 485 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
486 cid, token_pos, try_index); | 486 deopt_id, token_pos, try_index); |
487 __ Bind(&done); | 487 __ Bind(&done); |
488 } | 488 } |
489 | 489 |
490 | 490 |
491 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 491 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
492 if (receiver_class_id() == kSmi) { | 492 if (receiver_class_id() == kSmi) { |
493 EmitSmiEqualityCompare(compiler, this); | 493 EmitSmiEqualityCompare(compiler, this); |
494 return; | 494 return; |
495 } | 495 } |
496 if (receiver_class_id() == kDouble) { | 496 if (receiver_class_id() == kDouble) { |
497 EmitDoubleEqualityCompare(compiler, this); | 497 EmitDoubleEqualityCompare(compiler, this); |
498 return; | 498 return; |
499 } | 499 } |
500 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 500 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
501 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, | 501 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), |
502 *ic_data(), cid(), token_pos(), try_index()); | 502 deopt_id(), token_pos(), try_index()); |
503 } else { | 503 } else { |
504 Register left = locs()->in(0).reg(); | 504 Register left = locs()->in(0).reg(); |
505 Register right = locs()->in(1).reg(); | 505 Register right = locs()->in(1).reg(); |
506 __ pushq(left); | 506 __ pushq(left); |
507 __ pushq(right); | 507 __ pushq(right); |
508 EmitEqualityAsInstanceCall(compiler, this); | 508 EmitEqualityAsInstanceCall(compiler, this); |
509 } | 509 } |
510 } | 510 } |
511 | 511 |
512 | 512 |
(...skipping 11 matching lines...) Expand all Loading... |
524 } | 524 } |
525 ASSERT(operands_class_id() == kObject); | 525 ASSERT(operands_class_id() == kObject); |
526 return MakeCallSummary(); | 526 return MakeCallSummary(); |
527 } | 527 } |
528 | 528 |
529 | 529 |
530 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 530 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
531 const LocationSummary& locs, | 531 const LocationSummary& locs, |
532 Token::Kind kind, | 532 Token::Kind kind, |
533 BranchInstr* branch, | 533 BranchInstr* branch, |
534 intptr_t cid, | 534 intptr_t deopt_id, |
535 intptr_t token_pos, | 535 intptr_t token_pos, |
536 intptr_t try_index) { | 536 intptr_t try_index) { |
537 Register left = locs.in(0).reg(); | 537 Register left = locs.in(0).reg(); |
538 Register right = locs.in(1).reg(); | 538 Register right = locs.in(1).reg(); |
539 Register temp = locs.temp(0).reg(); | 539 Register temp = locs.temp(0).reg(); |
540 Label* deopt = compiler->AddDeoptStub(cid, | 540 Label* deopt = compiler->AddDeoptStub(deopt_id, |
541 token_pos, | 541 token_pos, |
542 try_index, | 542 try_index, |
543 kDeoptSmiCompareSmi, | 543 kDeoptSmiCompareSmi, |
544 left, | 544 left, |
545 right); | 545 right); |
546 __ movq(temp, left); | 546 __ movq(temp, left); |
547 __ orq(temp, right); | 547 __ orq(temp, right); |
548 __ testq(temp, Immediate(kSmiTagMask)); | 548 __ testq(temp, Immediate(kSmiTagMask)); |
549 __ j(NOT_ZERO, deopt); | 549 __ j(NOT_ZERO, deopt); |
550 | 550 |
(...skipping 27 matching lines...) Expand all Loading... |
578 UNREACHABLE(); | 578 UNREACHABLE(); |
579 return OVERFLOW; | 579 return OVERFLOW; |
580 } | 580 } |
581 } | 581 } |
582 | 582 |
583 | 583 |
584 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 584 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
585 const LocationSummary& locs, | 585 const LocationSummary& locs, |
586 Token::Kind kind, | 586 Token::Kind kind, |
587 BranchInstr* branch, | 587 BranchInstr* branch, |
588 intptr_t cid, | 588 intptr_t deopt_id, |
589 intptr_t token_pos, | 589 intptr_t token_pos, |
590 intptr_t try_index) { | 590 intptr_t try_index) { |
591 Register left = locs.in(0).reg(); | 591 Register left = locs.in(0).reg(); |
592 Register right = locs.in(1).reg(); | 592 Register right = locs.in(1).reg(); |
593 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 593 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
594 Register temp = locs.temp(0).reg(); | 594 Register temp = locs.temp(0).reg(); |
595 Label* deopt = compiler->AddDeoptStub(cid, | 595 Label* deopt = compiler->AddDeoptStub(deopt_id, |
596 token_pos, | 596 token_pos, |
597 try_index, | 597 try_index, |
598 kDeoptDoubleComparison, | 598 kDeoptDoubleComparison, |
599 left, | 599 left, |
600 right); | 600 right); |
601 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 601 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
602 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 602 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
603 | 603 |
604 Condition true_condition = TokenKindToDoubleCondition(kind); | 604 Condition true_condition = TokenKindToDoubleCondition(kind); |
605 if (branch != NULL) { | 605 if (branch != NULL) { |
606 compiler->EmitDoubleCompareBranch( | 606 compiler->EmitDoubleCompareBranch( |
607 true_condition, XMM0, XMM1, branch); | 607 true_condition, XMM0, XMM1, branch); |
608 } else { | 608 } else { |
609 compiler->EmitDoubleCompareBool( | 609 compiler->EmitDoubleCompareBool( |
610 true_condition, XMM0, XMM1, locs.out().reg()); | 610 true_condition, XMM0, XMM1, locs.out().reg()); |
611 } | 611 } |
612 } | 612 } |
613 | 613 |
614 | 614 |
615 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 615 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
616 if (operands_class_id() == kSmi) { | 616 if (operands_class_id() == kSmi) { |
617 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, | 617 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, |
618 cid(), token_pos(), try_index()); | 618 deopt_id(), token_pos(), try_index()); |
619 return; | 619 return; |
620 } | 620 } |
621 if (operands_class_id() == kDouble) { | 621 if (operands_class_id() == kDouble) { |
622 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 622 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, |
623 cid(), token_pos(), try_index()); | 623 deopt_id(), token_pos(), try_index()); |
624 return; | 624 return; |
625 } | 625 } |
626 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 626 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
627 Label* deopt = compiler->AddDeoptStub(cid(), | 627 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
628 token_pos(), | 628 token_pos(), |
629 try_index(), | 629 try_index(), |
630 kDeoptRelationalOp); | 630 kDeoptRelationalOp); |
631 // Load receiver into RAX, class into RDI. | 631 // Load receiver into RAX, class into RDI. |
632 Label done; | 632 Label done; |
633 const intptr_t kNumArguments = 2; | 633 const intptr_t kNumArguments = 2; |
634 __ movq(RDI, Immediate(kSmi)); | 634 __ movq(RDI, Immediate(kSmi)); |
635 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 635 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
636 __ testq(RAX, Immediate(kSmiTagMask)); | 636 __ testq(RAX, Immediate(kSmiTagMask)); |
637 __ j(ZERO, &done); | 637 __ j(ZERO, &done); |
638 __ LoadClassId(RDI, RAX); | 638 __ LoadClassId(RDI, RAX); |
639 __ Bind(&done); | 639 __ Bind(&done); |
640 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 640 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
641 RDI, // Class id register. | 641 RDI, // Class id register. |
642 kNumArguments, | 642 kNumArguments, |
643 Array::Handle(), // No named arguments. | 643 Array::Handle(), // No named arguments. |
644 deopt, // Deoptimize target. | 644 deopt, // Deoptimize target. |
645 NULL, // Fallthrough when done. | 645 NULL, // Fallthrough when done. |
646 cid(), | 646 deopt_id(), |
647 token_pos(), | 647 token_pos(), |
648 try_index()); | 648 try_index()); |
649 return; | 649 return; |
650 } | 650 } |
651 const String& function_name = | 651 const String& function_name = |
652 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 652 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
653 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 653 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
654 cid(), | 654 deopt_id(), |
655 token_pos(), | 655 token_pos(), |
656 try_index()); | 656 try_index()); |
657 const intptr_t kNumArguments = 2; | 657 const intptr_t kNumArguments = 2; |
658 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 658 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
659 compiler->GenerateInstanceCall(cid(), | 659 compiler->GenerateInstanceCall(deopt_id(), |
660 token_pos(), | 660 token_pos(), |
661 try_index(), | 661 try_index(), |
662 function_name, | 662 function_name, |
663 kNumArguments, | 663 kNumArguments, |
664 Array::ZoneHandle(), // No optional arguments. | 664 Array::ZoneHandle(), // No optional arguments. |
665 kNumArgsChecked); | 665 kNumArgsChecked); |
666 ASSERT(locs()->out().reg() == RAX); | 666 ASSERT(locs()->out().reg() == RAX); |
667 } | 667 } |
668 | 668 |
669 | 669 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 LocationSummary::kNoCall); | 727 LocationSummary::kNoCall); |
728 } else { | 728 } else { |
729 ASSERT(receiver_type() == kIllegalObjectKind); | 729 ASSERT(receiver_type() == kIllegalObjectKind); |
730 return MakeCallSummary(); | 730 return MakeCallSummary(); |
731 } | 731 } |
732 } | 732 } |
733 | 733 |
734 | 734 |
735 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 735 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
736 LoadIndexedComp* comp) { | 736 LoadIndexedComp* comp) { |
737 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 737 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
738 comp->token_pos(), | 738 comp->token_pos(), |
739 comp->try_index(), | 739 comp->try_index(), |
740 kDeoptLoadIndexedPolymorphic); | 740 kDeoptLoadIndexedPolymorphic); |
741 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 741 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
742 ASSERT(comp->HasICData()); | 742 ASSERT(comp->HasICData()); |
743 const ICData& ic_data = *comp->ic_data(); | 743 const ICData& ic_data = *comp->ic_data(); |
744 ASSERT(ic_data.num_args_tested() == 1); | 744 ASSERT(ic_data.num_args_tested() == 1); |
745 // No indexed access on Smi. | 745 // No indexed access on Smi. |
746 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 746 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
747 // Load receiver into RAX. | 747 // Load receiver into RAX. |
748 const intptr_t kNumArguments = 2; | 748 const intptr_t kNumArguments = 2; |
749 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 749 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
750 __ testq(RAX, Immediate(kSmiTagMask)); | 750 __ testq(RAX, Immediate(kSmiTagMask)); |
751 __ j(ZERO, deopt); | 751 __ j(ZERO, deopt); |
752 __ LoadClassId(RDI, RAX); | 752 __ LoadClassId(RDI, RAX); |
753 compiler->EmitTestAndCall(ic_data, | 753 compiler->EmitTestAndCall(ic_data, |
754 RDI, // Class id register. | 754 RDI, // Class id register. |
755 kNumArguments, | 755 kNumArguments, |
756 Array::Handle(), // No named arguments. | 756 Array::Handle(), // No named arguments. |
757 deopt, // Deoptimize target. | 757 deopt, // Deoptimize target. |
758 NULL, // Fallthrough when done. | 758 NULL, // Fallthrough when done. |
759 comp->cid(), | 759 comp->deopt_id(), |
760 comp->token_pos(), | 760 comp->token_pos(), |
761 comp->try_index()); | 761 comp->try_index()); |
762 } | 762 } |
763 | 763 |
764 | 764 |
765 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 765 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
766 if (receiver_type() == kIllegalObjectKind) { | 766 if (receiver_type() == kIllegalObjectKind) { |
767 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 767 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
768 EmitLoadIndexedPolymorphic(compiler, this); | 768 EmitLoadIndexedPolymorphic(compiler, this); |
769 } else { | 769 } else { |
770 compiler->EmitLoadIndexedGeneric(this); | 770 compiler->EmitLoadIndexedGeneric(this); |
771 } | 771 } |
772 ASSERT(locs()->out().reg() == RAX); | 772 ASSERT(locs()->out().reg() == RAX); |
773 return; | 773 return; |
774 } | 774 } |
775 | 775 |
776 Register receiver = locs()->in(0).reg(); | 776 Register receiver = locs()->in(0).reg(); |
777 Register index = locs()->in(1).reg(); | 777 Register index = locs()->in(1).reg(); |
778 Register result = locs()->out().reg(); | 778 Register result = locs()->out().reg(); |
779 | 779 |
780 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 780 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
781 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 781 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
782 | 782 |
783 Label* deopt = compiler->AddDeoptStub(cid(), | 783 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
784 token_pos(), | 784 token_pos(), |
785 try_index(), | 785 try_index(), |
786 deopt_reason, | 786 deopt_reason, |
787 receiver, | 787 receiver, |
788 index); | 788 index); |
789 | 789 |
790 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 790 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
791 __ j(ZERO, deopt); | 791 __ j(ZERO, deopt); |
792 __ CompareClassId(receiver, receiver_type()); | 792 __ CompareClassId(receiver, receiver_type()); |
793 __ j(NOT_EQUAL, deopt); | 793 __ j(NOT_EQUAL, deopt); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 } | 847 } |
848 } | 848 } |
849 | 849 |
850 | 850 |
851 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 851 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
852 StoreIndexedComp* comp) { | 852 StoreIndexedComp* comp) { |
853 const String& function_name = | 853 const String& function_name = |
854 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); | 854 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
855 | 855 |
856 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 856 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
857 comp->cid(), | 857 comp->deopt_id(), |
858 comp->token_pos(), | 858 comp->token_pos(), |
859 comp->try_index()); | 859 comp->try_index()); |
860 | 860 |
861 const intptr_t kNumArguments = 3; | 861 const intptr_t kNumArguments = 3; |
862 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 862 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
863 compiler->GenerateInstanceCall(comp->cid(), | 863 compiler->GenerateInstanceCall(comp->deopt_id(), |
864 comp->token_pos(), | 864 comp->token_pos(), |
865 comp->try_index(), | 865 comp->try_index(), |
866 function_name, | 866 function_name, |
867 kNumArguments, | 867 kNumArguments, |
868 Array::ZoneHandle(), // No named arguments. | 868 Array::ZoneHandle(), // No named arguments. |
869 kNumArgsChecked); | 869 kNumArgsChecked); |
870 } | 870 } |
871 | 871 |
872 | 872 |
873 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 873 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
874 StoreIndexedComp* comp) { | 874 StoreIndexedComp* comp) { |
875 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 875 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
876 comp->token_pos(), | 876 comp->token_pos(), |
877 comp->try_index(), | 877 comp->try_index(), |
878 kDeoptStoreIndexedPolymorphic); | 878 kDeoptStoreIndexedPolymorphic); |
879 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 879 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
880 ASSERT(comp->HasICData()); | 880 ASSERT(comp->HasICData()); |
881 const ICData& ic_data = *comp->ic_data(); | 881 const ICData& ic_data = *comp->ic_data(); |
882 ASSERT(ic_data.num_args_tested() == 1); | 882 ASSERT(ic_data.num_args_tested() == 1); |
883 // No indexed access on Smi. | 883 // No indexed access on Smi. |
884 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 884 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
885 // Load receiver into RAX. | 885 // Load receiver into RAX. |
886 const intptr_t kNumArguments = 3; | 886 const intptr_t kNumArguments = 3; |
887 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 887 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
888 __ testq(RAX, Immediate(kSmiTagMask)); | 888 __ testq(RAX, Immediate(kSmiTagMask)); |
889 __ j(ZERO, deopt); | 889 __ j(ZERO, deopt); |
890 __ LoadClassId(RDI, RAX); | 890 __ LoadClassId(RDI, RAX); |
891 compiler->EmitTestAndCall(ic_data, | 891 compiler->EmitTestAndCall(ic_data, |
892 RDI, // Class id register. | 892 RDI, // Class id register. |
893 kNumArguments, | 893 kNumArguments, |
894 Array::Handle(), // No named arguments. | 894 Array::Handle(), // No named arguments. |
895 deopt, // deoptimize label. | 895 deopt, // deoptimize label. |
896 NULL, // fallthrough when done. | 896 NULL, // fallthrough when done. |
897 comp->cid(), | 897 comp->deopt_id(), |
898 comp->token_pos(), | 898 comp->token_pos(), |
899 comp->try_index()); | 899 comp->try_index()); |
900 } | 900 } |
901 | 901 |
902 | 902 |
903 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 903 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
904 if (receiver_type() == kIllegalObjectKind) { | 904 if (receiver_type() == kIllegalObjectKind) { |
905 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 905 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
906 EmitStoreIndexedPolymorphic(compiler, this); | 906 EmitStoreIndexedPolymorphic(compiler, this); |
907 } else { | 907 } else { |
908 EmitStoreIndexedGeneric(compiler, this); | 908 EmitStoreIndexedGeneric(compiler, this); |
909 } | 909 } |
910 return; | 910 return; |
911 } | 911 } |
912 | 912 |
913 Register receiver = locs()->in(0).reg(); | 913 Register receiver = locs()->in(0).reg(); |
914 Register index = locs()->in(1).reg(); | 914 Register index = locs()->in(1).reg(); |
915 Register value = locs()->in(2).reg(); | 915 Register value = locs()->in(2).reg(); |
916 | 916 |
917 Label* deopt = compiler->AddDeoptStub(cid(), | 917 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
918 token_pos(), | 918 token_pos(), |
919 try_index(), | 919 try_index(), |
920 kDeoptStoreIndexed, | 920 kDeoptStoreIndexed, |
921 receiver, | 921 receiver, |
922 index, | 922 index, |
923 value); | 923 value); |
924 | 924 |
925 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 925 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
926 __ j(ZERO, deopt); | 926 __ j(ZERO, deopt); |
927 __ CompareClassId(receiver, receiver_type()); | 927 __ CompareClassId(receiver, receiver_type()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 | 964 |
965 | 965 |
966 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { | 966 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { |
967 return MakeCallSummary(); | 967 return MakeCallSummary(); |
968 } | 968 } |
969 | 969 |
970 | 970 |
971 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 971 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
972 Label* deopt = NULL; | 972 Label* deopt = NULL; |
973 if (compiler->is_optimizing()) { | 973 if (compiler->is_optimizing()) { |
974 deopt = compiler->AddDeoptStub(cid(), | 974 deopt = compiler->AddDeoptStub(deopt_id(), |
975 token_pos(), | 975 token_pos(), |
976 try_index(), | 976 try_index(), |
977 kDeoptInstanceSetter); | 977 kDeoptInstanceSetter); |
978 } | 978 } |
979 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 979 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
980 // No index-setter on Smi's. | 980 // No index-setter on Smi's. |
981 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi); | 981 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi); |
982 // Load receiver into RAX. | 982 // Load receiver into RAX. |
983 const intptr_t kNumArguments = 2; | 983 const intptr_t kNumArguments = 2; |
984 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 984 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
985 __ testq(RAX, Immediate(kSmiTagMask)); | 985 __ testq(RAX, Immediate(kSmiTagMask)); |
986 __ j(ZERO, deopt); | 986 __ j(ZERO, deopt); |
987 __ LoadClassId(RDI, RAX); | 987 __ LoadClassId(RDI, RAX); |
988 compiler->EmitTestAndCall(*ic_data(), | 988 compiler->EmitTestAndCall(*ic_data(), |
989 RDI, // Class id register. | 989 RDI, // Class id register. |
990 kNumArguments, | 990 kNumArguments, |
991 Array::Handle(), // No named arguments. | 991 Array::Handle(), // No named arguments. |
992 deopt, // Deoptimize target. | 992 deopt, // Deoptimize target. |
993 NULL, // Fallthrough when done. | 993 NULL, // Fallthrough when done. |
994 cid(), | 994 deopt_id(), |
995 token_pos(), | 995 token_pos(), |
996 try_index()); | 996 try_index()); |
997 | 997 |
998 } else if (compiler->is_optimizing()) { | 998 } else if (compiler->is_optimizing()) { |
999 // Get some IC data then optimize again. | 999 // Get some IC data then optimize again. |
1000 __ jmp(deopt); | 1000 __ jmp(deopt); |
1001 } else { | 1001 } else { |
1002 // Unoptimized code. | 1002 // Unoptimized code. |
1003 const String& function_name = | 1003 const String& function_name = |
1004 String::ZoneHandle(Field::SetterSymbol(field_name())); | 1004 String::ZoneHandle(Field::SetterSymbol(field_name())); |
1005 | 1005 |
1006 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 1006 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
1007 cid(), | 1007 deopt_id(), |
1008 token_pos(), | 1008 token_pos(), |
1009 try_index()); | 1009 try_index()); |
1010 const intptr_t kArgumentCount = 2; | 1010 const intptr_t kArgumentCount = 2; |
1011 const intptr_t kCheckedArgumentCount = 1; | 1011 const intptr_t kCheckedArgumentCount = 1; |
1012 compiler->GenerateInstanceCall(cid(), | 1012 compiler->GenerateInstanceCall(deopt_id(), |
1013 token_pos(), | 1013 token_pos(), |
1014 try_index(), | 1014 try_index(), |
1015 function_name, | 1015 function_name, |
1016 kArgumentCount, | 1016 kArgumentCount, |
1017 Array::ZoneHandle(), | 1017 Array::ZoneHandle(), |
1018 kCheckedArgumentCount); | 1018 kCheckedArgumentCount); |
1019 } | 1019 } |
1020 } | 1020 } |
1021 | 1021 |
1022 | 1022 |
1023 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 1023 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { |
1024 // TODO(fschneider): For this instruction the input register may be | 1024 // TODO(fschneider): For this instruction the input register may be |
1025 // reused for the result (but is not required to) because the input | 1025 // reused for the result (but is not required to) because the input |
1026 // is not used after the result is defined. We should consider adding | 1026 // is not used after the result is defined. We should consider adding |
1027 // this information to the input policy. | 1027 // this information to the input policy. |
1028 return LocationSummary::Make(1, | 1028 return LocationSummary::Make(1, |
1029 Location::RequiresRegister(), | 1029 Location::RequiresRegister(), |
1030 LocationSummary::kNoCall); | 1030 LocationSummary::kNoCall); |
1031 } | 1031 } |
1032 | 1032 |
1033 | 1033 |
1034 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1034 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1035 Register instance_reg = locs()->in(0).reg(); | 1035 Register instance_reg = locs()->in(0).reg(); |
1036 Register result_reg = locs()->out().reg(); | 1036 Register result_reg = locs()->out().reg(); |
1037 | 1037 |
1038 if (HasICData()) { | 1038 if (HasICData()) { |
1039 ASSERT(original() != NULL); | 1039 ASSERT(original() != NULL); |
1040 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1040 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
1041 original()->token_pos(), | 1041 original()->token_pos(), |
1042 original()->try_index(), | 1042 original()->try_index(), |
1043 kDeoptInstanceGetterSameTarget, | 1043 kDeoptInstanceGetterSameTarget, |
1044 instance_reg); | 1044 instance_reg); |
1045 // Smis do not have instance fields (Smi class is always first). | 1045 // Smis do not have instance fields (Smi class is always first). |
1046 // Use 'result' as temporary register. | 1046 // Use 'result' as temporary register. |
1047 ASSERT(result_reg != instance_reg); | 1047 ASSERT(result_reg != instance_reg); |
1048 ASSERT(ic_data() != NULL); | 1048 ASSERT(ic_data() != NULL); |
1049 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1049 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
1050 } | 1050 } |
(...skipping 26 matching lines...) Expand all Loading... |
1077 summary->set_out(Location::RegisterLocation(RAX)); | 1077 summary->set_out(Location::RegisterLocation(RAX)); |
1078 return summary; | 1078 return summary; |
1079 } | 1079 } |
1080 | 1080 |
1081 | 1081 |
1082 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1082 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1083 ASSERT(locs()->in(0).reg() == RAX); // Value. | 1083 ASSERT(locs()->in(0).reg() == RAX); // Value. |
1084 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. | 1084 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. |
1085 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. | 1085 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. |
1086 | 1086 |
1087 compiler->GenerateInstanceOf(cid(), | 1087 compiler->GenerateInstanceOf(deopt_id(), |
1088 token_pos(), | 1088 token_pos(), |
1089 try_index(), | 1089 try_index(), |
1090 type(), | 1090 type(), |
1091 negate_result()); | 1091 negate_result()); |
1092 ASSERT(locs()->out().reg() == RAX); | 1092 ASSERT(locs()->out().reg() == RAX); |
1093 } | 1093 } |
1094 | 1094 |
1095 | 1095 |
1096 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1096 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
1097 // TODO(regis): The elements of the array could be considered as arguments to | 1097 // TODO(regis): The elements of the array could be considered as arguments to |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1150 const Class& cls = Class::ZoneHandle(constructor().owner()); |
1151 Register type_arguments = locs()->in(0).reg(); | 1151 Register type_arguments = locs()->in(0).reg(); |
1152 Register instantiator_type_arguments = locs()->in(1).reg(); | 1152 Register instantiator_type_arguments = locs()->in(1).reg(); |
1153 Register result = locs()->out().reg(); | 1153 Register result = locs()->out().reg(); |
1154 | 1154 |
1155 // Push the result place holder initialized to NULL. | 1155 // Push the result place holder initialized to NULL. |
1156 __ PushObject(Object::ZoneHandle()); | 1156 __ PushObject(Object::ZoneHandle()); |
1157 __ PushObject(cls); | 1157 __ PushObject(cls); |
1158 __ pushq(type_arguments); | 1158 __ pushq(type_arguments); |
1159 __ pushq(instantiator_type_arguments); | 1159 __ pushq(instantiator_type_arguments); |
1160 compiler->GenerateCallRuntime(cid(), | 1160 compiler->GenerateCallRuntime(deopt_id(), |
1161 token_pos(), | 1161 token_pos(), |
1162 try_index(), | 1162 try_index(), |
1163 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1163 kAllocateObjectWithBoundsCheckRuntimeEntry); |
1164 // Pop instantiator type arguments, type arguments, and class. | 1164 // Pop instantiator type arguments, type arguments, and class. |
1165 __ Drop(3); | 1165 __ Drop(3); |
1166 __ popq(result); // Pop new instance. | 1166 __ popq(result); // Pop new instance. |
1167 } | 1167 } |
1168 | 1168 |
1169 | 1169 |
1170 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1170 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
1171 return LocationSummary::Make(1, | 1171 return LocationSummary::Make(1, |
1172 Location::RequiresRegister(), | 1172 Location::RequiresRegister(), |
1173 LocationSummary::kNoCall); | 1173 LocationSummary::kNoCall); |
1174 } | 1174 } |
1175 | 1175 |
1176 | 1176 |
1177 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1177 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1178 Register instance_reg = locs()->in(0).reg(); | 1178 Register instance_reg = locs()->in(0).reg(); |
1179 Register result_reg = locs()->out().reg(); | 1179 Register result_reg = locs()->out().reg(); |
1180 if (HasICData()) { | 1180 if (HasICData()) { |
1181 ASSERT(original() != NULL); | 1181 ASSERT(original() != NULL); |
1182 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1182 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
1183 original()->token_pos(), | 1183 original()->token_pos(), |
1184 original()->try_index(), | 1184 original()->try_index(), |
1185 kDeoptInstanceGetterSameTarget, | 1185 kDeoptInstanceGetterSameTarget, |
1186 instance_reg); | 1186 instance_reg); |
1187 // Smis do not have instance fields (Smi class is always first). | 1187 // Smis do not have instance fields (Smi class is always first). |
1188 // Use 'result' as temporary register. | 1188 // Use 'result' as temporary register. |
1189 ASSERT(result_reg != instance_reg); | 1189 ASSERT(result_reg != instance_reg); |
1190 ASSERT(ic_data() != NULL); | 1190 ASSERT(ic_data() != NULL); |
1191 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1191 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
1192 } | 1192 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1236 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1237 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1237 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1238 Immediate(Smi::RawValue(len))); | 1238 Immediate(Smi::RawValue(len))); |
1239 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1239 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1240 __ Bind(&type_arguments_uninstantiated); | 1240 __ Bind(&type_arguments_uninstantiated); |
1241 } | 1241 } |
1242 // A runtime call to instantiate the type arguments is required. | 1242 // A runtime call to instantiate the type arguments is required. |
1243 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1243 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1244 __ PushObject(type_arguments()); | 1244 __ PushObject(type_arguments()); |
1245 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1245 __ pushq(instantiator_reg); // Push instantiator type arguments. |
1246 compiler->GenerateCallRuntime(cid(), | 1246 compiler->GenerateCallRuntime(deopt_id(), |
1247 token_pos(), | 1247 token_pos(), |
1248 try_index(), | 1248 try_index(), |
1249 kInstantiateTypeArgumentsRuntimeEntry); | 1249 kInstantiateTypeArgumentsRuntimeEntry); |
1250 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1250 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
1251 __ popq(result_reg); // Pop instantiated type arguments. | 1251 __ popq(result_reg); // Pop instantiated type arguments. |
1252 __ Bind(&type_arguments_instantiated); | 1252 __ Bind(&type_arguments_instantiated); |
1253 ASSERT(instantiator_reg == result_reg); | 1253 ASSERT(instantiator_reg == result_reg); |
1254 // 'result_reg': Instantiated type arguments. | 1254 // 'result_reg': Instantiated type arguments. |
1255 } | 1255 } |
1256 | 1256 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 return locs; | 1412 return locs; |
1413 } | 1413 } |
1414 | 1414 |
1415 | 1415 |
1416 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1416 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1417 Register context_value = locs()->in(0).reg(); | 1417 Register context_value = locs()->in(0).reg(); |
1418 Register result = locs()->out().reg(); | 1418 Register result = locs()->out().reg(); |
1419 | 1419 |
1420 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1420 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1421 __ pushq(context_value); | 1421 __ pushq(context_value); |
1422 compiler->GenerateCallRuntime(cid(), | 1422 compiler->GenerateCallRuntime(deopt_id(), |
1423 token_pos(), | 1423 token_pos(), |
1424 try_index(), | 1424 try_index(), |
1425 kCloneContextRuntimeEntry); | 1425 kCloneContextRuntimeEntry); |
1426 __ popq(result); // Remove argument. | 1426 __ popq(result); // Remove argument. |
1427 __ popq(result); // Get result (cloned context). | 1427 __ popq(result); // Get result (cloned context). |
1428 } | 1428 } |
1429 | 1429 |
1430 | 1430 |
1431 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1431 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
1432 return LocationSummary::Make(0, | 1432 return LocationSummary::Make(0, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1468 } | 1468 } |
1469 | 1469 |
1470 | 1470 |
1471 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1471 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1472 Register temp = locs()->temp(0).reg(); | 1472 Register temp = locs()->temp(0).reg(); |
1473 // Generate stack overflow check. | 1473 // Generate stack overflow check. |
1474 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1474 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
1475 __ cmpq(RSP, Address(temp, 0)); | 1475 __ cmpq(RSP, Address(temp, 0)); |
1476 Label no_stack_overflow; | 1476 Label no_stack_overflow; |
1477 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1477 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
1478 compiler->GenerateCallRuntime(cid(), | 1478 compiler->GenerateCallRuntime(deopt_id(), |
1479 token_pos(), | 1479 token_pos(), |
1480 try_index(), | 1480 try_index(), |
1481 kStackOverflowRuntimeEntry); | 1481 kStackOverflowRuntimeEntry); |
1482 __ Bind(&no_stack_overflow); | 1482 __ Bind(&no_stack_overflow); |
1483 } | 1483 } |
1484 | 1484 |
1485 | 1485 |
1486 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1486 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
1487 const intptr_t kNumInputs = 2; | 1487 const intptr_t kNumInputs = 2; |
1488 | 1488 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 } | 1546 } |
1547 } | 1547 } |
1548 | 1548 |
1549 | 1549 |
1550 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1550 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
1551 Register left = comp->locs()->in(0).reg(); | 1551 Register left = comp->locs()->in(0).reg(); |
1552 Register right = comp->locs()->in(1).reg(); | 1552 Register right = comp->locs()->in(1).reg(); |
1553 Register result = comp->locs()->out().reg(); | 1553 Register result = comp->locs()->out().reg(); |
1554 Register temp = comp->locs()->temp(0).reg(); | 1554 Register temp = comp->locs()->temp(0).reg(); |
1555 ASSERT(left == result); | 1555 ASSERT(left == result); |
1556 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1556 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
1557 comp->instance_call()->token_pos(), | 1557 comp->instance_call()->token_pos(), |
1558 comp->instance_call()->try_index(), | 1558 comp->instance_call()->try_index(), |
1559 kDeoptSmiBinaryOp, | 1559 kDeoptSmiBinaryOp, |
1560 temp, | 1560 temp, |
1561 right); | 1561 right); |
1562 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1562 // TODO(vegorov): for many binary operations this pattern can be rearranged |
1563 // to save one move. | 1563 // to save one move. |
1564 __ movq(temp, left); | 1564 __ movq(temp, left); |
1565 __ orq(left, right); | 1565 __ orq(left, right); |
1566 __ testq(left, Immediate(kSmiTagMask)); | 1566 __ testq(left, Immediate(kSmiTagMask)); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1657 __ shlq(left, right_temp); | 1657 __ shlq(left, right_temp); |
1658 __ jmp(&done); | 1658 __ jmp(&done); |
1659 { | 1659 { |
1660 __ Bind(&call_method); | 1660 __ Bind(&call_method); |
1661 Function& target = Function::ZoneHandle( | 1661 Function& target = Function::ZoneHandle( |
1662 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1662 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1663 ASSERT(!target.IsNull()); | 1663 ASSERT(!target.IsNull()); |
1664 const intptr_t kArgumentCount = 2; | 1664 const intptr_t kArgumentCount = 2; |
1665 __ pushq(temp); | 1665 __ pushq(temp); |
1666 __ pushq(right); | 1666 __ pushq(right); |
1667 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1667 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1668 comp->instance_call()->token_pos(), | 1668 comp->instance_call()->token_pos(), |
1669 comp->instance_call()->try_index(), | 1669 comp->instance_call()->try_index(), |
1670 target, | 1670 target, |
1671 kArgumentCount, | 1671 kArgumentCount, |
1672 Array::Handle()); // No argument names. | 1672 Array::Handle()); // No argument names. |
1673 ASSERT(result == RAX); | 1673 ASSERT(result == RAX); |
1674 } | 1674 } |
1675 __ Bind(&done); | 1675 __ Bind(&done); |
1676 break; | 1676 break; |
1677 } | 1677 } |
(...skipping 25 matching lines...) Expand all Loading... |
1703 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1703 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
1704 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1704 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
1705 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1705 // receiver and a Mint or Smi argument. We fall back to the run time call if |
1706 // both receiver and argument are Mint or if one of them is Mint and the other | 1706 // both receiver and argument are Mint or if one of them is Mint and the other |
1707 // is a negative Smi. | 1707 // is a negative Smi. |
1708 Register left = comp->locs()->in(0).reg(); | 1708 Register left = comp->locs()->in(0).reg(); |
1709 Register right = comp->locs()->in(1).reg(); | 1709 Register right = comp->locs()->in(1).reg(); |
1710 Register result = comp->locs()->out().reg(); | 1710 Register result = comp->locs()->out().reg(); |
1711 ASSERT(left == result); | 1711 ASSERT(left == result); |
1712 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1712 ASSERT(comp->op_kind() == Token::kBIT_AND); |
1713 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1713 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
1714 comp->instance_call()->token_pos(), | 1714 comp->instance_call()->token_pos(), |
1715 comp->instance_call()->try_index(), | 1715 comp->instance_call()->try_index(), |
1716 kDeoptMintBinaryOp, | 1716 kDeoptMintBinaryOp, |
1717 left, | 1717 left, |
1718 right); | 1718 right); |
1719 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1719 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
1720 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1720 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
1721 __ j(NOT_ZERO, &non_smi); | 1721 __ j(NOT_ZERO, &non_smi); |
1722 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1722 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1723 __ j(ZERO, &smi_smi); | 1723 __ j(ZERO, &smi_smi); |
(...skipping 27 matching lines...) Expand all Loading... |
1751 | 1751 |
1752 __ Bind(&smi_static_call); | 1752 __ Bind(&smi_static_call); |
1753 { | 1753 { |
1754 Function& target = Function::ZoneHandle( | 1754 Function& target = Function::ZoneHandle( |
1755 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1755 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1756 if (target.IsNull()) { | 1756 if (target.IsNull()) { |
1757 __ jmp(deopt); | 1757 __ jmp(deopt); |
1758 } else { | 1758 } else { |
1759 __ pushq(left); | 1759 __ pushq(left); |
1760 __ pushq(right); | 1760 __ pushq(right); |
1761 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1761 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1762 comp->instance_call()->token_pos(), | 1762 comp->instance_call()->token_pos(), |
1763 comp->instance_call()->try_index(), | 1763 comp->instance_call()->try_index(), |
1764 target, | 1764 target, |
1765 comp->instance_call()->ArgumentCount(), | 1765 comp->instance_call()->ArgumentCount(), |
1766 comp->instance_call()->argument_names()); | 1766 comp->instance_call()->argument_names()); |
1767 ASSERT(result == RAX); | 1767 ASSERT(result == RAX); |
1768 __ jmp(&done); | 1768 __ jmp(&done); |
1769 } | 1769 } |
1770 } | 1770 } |
1771 | 1771 |
1772 __ Bind(&mint_static_call); | 1772 __ Bind(&mint_static_call); |
1773 { | 1773 { |
1774 Function& target = Function::ZoneHandle( | 1774 Function& target = Function::ZoneHandle( |
1775 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1775 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
1776 if (target.IsNull()) { | 1776 if (target.IsNull()) { |
1777 __ jmp(deopt); | 1777 __ jmp(deopt); |
1778 } else { | 1778 } else { |
1779 __ pushq(left); | 1779 __ pushq(left); |
1780 __ pushq(right); | 1780 __ pushq(right); |
1781 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1781 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1782 comp->instance_call()->token_pos(), | 1782 comp->instance_call()->token_pos(), |
1783 comp->instance_call()->try_index(), | 1783 comp->instance_call()->try_index(), |
1784 target, | 1784 target, |
1785 comp->instance_call()->ArgumentCount(), | 1785 comp->instance_call()->ArgumentCount(), |
1786 comp->instance_call()->argument_names()); | 1786 comp->instance_call()->argument_names()); |
1787 ASSERT(result == RAX); | 1787 ASSERT(result == RAX); |
1788 } | 1788 } |
1789 } | 1789 } |
1790 __ Bind(&done); | 1790 __ Bind(&done); |
1791 } | 1791 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1824 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1824 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1825 compiler->GenerateCall(instance_call()->token_pos(), | 1825 compiler->GenerateCall(instance_call()->token_pos(), |
1826 instance_call()->try_index(), | 1826 instance_call()->try_index(), |
1827 &label, | 1827 &label, |
1828 PcDescriptors::kOther); | 1828 PcDescriptors::kOther); |
1829 // Newly allocated object is now in the result register (RAX). | 1829 // Newly allocated object is now in the result register (RAX). |
1830 ASSERT(result == RAX); | 1830 ASSERT(result == RAX); |
1831 __ popq(right); | 1831 __ popq(right); |
1832 __ popq(left); | 1832 __ popq(left); |
1833 | 1833 |
1834 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1834 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1835 instance_call()->token_pos(), | 1835 instance_call()->token_pos(), |
1836 instance_call()->try_index(), | 1836 instance_call()->try_index(), |
1837 kDeoptDoubleBinaryOp, | 1837 kDeoptDoubleBinaryOp, |
1838 left, | 1838 left, |
1839 right); | 1839 right); |
1840 | 1840 |
1841 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1841 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
1842 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1842 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
1843 | 1843 |
1844 switch (op_kind()) { | 1844 switch (op_kind()) { |
(...skipping 25 matching lines...) Expand all Loading... |
1870 ASSERT(ic_data.num_args_tested() == 1); | 1870 ASSERT(ic_data.num_args_tested() == 1); |
1871 // TODO(srdjan): Implement for more checks. | 1871 // TODO(srdjan): Implement for more checks. |
1872 ASSERT(ic_data.NumberOfChecks() == 1); | 1872 ASSERT(ic_data.NumberOfChecks() == 1); |
1873 intptr_t test_class_id; | 1873 intptr_t test_class_id; |
1874 Function& target = Function::Handle(); | 1874 Function& target = Function::Handle(); |
1875 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1875 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1876 | 1876 |
1877 Register value = locs()->in(0).reg(); | 1877 Register value = locs()->in(0).reg(); |
1878 Register result = locs()->out().reg(); | 1878 Register result = locs()->out().reg(); |
1879 ASSERT(value == result); | 1879 ASSERT(value == result); |
1880 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1880 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1881 instance_call()->token_pos(), | 1881 instance_call()->token_pos(), |
1882 instance_call()->try_index(), | 1882 instance_call()->try_index(), |
1883 kDeoptUnaryOp, | 1883 kDeoptUnaryOp, |
1884 value); | 1884 value); |
1885 if (test_class_id == kSmi) { | 1885 if (test_class_id == kSmi) { |
1886 __ testq(value, Immediate(kSmiTagMask)); | 1886 __ testq(value, Immediate(kSmiTagMask)); |
1887 __ j(NOT_ZERO, deopt); | 1887 __ j(NOT_ZERO, deopt); |
1888 switch (op_kind()) { | 1888 switch (op_kind()) { |
1889 case Token::kNEGATE: | 1889 case Token::kNEGATE: |
1890 __ negq(value); | 1890 __ negq(value); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1922 | 1922 |
1923 // TODO(srdjan): Implement for more checks. | 1923 // TODO(srdjan): Implement for more checks. |
1924 ASSERT(ic_data.NumberOfChecks() == 1); | 1924 ASSERT(ic_data.NumberOfChecks() == 1); |
1925 intptr_t test_class_id; | 1925 intptr_t test_class_id; |
1926 Function& target = Function::Handle(); | 1926 Function& target = Function::Handle(); |
1927 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1927 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1928 | 1928 |
1929 Register value = locs()->in(0).reg(); | 1929 Register value = locs()->in(0).reg(); |
1930 Register result = locs()->out().reg(); | 1930 Register result = locs()->out().reg(); |
1931 ASSERT(value == result); | 1931 ASSERT(value == result); |
1932 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1932 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1933 instance_call()->token_pos(), | 1933 instance_call()->token_pos(), |
1934 instance_call()->try_index(), | 1934 instance_call()->try_index(), |
1935 kDeoptUnaryOp, | 1935 kDeoptUnaryOp, |
1936 value); | 1936 value); |
1937 if (test_class_id == kDouble) { | 1937 if (test_class_id == kDouble) { |
1938 Register temp = locs()->temp(0).reg(); | 1938 Register temp = locs()->temp(0).reg(); |
1939 __ testq(value, Immediate(kSmiTagMask)); | 1939 __ testq(value, Immediate(kSmiTagMask)); |
1940 __ j(ZERO, deopt); // Smi. | 1940 __ j(ZERO, deopt); // Smi. |
1941 __ CompareClassId(value, kDouble); | 1941 __ CompareClassId(value, kDouble); |
1942 __ j(NOT_EQUAL, deopt); | 1942 __ j(NOT_EQUAL, deopt); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1978 } | 1978 } |
1979 } | 1979 } |
1980 | 1980 |
1981 | 1981 |
1982 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1982 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1983 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 1983 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; |
1984 Register result = locs()->out().reg(); | 1984 Register result = locs()->out().reg(); |
1985 | 1985 |
1986 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1986 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
1987 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1987 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1988 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1988 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1989 instance_call()->token_pos(), | 1989 instance_call()->token_pos(), |
1990 instance_call()->try_index(), | 1990 instance_call()->try_index(), |
1991 deopt_reason, | 1991 deopt_reason, |
1992 value); | 1992 value); |
1993 | 1993 |
1994 if (from() == kDouble) { | 1994 if (from() == kDouble) { |
1995 __ testq(value, Immediate(kSmiTagMask)); | 1995 __ testq(value, Immediate(kSmiTagMask)); |
1996 __ j(ZERO, deopt); // Deoptimize if Smi. | 1996 __ j(ZERO, deopt); // Deoptimize if Smi. |
1997 __ CompareClassId(value, kDouble); | 1997 __ CompareClassId(value, kDouble); |
1998 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1998 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
(...skipping 23 matching lines...) Expand all Loading... |
2022 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 2022 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
2023 } | 2023 } |
2024 | 2024 |
2025 | 2025 |
2026 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 2026 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
2027 return MakeCallSummary(); | 2027 return MakeCallSummary(); |
2028 } | 2028 } |
2029 | 2029 |
2030 | 2030 |
2031 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2031 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
2032 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 2032 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
2033 instance_call()->token_pos(), | 2033 instance_call()->token_pos(), |
2034 instance_call()->try_index(), | 2034 instance_call()->try_index(), |
2035 kDeoptPolymorphicInstanceCallTestFail); | 2035 kDeoptPolymorphicInstanceCallTestFail); |
2036 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 2036 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
2037 __ jmp(deopt); | 2037 __ jmp(deopt); |
2038 return; | 2038 return; |
2039 } | 2039 } |
2040 ASSERT(HasICData()); | 2040 ASSERT(HasICData()); |
2041 ASSERT(ic_data()->num_args_tested() == 1); | 2041 ASSERT(ic_data()->num_args_tested() == 1); |
2042 Label handle_smi; | 2042 Label handle_smi; |
2043 Label* is_smi_label = | 2043 Label* is_smi_label = |
2044 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 2044 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
2045 | 2045 |
2046 // Load receiver into RAX. | 2046 // Load receiver into RAX. |
2047 __ movq(RAX, | 2047 __ movq(RAX, |
2048 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 2048 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
2049 __ testq(RAX, Immediate(kSmiTagMask)); | 2049 __ testq(RAX, Immediate(kSmiTagMask)); |
2050 __ j(ZERO, is_smi_label); | 2050 __ j(ZERO, is_smi_label); |
2051 Label done; | 2051 Label done; |
2052 __ LoadClassId(RDI, RAX); | 2052 __ LoadClassId(RDI, RAX); |
2053 compiler->EmitTestAndCall(*ic_data(), | 2053 compiler->EmitTestAndCall(*ic_data(), |
2054 RDI, // Class id register. | 2054 RDI, // Class id register. |
2055 instance_call()->ArgumentCount(), | 2055 instance_call()->ArgumentCount(), |
2056 instance_call()->argument_names(), | 2056 instance_call()->argument_names(), |
2057 deopt, | 2057 deopt, |
2058 (is_smi_label == &handle_smi) ? &done : NULL, | 2058 (is_smi_label == &handle_smi) ? &done : NULL, |
2059 instance_call()->cid(), | 2059 instance_call()->deopt_id(), |
2060 instance_call()->token_pos(), | 2060 instance_call()->token_pos(), |
2061 instance_call()->try_index()); | 2061 instance_call()->try_index()); |
2062 if (is_smi_label == &handle_smi) { | 2062 if (is_smi_label == &handle_smi) { |
2063 __ Bind(&handle_smi); | 2063 __ Bind(&handle_smi); |
2064 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 2064 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
2065 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 2065 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
2066 compiler->GenerateStaticCall(instance_call()->cid(), | 2066 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
2067 instance_call()->token_pos(), | 2067 instance_call()->token_pos(), |
2068 instance_call()->try_index(), | 2068 instance_call()->try_index(), |
2069 target, | 2069 target, |
2070 instance_call()->ArgumentCount(), | 2070 instance_call()->ArgumentCount(), |
2071 instance_call()->argument_names()); | 2071 instance_call()->argument_names()); |
2072 } | 2072 } |
2073 __ Bind(&done); | 2073 __ Bind(&done); |
2074 } | 2074 } |
2075 | 2075 |
2076 | 2076 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2130 Register right = locs()->in(1).reg(); | 2130 Register right = locs()->in(1).reg(); |
2131 __ cmpq(left, right); | 2131 __ cmpq(left, right); |
2132 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 2132 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
2133 EmitBranchOnCondition(compiler, cond); | 2133 EmitBranchOnCondition(compiler, cond); |
2134 return; | 2134 return; |
2135 } | 2135 } |
2136 // Relational or equality. | 2136 // Relational or equality. |
2137 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2137 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
2138 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { | 2138 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { |
2139 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2139 EmitSmiComparisonOp(compiler, *locs(), kind(), this, |
2140 cid(), token_pos(), try_index()); | 2140 deopt_id(), token_pos(), try_index()); |
2141 return; | 2141 return; |
2142 } | 2142 } |
2143 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2143 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { |
2144 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2144 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, |
2145 cid(), token_pos(), try_index()); | 2145 deopt_id(), token_pos(), try_index()); |
2146 return; | 2146 return; |
2147 } | 2147 } |
2148 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2148 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
2149 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2149 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
2150 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2150 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), |
2151 cid(), token_pos(), try_index()); | 2151 deopt_id(), token_pos(), try_index()); |
2152 return; | 2152 return; |
2153 } | 2153 } |
2154 // Otherwise polymorphic dispatch? | 2154 // Otherwise polymorphic dispatch? |
2155 } | 2155 } |
2156 // Not equal is always split into '==' and negate, | 2156 // Not equal is always split into '==' and negate, |
2157 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 2157 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
2158 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); | 2158 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); |
2159 const String& function_name = | 2159 const String& function_name = |
2160 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); | 2160 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); |
2161 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 2161 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
2162 cid(), | 2162 deopt_id(), |
2163 token_pos(), | 2163 token_pos(), |
2164 try_index()); | 2164 try_index()); |
2165 const intptr_t kNumArguments = 2; | 2165 const intptr_t kNumArguments = 2; |
2166 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 2166 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
2167 compiler->GenerateInstanceCall(cid(), | 2167 compiler->GenerateInstanceCall(deopt_id(), |
2168 token_pos(), | 2168 token_pos(), |
2169 try_index(), | 2169 try_index(), |
2170 function_name, | 2170 function_name, |
2171 kNumArguments, | 2171 kNumArguments, |
2172 Array::ZoneHandle(), // No optional arguments. | 2172 Array::ZoneHandle(), // No optional arguments. |
2173 kNumArgsChecked); | 2173 kNumArgsChecked); |
2174 ASSERT(locs()->out().reg() == RAX); | 2174 ASSERT(locs()->out().reg() == RAX); |
2175 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2175 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
2176 EmitBranchOnCondition(compiler, branch_condition); | 2176 EmitBranchOnCondition(compiler, branch_condition); |
2177 } | 2177 } |
2178 | 2178 |
2179 } // namespace dart | 2179 } // namespace dart |
2180 | 2180 |
2181 #undef __ | 2181 #undef __ |
2182 | 2182 |
2183 #endif // defined TARGET_ARCH_X64 | 2183 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |