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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 LocationSummary::kNoCall); | 973 LocationSummary::kNoCall); |
974 } | 974 } |
975 | 975 |
976 | 976 |
977 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 977 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
978 Register instance_reg = locs()->in(0).reg(); | 978 Register instance_reg = locs()->in(0).reg(); |
979 Register result_reg = locs()->out().reg(); | 979 Register result_reg = locs()->out().reg(); |
980 | 980 |
981 if (HasICData()) { | 981 if (HasICData()) { |
982 ASSERT(original() != NULL); | 982 ASSERT(original() != NULL); |
983 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 983 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
984 original()->token_pos(), | 984 original()->token_pos(), |
985 original()->try_index(), | 985 original()->try_index(), |
986 kDeoptInstanceGetterSameTarget, | 986 kDeoptInstanceGetterSameTarget, |
987 instance_reg); | 987 instance_reg); |
988 // Smis do not have instance fields (Smi class is always first). | 988 // Smis do not have instance fields (Smi class is always first). |
989 // Use 'result' as temporary register. | 989 // Use 'result' as temporary register. |
990 ASSERT(result_reg != instance_reg); | 990 ASSERT(result_reg != instance_reg); |
991 ASSERT(ic_data() != NULL); | 991 ASSERT(ic_data() != NULL); |
992 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 992 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
993 } | 993 } |
(...skipping 26 matching lines...) Expand all Loading... |
1020 summary->set_out(Location::RegisterLocation(RAX)); | 1020 summary->set_out(Location::RegisterLocation(RAX)); |
1021 return summary; | 1021 return summary; |
1022 } | 1022 } |
1023 | 1023 |
1024 | 1024 |
1025 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1025 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1026 ASSERT(locs()->in(0).reg() == RAX); // Value. | 1026 ASSERT(locs()->in(0).reg() == RAX); // Value. |
1027 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. | 1027 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. |
1028 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. | 1028 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. |
1029 | 1029 |
1030 compiler->GenerateInstanceOf(cid(), | 1030 compiler->GenerateInstanceOf(deopt_id(), |
1031 token_pos(), | 1031 token_pos(), |
1032 try_index(), | 1032 try_index(), |
1033 type(), | 1033 type(), |
1034 negate_result()); | 1034 negate_result()); |
1035 ASSERT(locs()->out().reg() == RAX); | 1035 ASSERT(locs()->out().reg() == RAX); |
1036 } | 1036 } |
1037 | 1037 |
1038 | 1038 |
1039 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1039 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
1040 return MakeCallSummary(); | 1040 return MakeCallSummary(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1079 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1079 const Class& cls = Class::ZoneHandle(constructor().owner()); |
1080 Register type_arguments = locs()->in(0).reg(); | 1080 Register type_arguments = locs()->in(0).reg(); |
1081 Register instantiator_type_arguments = locs()->in(1).reg(); | 1081 Register instantiator_type_arguments = locs()->in(1).reg(); |
1082 Register result = locs()->out().reg(); | 1082 Register result = locs()->out().reg(); |
1083 | 1083 |
1084 // Push the result place holder initialized to NULL. | 1084 // Push the result place holder initialized to NULL. |
1085 __ PushObject(Object::ZoneHandle()); | 1085 __ PushObject(Object::ZoneHandle()); |
1086 __ PushObject(cls); | 1086 __ PushObject(cls); |
1087 __ pushq(type_arguments); | 1087 __ pushq(type_arguments); |
1088 __ pushq(instantiator_type_arguments); | 1088 __ pushq(instantiator_type_arguments); |
1089 compiler->GenerateCallRuntime(cid(), | 1089 compiler->GenerateCallRuntime(deopt_id(), |
1090 token_pos(), | 1090 token_pos(), |
1091 try_index(), | 1091 try_index(), |
1092 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1092 kAllocateObjectWithBoundsCheckRuntimeEntry); |
1093 // Pop instantiator type arguments, type arguments, and class. | 1093 // Pop instantiator type arguments, type arguments, and class. |
1094 __ Drop(3); | 1094 __ Drop(3); |
1095 __ popq(result); // Pop new instance. | 1095 __ popq(result); // Pop new instance. |
1096 } | 1096 } |
1097 | 1097 |
1098 | 1098 |
1099 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1099 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
1100 return LocationSummary::Make(1, | 1100 return LocationSummary::Make(1, |
1101 Location::RequiresRegister(), | 1101 Location::RequiresRegister(), |
1102 LocationSummary::kNoCall); | 1102 LocationSummary::kNoCall); |
1103 } | 1103 } |
1104 | 1104 |
1105 | 1105 |
1106 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1106 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1107 Register instance_reg = locs()->in(0).reg(); | 1107 Register instance_reg = locs()->in(0).reg(); |
1108 Register result_reg = locs()->out().reg(); | 1108 Register result_reg = locs()->out().reg(); |
1109 if (HasICData()) { | 1109 if (HasICData()) { |
1110 ASSERT(original() != NULL); | 1110 ASSERT(original() != NULL); |
1111 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1111 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
1112 original()->token_pos(), | 1112 original()->token_pos(), |
1113 original()->try_index(), | 1113 original()->try_index(), |
1114 kDeoptInstanceGetterSameTarget, | 1114 kDeoptInstanceGetterSameTarget, |
1115 instance_reg); | 1115 instance_reg); |
1116 // Smis do not have instance fields (Smi class is always first). | 1116 // Smis do not have instance fields (Smi class is always first). |
1117 // Use 'result' as temporary register. | 1117 // Use 'result' as temporary register. |
1118 ASSERT(result_reg != instance_reg); | 1118 ASSERT(result_reg != instance_reg); |
1119 ASSERT(ic_data() != NULL); | 1119 ASSERT(ic_data() != NULL); |
1120 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1120 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
1121 } | 1121 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1165 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1166 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1166 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1167 Immediate(Smi::RawValue(len))); | 1167 Immediate(Smi::RawValue(len))); |
1168 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1168 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1169 __ Bind(&type_arguments_uninstantiated); | 1169 __ Bind(&type_arguments_uninstantiated); |
1170 } | 1170 } |
1171 // A runtime call to instantiate the type arguments is required. | 1171 // A runtime call to instantiate the type arguments is required. |
1172 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1172 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1173 __ PushObject(type_arguments()); | 1173 __ PushObject(type_arguments()); |
1174 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1174 __ pushq(instantiator_reg); // Push instantiator type arguments. |
1175 compiler->GenerateCallRuntime(cid(), | 1175 compiler->GenerateCallRuntime(deopt_id(), |
1176 token_pos(), | 1176 token_pos(), |
1177 try_index(), | 1177 try_index(), |
1178 kInstantiateTypeArgumentsRuntimeEntry); | 1178 kInstantiateTypeArgumentsRuntimeEntry); |
1179 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1179 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
1180 __ popq(result_reg); // Pop instantiated type arguments. | 1180 __ popq(result_reg); // Pop instantiated type arguments. |
1181 __ Bind(&type_arguments_instantiated); | 1181 __ Bind(&type_arguments_instantiated); |
1182 ASSERT(instantiator_reg == result_reg); | 1182 ASSERT(instantiator_reg == result_reg); |
1183 // 'result_reg': Instantiated type arguments. | 1183 // 'result_reg': Instantiated type arguments. |
1184 } | 1184 } |
1185 | 1185 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 return locs; | 1341 return locs; |
1342 } | 1342 } |
1343 | 1343 |
1344 | 1344 |
1345 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1345 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1346 Register context_value = locs()->in(0).reg(); | 1346 Register context_value = locs()->in(0).reg(); |
1347 Register result = locs()->out().reg(); | 1347 Register result = locs()->out().reg(); |
1348 | 1348 |
1349 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1349 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1350 __ pushq(context_value); | 1350 __ pushq(context_value); |
1351 compiler->GenerateCallRuntime(cid(), | 1351 compiler->GenerateCallRuntime(deopt_id(), |
1352 token_pos(), | 1352 token_pos(), |
1353 try_index(), | 1353 try_index(), |
1354 kCloneContextRuntimeEntry); | 1354 kCloneContextRuntimeEntry); |
1355 __ popq(result); // Remove argument. | 1355 __ popq(result); // Remove argument. |
1356 __ popq(result); // Get result (cloned context). | 1356 __ popq(result); // Get result (cloned context). |
1357 } | 1357 } |
1358 | 1358 |
1359 | 1359 |
1360 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1360 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
1361 return LocationSummary::Make(0, | 1361 return LocationSummary::Make(0, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 } | 1397 } |
1398 | 1398 |
1399 | 1399 |
1400 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1400 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1401 Register temp = locs()->temp(0).reg(); | 1401 Register temp = locs()->temp(0).reg(); |
1402 // Generate stack overflow check. | 1402 // Generate stack overflow check. |
1403 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1403 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
1404 __ cmpq(RSP, Address(temp, 0)); | 1404 __ cmpq(RSP, Address(temp, 0)); |
1405 Label no_stack_overflow; | 1405 Label no_stack_overflow; |
1406 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1406 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
1407 compiler->GenerateCallRuntime(cid(), | 1407 compiler->GenerateCallRuntime(deopt_id(), |
1408 token_pos(), | 1408 token_pos(), |
1409 try_index(), | 1409 try_index(), |
1410 kStackOverflowRuntimeEntry); | 1410 kStackOverflowRuntimeEntry); |
1411 __ Bind(&no_stack_overflow); | 1411 __ Bind(&no_stack_overflow); |
1412 } | 1412 } |
1413 | 1413 |
1414 | 1414 |
1415 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1415 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
1416 const intptr_t kNumInputs = 2; | 1416 const intptr_t kNumInputs = 2; |
1417 | 1417 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 } | 1475 } |
1476 } | 1476 } |
1477 | 1477 |
1478 | 1478 |
1479 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1479 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
1480 Register left = comp->locs()->in(0).reg(); | 1480 Register left = comp->locs()->in(0).reg(); |
1481 Register right = comp->locs()->in(1).reg(); | 1481 Register right = comp->locs()->in(1).reg(); |
1482 Register result = comp->locs()->out().reg(); | 1482 Register result = comp->locs()->out().reg(); |
1483 Register temp = comp->locs()->temp(0).reg(); | 1483 Register temp = comp->locs()->temp(0).reg(); |
1484 ASSERT(left == result); | 1484 ASSERT(left == result); |
1485 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1485 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
1486 comp->instance_call()->token_pos(), | 1486 comp->instance_call()->token_pos(), |
1487 comp->instance_call()->try_index(), | 1487 comp->instance_call()->try_index(), |
1488 kDeoptSmiBinaryOp, | 1488 kDeoptSmiBinaryOp, |
1489 temp, | 1489 temp, |
1490 right); | 1490 right); |
1491 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1491 // TODO(vegorov): for many binary operations this pattern can be rearranged |
1492 // to save one move. | 1492 // to save one move. |
1493 __ movq(temp, left); | 1493 __ movq(temp, left); |
1494 __ orq(left, right); | 1494 __ orq(left, right); |
1495 __ testq(left, Immediate(kSmiTagMask)); | 1495 __ testq(left, Immediate(kSmiTagMask)); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1586 __ shlq(left, right_temp); | 1586 __ shlq(left, right_temp); |
1587 __ jmp(&done); | 1587 __ jmp(&done); |
1588 { | 1588 { |
1589 __ Bind(&call_method); | 1589 __ Bind(&call_method); |
1590 Function& target = Function::ZoneHandle( | 1590 Function& target = Function::ZoneHandle( |
1591 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1591 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1592 ASSERT(!target.IsNull()); | 1592 ASSERT(!target.IsNull()); |
1593 const intptr_t kArgumentCount = 2; | 1593 const intptr_t kArgumentCount = 2; |
1594 __ pushq(temp); | 1594 __ pushq(temp); |
1595 __ pushq(right); | 1595 __ pushq(right); |
1596 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1596 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1597 comp->instance_call()->token_pos(), | 1597 comp->instance_call()->token_pos(), |
1598 comp->instance_call()->try_index(), | 1598 comp->instance_call()->try_index(), |
1599 target, | 1599 target, |
1600 kArgumentCount, | 1600 kArgumentCount, |
1601 Array::Handle()); // No argument names. | 1601 Array::Handle()); // No argument names. |
1602 ASSERT(result == RAX); | 1602 ASSERT(result == RAX); |
1603 } | 1603 } |
1604 __ Bind(&done); | 1604 __ Bind(&done); |
1605 break; | 1605 break; |
1606 } | 1606 } |
(...skipping 25 matching lines...) Expand all Loading... |
1632 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1632 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
1633 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1633 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
1634 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1634 // receiver and a Mint or Smi argument. We fall back to the run time call if |
1635 // both receiver and argument are Mint or if one of them is Mint and the other | 1635 // both receiver and argument are Mint or if one of them is Mint and the other |
1636 // is a negative Smi. | 1636 // is a negative Smi. |
1637 Register left = comp->locs()->in(0).reg(); | 1637 Register left = comp->locs()->in(0).reg(); |
1638 Register right = comp->locs()->in(1).reg(); | 1638 Register right = comp->locs()->in(1).reg(); |
1639 Register result = comp->locs()->out().reg(); | 1639 Register result = comp->locs()->out().reg(); |
1640 ASSERT(left == result); | 1640 ASSERT(left == result); |
1641 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1641 ASSERT(comp->op_kind() == Token::kBIT_AND); |
1642 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1642 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
1643 comp->instance_call()->token_pos(), | 1643 comp->instance_call()->token_pos(), |
1644 comp->instance_call()->try_index(), | 1644 comp->instance_call()->try_index(), |
1645 kDeoptMintBinaryOp, | 1645 kDeoptMintBinaryOp, |
1646 left, | 1646 left, |
1647 right); | 1647 right); |
1648 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1648 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
1649 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1649 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
1650 __ j(NOT_ZERO, &non_smi); | 1650 __ j(NOT_ZERO, &non_smi); |
1651 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1651 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1652 __ j(ZERO, &smi_smi); | 1652 __ j(ZERO, &smi_smi); |
(...skipping 27 matching lines...) Expand all Loading... |
1680 | 1680 |
1681 __ Bind(&smi_static_call); | 1681 __ Bind(&smi_static_call); |
1682 { | 1682 { |
1683 Function& target = Function::ZoneHandle( | 1683 Function& target = Function::ZoneHandle( |
1684 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1684 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1685 if (target.IsNull()) { | 1685 if (target.IsNull()) { |
1686 __ jmp(deopt); | 1686 __ jmp(deopt); |
1687 } else { | 1687 } else { |
1688 __ pushq(left); | 1688 __ pushq(left); |
1689 __ pushq(right); | 1689 __ pushq(right); |
1690 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1690 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1691 comp->instance_call()->token_pos(), | 1691 comp->instance_call()->token_pos(), |
1692 comp->instance_call()->try_index(), | 1692 comp->instance_call()->try_index(), |
1693 target, | 1693 target, |
1694 comp->instance_call()->ArgumentCount(), | 1694 comp->instance_call()->ArgumentCount(), |
1695 comp->instance_call()->argument_names()); | 1695 comp->instance_call()->argument_names()); |
1696 ASSERT(result == RAX); | 1696 ASSERT(result == RAX); |
1697 __ jmp(&done); | 1697 __ jmp(&done); |
1698 } | 1698 } |
1699 } | 1699 } |
1700 | 1700 |
1701 __ Bind(&mint_static_call); | 1701 __ Bind(&mint_static_call); |
1702 { | 1702 { |
1703 Function& target = Function::ZoneHandle( | 1703 Function& target = Function::ZoneHandle( |
1704 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1704 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
1705 if (target.IsNull()) { | 1705 if (target.IsNull()) { |
1706 __ jmp(deopt); | 1706 __ jmp(deopt); |
1707 } else { | 1707 } else { |
1708 __ pushq(left); | 1708 __ pushq(left); |
1709 __ pushq(right); | 1709 __ pushq(right); |
1710 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1710 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1711 comp->instance_call()->token_pos(), | 1711 comp->instance_call()->token_pos(), |
1712 comp->instance_call()->try_index(), | 1712 comp->instance_call()->try_index(), |
1713 target, | 1713 target, |
1714 comp->instance_call()->ArgumentCount(), | 1714 comp->instance_call()->ArgumentCount(), |
1715 comp->instance_call()->argument_names()); | 1715 comp->instance_call()->argument_names()); |
1716 ASSERT(result == RAX); | 1716 ASSERT(result == RAX); |
1717 } | 1717 } |
1718 } | 1718 } |
1719 __ Bind(&done); | 1719 __ Bind(&done); |
1720 } | 1720 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1753 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1754 compiler->GenerateCall(instance_call()->token_pos(), | 1754 compiler->GenerateCall(instance_call()->token_pos(), |
1755 instance_call()->try_index(), | 1755 instance_call()->try_index(), |
1756 &label, | 1756 &label, |
1757 PcDescriptors::kOther); | 1757 PcDescriptors::kOther); |
1758 // Newly allocated object is now in the result register (RAX). | 1758 // Newly allocated object is now in the result register (RAX). |
1759 ASSERT(result == RAX); | 1759 ASSERT(result == RAX); |
1760 __ popq(right); | 1760 __ popq(right); |
1761 __ popq(left); | 1761 __ popq(left); |
1762 | 1762 |
1763 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1763 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1764 instance_call()->token_pos(), | 1764 instance_call()->token_pos(), |
1765 instance_call()->try_index(), | 1765 instance_call()->try_index(), |
1766 kDeoptDoubleBinaryOp, | 1766 kDeoptDoubleBinaryOp, |
1767 left, | 1767 left, |
1768 right); | 1768 right); |
1769 | 1769 |
1770 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1770 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
1771 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1771 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
1772 | 1772 |
1773 switch (op_kind()) { | 1773 switch (op_kind()) { |
(...skipping 25 matching lines...) Expand all Loading... |
1799 ASSERT(ic_data.num_args_tested() == 1); | 1799 ASSERT(ic_data.num_args_tested() == 1); |
1800 // TODO(srdjan): Implement for more checks. | 1800 // TODO(srdjan): Implement for more checks. |
1801 ASSERT(ic_data.NumberOfChecks() == 1); | 1801 ASSERT(ic_data.NumberOfChecks() == 1); |
1802 intptr_t test_class_id; | 1802 intptr_t test_class_id; |
1803 Function& target = Function::Handle(); | 1803 Function& target = Function::Handle(); |
1804 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1804 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1805 | 1805 |
1806 Register value = locs()->in(0).reg(); | 1806 Register value = locs()->in(0).reg(); |
1807 Register result = locs()->out().reg(); | 1807 Register result = locs()->out().reg(); |
1808 ASSERT(value == result); | 1808 ASSERT(value == result); |
1809 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1809 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1810 instance_call()->token_pos(), | 1810 instance_call()->token_pos(), |
1811 instance_call()->try_index(), | 1811 instance_call()->try_index(), |
1812 kDeoptUnaryOp, | 1812 kDeoptUnaryOp, |
1813 value); | 1813 value); |
1814 if (test_class_id == kSmi) { | 1814 if (test_class_id == kSmi) { |
1815 __ testq(value, Immediate(kSmiTagMask)); | 1815 __ testq(value, Immediate(kSmiTagMask)); |
1816 __ j(NOT_ZERO, deopt); | 1816 __ j(NOT_ZERO, deopt); |
1817 switch (op_kind()) { | 1817 switch (op_kind()) { |
1818 case Token::kNEGATE: | 1818 case Token::kNEGATE: |
1819 __ negq(value); | 1819 __ negq(value); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1851 | 1851 |
1852 // TODO(srdjan): Implement for more checks. | 1852 // TODO(srdjan): Implement for more checks. |
1853 ASSERT(ic_data.NumberOfChecks() == 1); | 1853 ASSERT(ic_data.NumberOfChecks() == 1); |
1854 intptr_t test_class_id; | 1854 intptr_t test_class_id; |
1855 Function& target = Function::Handle(); | 1855 Function& target = Function::Handle(); |
1856 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1856 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1857 | 1857 |
1858 Register value = locs()->in(0).reg(); | 1858 Register value = locs()->in(0).reg(); |
1859 Register result = locs()->out().reg(); | 1859 Register result = locs()->out().reg(); |
1860 ASSERT(value == result); | 1860 ASSERT(value == result); |
1861 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1861 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1862 instance_call()->token_pos(), | 1862 instance_call()->token_pos(), |
1863 instance_call()->try_index(), | 1863 instance_call()->try_index(), |
1864 kDeoptUnaryOp, | 1864 kDeoptUnaryOp, |
1865 value); | 1865 value); |
1866 if (test_class_id == kDouble) { | 1866 if (test_class_id == kDouble) { |
1867 Register temp = locs()->temp(0).reg(); | 1867 Register temp = locs()->temp(0).reg(); |
1868 __ testq(value, Immediate(kSmiTagMask)); | 1868 __ testq(value, Immediate(kSmiTagMask)); |
1869 __ j(ZERO, deopt); // Smi. | 1869 __ j(ZERO, deopt); // Smi. |
1870 __ CompareClassId(value, kDouble); | 1870 __ CompareClassId(value, kDouble); |
1871 __ j(NOT_EQUAL, deopt); | 1871 __ j(NOT_EQUAL, deopt); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1907 } | 1907 } |
1908 } | 1908 } |
1909 | 1909 |
1910 | 1910 |
1911 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1911 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1912 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 1912 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; |
1913 Register result = locs()->out().reg(); | 1913 Register result = locs()->out().reg(); |
1914 | 1914 |
1915 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1915 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
1916 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1916 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1917 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1917 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1918 instance_call()->token_pos(), | 1918 instance_call()->token_pos(), |
1919 instance_call()->try_index(), | 1919 instance_call()->try_index(), |
1920 deopt_reason, | 1920 deopt_reason, |
1921 value); | 1921 value); |
1922 | 1922 |
1923 if (from() == kDouble) { | 1923 if (from() == kDouble) { |
1924 __ testq(value, Immediate(kSmiTagMask)); | 1924 __ testq(value, Immediate(kSmiTagMask)); |
1925 __ j(ZERO, deopt); // Deoptimize if Smi. | 1925 __ j(ZERO, deopt); // Deoptimize if Smi. |
1926 __ CompareClassId(value, kDouble); | 1926 __ CompareClassId(value, kDouble); |
1927 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1927 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
(...skipping 23 matching lines...) Expand all Loading... |
1951 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1951 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
1952 } | 1952 } |
1953 | 1953 |
1954 | 1954 |
1955 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1955 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
1956 return MakeCallSummary(); | 1956 return MakeCallSummary(); |
1957 } | 1957 } |
1958 | 1958 |
1959 | 1959 |
1960 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1960 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1961 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1961 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1962 instance_call()->token_pos(), | 1962 instance_call()->token_pos(), |
1963 instance_call()->try_index(), | 1963 instance_call()->try_index(), |
1964 kDeoptPolymorphicInstanceCallTestFail); | 1964 kDeoptPolymorphicInstanceCallTestFail); |
1965 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1965 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
1966 __ jmp(deopt); | 1966 __ jmp(deopt); |
1967 return; | 1967 return; |
1968 } | 1968 } |
1969 ASSERT(HasICData()); | 1969 ASSERT(HasICData()); |
1970 ASSERT(ic_data()->num_args_tested() == 1); | 1970 ASSERT(ic_data()->num_args_tested() == 1); |
1971 Label handle_smi; | 1971 Label handle_smi; |
1972 Label* is_smi_label = | 1972 Label* is_smi_label = |
1973 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1973 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
1974 | 1974 |
1975 // Load receiver into RAX. | 1975 // Load receiver into RAX. |
1976 __ movq(RAX, | 1976 __ movq(RAX, |
1977 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1977 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
1978 __ testq(RAX, Immediate(kSmiTagMask)); | 1978 __ testq(RAX, Immediate(kSmiTagMask)); |
1979 __ j(ZERO, is_smi_label); | 1979 __ j(ZERO, is_smi_label); |
1980 Label done; | 1980 Label done; |
1981 __ LoadClassId(RDI, RAX); | 1981 __ LoadClassId(RDI, RAX); |
1982 compiler->EmitTestAndCall(*ic_data(), | 1982 compiler->EmitTestAndCall(*ic_data(), |
1983 RDI, // Class id register. | 1983 RDI, // Class id register. |
1984 instance_call()->ArgumentCount(), | 1984 instance_call()->ArgumentCount(), |
1985 instance_call()->argument_names(), | 1985 instance_call()->argument_names(), |
1986 deopt, | 1986 deopt, |
1987 (is_smi_label == &handle_smi) ? &done : NULL, | 1987 (is_smi_label == &handle_smi) ? &done : NULL, |
1988 instance_call()->cid(), | 1988 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 if (is_smi_label == &handle_smi) { | 1991 if (is_smi_label == &handle_smi) { |
1992 __ Bind(&handle_smi); | 1992 __ Bind(&handle_smi); |
1993 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1993 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
1994 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1994 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
1995 compiler->GenerateStaticCall(instance_call()->cid(), | 1995 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
1996 instance_call()->token_pos(), | 1996 instance_call()->token_pos(), |
1997 instance_call()->try_index(), | 1997 instance_call()->try_index(), |
1998 target, | 1998 target, |
1999 instance_call()->ArgumentCount(), | 1999 instance_call()->ArgumentCount(), |
2000 instance_call()->argument_names()); | 2000 instance_call()->argument_names()); |
2001 } | 2001 } |
2002 __ Bind(&done); | 2002 __ Bind(&done); |
2003 } | 2003 } |
2004 | 2004 |
2005 | 2005 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2059 Register right = locs()->in(1).reg(); | 2059 Register right = locs()->in(1).reg(); |
2060 __ cmpq(left, right); | 2060 __ cmpq(left, right); |
2061 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 2061 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
2062 EmitBranchOnCondition(compiler, cond); | 2062 EmitBranchOnCondition(compiler, cond); |
2063 return; | 2063 return; |
2064 } | 2064 } |
2065 // Relational or equality. | 2065 // Relational or equality. |
2066 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2066 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
2067 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { | 2067 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { |
2068 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2068 EmitSmiComparisonOp(compiler, *locs(), kind(), this, |
2069 cid(), token_pos(), try_index()); | 2069 deopt_id(), token_pos(), try_index()); |
2070 return; | 2070 return; |
2071 } | 2071 } |
2072 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2072 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { |
2073 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2073 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, |
2074 cid(), token_pos(), try_index()); | 2074 deopt_id(), token_pos(), try_index()); |
2075 return; | 2075 return; |
2076 } | 2076 } |
2077 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2077 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
2078 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2078 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
2079 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2079 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), |
2080 cid(), token_pos(), try_index()); | 2080 deopt_id(), token_pos(), try_index()); |
2081 return; | 2081 return; |
2082 } | 2082 } |
2083 // Otherwise polymorphic dispatch? | 2083 // Otherwise polymorphic dispatch? |
2084 } | 2084 } |
2085 // Not equal is always split into '==' and negate, | 2085 // Not equal is always split into '==' and negate, |
2086 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 2086 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
2087 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); | 2087 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); |
2088 const String& function_name = | 2088 const String& function_name = |
2089 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); | 2089 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); |
2090 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 2090 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
2091 cid(), | 2091 deopt_id(), |
2092 token_pos(), | 2092 token_pos(), |
2093 try_index()); | 2093 try_index()); |
2094 const intptr_t kNumArguments = 2; | 2094 const intptr_t kNumArguments = 2; |
2095 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 2095 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
2096 compiler->GenerateInstanceCall(cid(), | 2096 compiler->GenerateInstanceCall(deopt_id(), |
2097 token_pos(), | 2097 token_pos(), |
2098 try_index(), | 2098 try_index(), |
2099 function_name, | 2099 function_name, |
2100 kNumArguments, | 2100 kNumArguments, |
2101 Array::ZoneHandle(), // No optional arguments. | 2101 Array::ZoneHandle(), // No optional arguments. |
2102 kNumArgsChecked); | 2102 kNumArgsChecked); |
2103 ASSERT(locs()->out().reg() == RAX); | 2103 ASSERT(locs()->out().reg() == RAX); |
2104 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2104 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
2105 EmitBranchOnCondition(compiler, branch_condition); | 2105 EmitBranchOnCondition(compiler, branch_condition); |
2106 } | 2106 } |
2107 | 2107 |
2108 } // namespace dart | 2108 } // namespace dart |
2109 | 2109 |
2110 #undef __ | 2110 #undef __ |
2111 | 2111 |
2112 #endif // defined TARGET_ARCH_X64 | 2112 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |