Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 10832150: Get rid of ast node ids. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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
81 __ Bind(&not_yet_hot); 81 __ Bind(&not_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 __ pushl(result); // Preserve result. 89 __ pushl(result); // Preserve result.
90 __ pushl(temp); 90 __ pushl(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 __ popl(temp); // Remove argument. 95 __ popl(temp); // Remove argument.
96 __ popl(result); // Restore result. 96 __ popl(result); // Restore result.
97 } 97 }
98 __ LeaveFrame(); 98 __ LeaveFrame();
99 __ ret(); 99 __ ret();
100 100
101 // Generate 1 byte NOP so that the debugger can patch the 101 // Generate 1 byte NOP 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 __ nop(1); 103 __ nop(1);
104 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, 104 compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
105 cid(), 105 deopt_id(),
106 token_pos(), 106 token_pos(),
107 CatchClauseNode::kInvalidTryIndex); 107 CatchClauseNode::kInvalidTryIndex);
108 } 108 }
109 109
110 110
111 LocationSummary* ClosureCallComp::MakeLocationSummary() const { 111 LocationSummary* ClosureCallComp::MakeLocationSummary() const {
112 const intptr_t kNumInputs = 0; 112 const intptr_t kNumInputs = 0;
113 const intptr_t kNumTemps = 1; 113 const intptr_t kNumTemps = 1;
114 LocationSummary* result = 114 LocationSummary* result =
115 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 115 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 190
191 // Check that the type of the value is allowed in conditional context. 191 // Check that the type of the value is allowed in conditional context.
192 // Call the runtime if the object is not bool::true or bool::false. 192 // Call the runtime if the object is not bool::true or bool::false.
193 Label done; 193 Label done;
194 __ CompareObject(obj, compiler->bool_true()); 194 __ CompareObject(obj, compiler->bool_true());
195 __ j(EQUAL, &done, Assembler::kNearJump); 195 __ j(EQUAL, &done, Assembler::kNearJump);
196 __ CompareObject(obj, compiler->bool_false()); 196 __ CompareObject(obj, compiler->bool_false());
197 __ j(EQUAL, &done, Assembler::kNearJump); 197 __ j(EQUAL, &done, Assembler::kNearJump);
198 198
199 __ pushl(obj); // Push the source object. 199 __ pushl(obj); // Push the source object.
200 compiler->GenerateCallRuntime(cid(), 200 compiler->GenerateCallRuntime(deopt_id(),
201 token_pos(), 201 token_pos(),
202 try_index(), 202 try_index(),
203 kConditionTypeErrorRuntimeEntry); 203 kConditionTypeErrorRuntimeEntry);
204 // We should never return here. 204 // We should never return here.
205 __ int3(); 205 __ int3();
206 206
207 __ Bind(&done); 207 __ Bind(&done);
208 ASSERT(obj == result); 208 ASSERT(obj == result);
209 } 209 }
210 210
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 } 257 }
258 258
259 259
260 // Optional integer arguments can often be null. Null is not collected 260 // Optional integer arguments can often be null. Null is not collected
261 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well? 261 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well?
262 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, 262 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler,
263 EqualityCompareComp* comp) { 263 EqualityCompareComp* comp) {
264 Register left = comp->locs()->in(0).reg(); 264 Register left = comp->locs()->in(0).reg();
265 Register right = comp->locs()->in(1).reg(); 265 Register right = comp->locs()->in(1).reg();
266 Register temp = comp->locs()->temp(0).reg(); 266 Register temp = comp->locs()->temp(0).reg();
267 Label* deopt = compiler->AddDeoptStub(comp->cid(), 267 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
268 comp->token_pos(), 268 comp->token_pos(),
269 comp->try_index(), 269 comp->try_index(),
270 kDeoptSmiCompareSmi, 270 kDeoptSmiCompareSmi,
271 left, 271 left,
272 right); 272 right);
273 __ movl(temp, left); 273 __ movl(temp, left);
274 __ orl(temp, right); 274 __ orl(temp, right);
275 __ testl(temp, Immediate(kSmiTagMask)); 275 __ testl(temp, Immediate(kSmiTagMask));
276 __ j(NOT_ZERO, deopt); 276 __ j(NOT_ZERO, deopt);
277 __ cmpl(left, right); 277 __ cmpl(left, right);
278 Register result = comp->locs()->out().reg(); 278 Register result = comp->locs()->out().reg();
279 Label load_true, done; 279 Label load_true, done;
280 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump); 280 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump);
281 __ LoadObject(result, compiler->bool_false()); 281 __ LoadObject(result, compiler->bool_false());
282 __ jmp(&done, Assembler::kNearJump); 282 __ jmp(&done, Assembler::kNearJump);
283 __ Bind(&load_true); 283 __ Bind(&load_true);
284 __ LoadObject(result, compiler->bool_true()); 284 __ LoadObject(result, compiler->bool_true());
285 __ Bind(&done); 285 __ Bind(&done);
286 } 286 }
287 287
288 288
289 // TODO(srdjan): Add support for mixed Smi/Double equality 289 // TODO(srdjan): Add support for mixed Smi/Double equality
290 // (see LoadDoubleOrSmiToXmm). 290 // (see LoadDoubleOrSmiToXmm).
291 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, 291 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler,
292 EqualityCompareComp* comp) { 292 EqualityCompareComp* comp) {
293 Register left = comp->locs()->in(0).reg(); 293 Register left = comp->locs()->in(0).reg();
294 Register right = comp->locs()->in(1).reg(); 294 Register right = comp->locs()->in(1).reg();
295 Register temp = comp->locs()->temp(0).reg(); 295 Register temp = comp->locs()->temp(0).reg();
296 Label* deopt = compiler->AddDeoptStub(comp->cid(), 296 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
297 comp->token_pos(), 297 comp->token_pos(),
298 comp->try_index(), 298 comp->try_index(),
299 kDeoptDoubleCompareDouble, 299 kDeoptDoubleCompareDouble,
300 left, 300 left,
301 right); 301 right);
302 Label done, is_false, is_true; 302 Label done, is_false, is_true;
303 __ CompareClassId(left, kDouble, temp); 303 __ CompareClassId(left, kDouble, temp);
304 __ j(NOT_EQUAL, deopt); 304 __ j(NOT_EQUAL, deopt);
305 __ CompareClassId(right, kDouble, temp); 305 __ CompareClassId(right, kDouble, temp);
306 __ j(NOT_EQUAL, deopt); 306 __ j(NOT_EQUAL, deopt);
307 __ movsd(XMM0, FieldAddress(left, Double::value_offset())); 307 __ movsd(XMM0, FieldAddress(left, Double::value_offset()));
308 __ movsd(XMM1, FieldAddress(right, Double::value_offset())); 308 __ movsd(XMM1, FieldAddress(right, Double::value_offset()));
309 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()), 309 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()),
310 XMM0, XMM1, 310 XMM0, XMM1,
311 comp->locs()->out().reg()); 311 comp->locs()->out().reg());
312 } 312 }
313 313
314 314
315 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 315 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
316 EqualityCompareComp* comp) { 316 EqualityCompareComp* comp) {
317 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 317 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
318 comp->cid(), 318 comp->deopt_id(),
319 comp->token_pos(), 319 comp->token_pos(),
320 comp->try_index()); 320 comp->try_index());
321 const String& operator_name = String::ZoneHandle(Symbols::New("==")); 321 const String& operator_name = String::ZoneHandle(Symbols::New("=="));
322 const int kNumberOfArguments = 2; 322 const int kNumberOfArguments = 2;
323 const Array& kNoArgumentNames = Array::Handle(); 323 const Array& kNoArgumentNames = Array::Handle();
324 const int kNumArgumentsChecked = 2; 324 const int kNumArgumentsChecked = 2;
325 325
326 compiler->GenerateInstanceCall(comp->cid(), 326 compiler->GenerateInstanceCall(comp->deopt_id(),
327 comp->token_pos(), 327 comp->token_pos(),
328 comp->try_index(), 328 comp->try_index(),
329 operator_name, 329 operator_name,
330 kNumberOfArguments, 330 kNumberOfArguments,
331 kNoArgumentNames, 331 kNoArgumentNames,
332 kNumArgumentsChecked); 332 kNumArgumentsChecked);
333 ASSERT(comp->locs()->out().reg() == EAX); 333 ASSERT(comp->locs()->out().reg() == EAX);
334 if (comp->kind() == Token::kNE) { 334 if (comp->kind() == Token::kNE) {
335 Label done, false_label; 335 Label done, false_label;
336 __ CompareObject(EAX, compiler->bool_true()); 336 __ CompareObject(EAX, compiler->bool_true());
337 __ j(EQUAL, &false_label, Assembler::kNearJump); 337 __ j(EQUAL, &false_label, Assembler::kNearJump);
338 __ LoadObject(EAX, compiler->bool_true()); 338 __ LoadObject(EAX, compiler->bool_true());
339 __ jmp(&done, Assembler::kNearJump); 339 __ jmp(&done, Assembler::kNearJump);
340 __ Bind(&false_label); 340 __ Bind(&false_label);
341 __ LoadObject(EAX, compiler->bool_false()); 341 __ LoadObject(EAX, compiler->bool_false());
342 __ Bind(&done); 342 __ Bind(&done);
343 } 343 }
344 } 344 }
345 345
346 346
347 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 347 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
348 const ICData& orig_ic_data, 348 const ICData& orig_ic_data,
349 const LocationSummary& locs, 349 const LocationSummary& locs,
350 BranchInstr* branch, 350 BranchInstr* branch,
351 Token::Kind kind, 351 Token::Kind kind,
352 intptr_t cid, 352 intptr_t deopt_id,
353 intptr_t token_pos, 353 intptr_t token_pos,
354 intptr_t try_index) { 354 intptr_t try_index) {
355 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 355 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
356 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); 356 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
357 ASSERT(ic_data.NumberOfChecks() > 0); 357 ASSERT(ic_data.NumberOfChecks() > 0);
358 ASSERT(ic_data.num_args_tested() == 1); 358 ASSERT(ic_data.num_args_tested() == 1);
359 Label* deopt = compiler->AddDeoptStub(cid, 359 Label* deopt = compiler->AddDeoptStub(deopt_id,
360 token_pos, 360 token_pos,
361 try_index, 361 try_index,
362 kDeoptEquality); 362 kDeoptEquality);
363 Register left = locs.in(0).reg(); 363 Register left = locs.in(0).reg();
364 Register right = locs.in(1).reg(); 364 Register right = locs.in(1).reg();
365 __ testl(left, Immediate(kSmiTagMask)); 365 __ testl(left, Immediate(kSmiTagMask));
366 Register temp = locs.temp(0).reg(); 366 Register temp = locs.temp(0).reg();
367 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { 367 if (ic_data.GetReceiverClassIdAt(0) == kSmi) {
368 Label done, load_class_id; 368 Label done, load_class_id;
369 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); 369 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
(...skipping 27 matching lines...) Expand all
397 Label load_true; 397 Label load_true;
398 __ j(cond, &load_true, Assembler::kNearJump); 398 __ j(cond, &load_true, Assembler::kNearJump);
399 __ LoadObject(result, compiler->bool_false()); 399 __ LoadObject(result, compiler->bool_false());
400 __ jmp(&done); 400 __ jmp(&done);
401 __ Bind(&load_true); 401 __ Bind(&load_true);
402 __ LoadObject(result, compiler->bool_true()); 402 __ LoadObject(result, compiler->bool_true());
403 } 403 }
404 } else { 404 } else {
405 const int kNumberOfArguments = 2; 405 const int kNumberOfArguments = 2;
406 const Array& kNoArgumentNames = Array::Handle(); 406 const Array& kNoArgumentNames = Array::Handle();
407 compiler->GenerateStaticCall(cid, 407 compiler->GenerateStaticCall(deopt_id,
408 token_pos, 408 token_pos,
409 try_index, 409 try_index,
410 target, 410 target,
411 kNumberOfArguments, 411 kNumberOfArguments,
412 kNoArgumentNames); 412 kNoArgumentNames);
413 if (branch == NULL) { 413 if (branch == NULL) {
414 if (kind == Token::kNE) { 414 if (kind == Token::kNE) {
415 Label false_label; 415 Label false_label;
416 __ CompareObject(EAX, compiler->bool_true()); 416 __ CompareObject(EAX, compiler->bool_true());
417 __ j(EQUAL, &false_label, Assembler::kNearJump); 417 __ j(EQUAL, &false_label, Assembler::kNearJump);
(...skipping 18 matching lines...) Expand all
436 436
437 437
438 // First test if receiver is NULL, in which case === is applied. 438 // First test if receiver is NULL, in which case === is applied.
439 // If type feedback was provided (lists of <class-id, target>), do a 439 // If type feedback was provided (lists of <class-id, target>), do a
440 // type by type check (either === or static call to the operator. 440 // type by type check (either === or static call to the operator.
441 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 441 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
442 const LocationSummary& locs, 442 const LocationSummary& locs,
443 Token::Kind kind, 443 Token::Kind kind,
444 BranchInstr* branch, 444 BranchInstr* branch,
445 const ICData& ic_data, 445 const ICData& ic_data,
446 intptr_t cid, 446 intptr_t deopt_id,
447 intptr_t token_pos, 447 intptr_t token_pos,
448 intptr_t try_index) { 448 intptr_t try_index) {
449 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 449 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
450 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); 450 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
451 Register left = locs.in(0).reg(); 451 Register left = locs.in(0).reg();
452 Register right = locs.in(1).reg(); 452 Register right = locs.in(1).reg();
453 const Immediate raw_null = 453 const Immediate raw_null =
454 Immediate(reinterpret_cast<intptr_t>(Object::null())); 454 Immediate(reinterpret_cast<intptr_t>(Object::null()));
455 Label done, non_null_compare; 455 Label done, non_null_compare;
456 __ cmpl(left, raw_null); 456 __ cmpl(left, raw_null);
(...skipping 10 matching lines...) Expand all
467 __ LoadObject(result, compiler->bool_false()); 467 __ LoadObject(result, compiler->bool_false());
468 __ jmp(&done); 468 __ jmp(&done);
469 __ Bind(&load_true); 469 __ Bind(&load_true);
470 __ LoadObject(result, compiler->bool_true()); 470 __ LoadObject(result, compiler->bool_true());
471 } 471 }
472 __ jmp(&done); 472 __ jmp(&done);
473 __ Bind(&non_null_compare); // Receiver is not null. 473 __ Bind(&non_null_compare); // Receiver is not null.
474 __ pushl(left); 474 __ pushl(left);
475 __ pushl(right); 475 __ pushl(right);
476 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, 476 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
477 cid, token_pos, try_index); 477 deopt_id, token_pos, try_index);
478 __ Bind(&done); 478 __ Bind(&done);
479 } 479 }
480 480
481 481
482 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 482 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
483 if (receiver_class_id() == kSmi) { 483 if (receiver_class_id() == kSmi) {
484 EmitSmiEqualityCompare(compiler, this); 484 EmitSmiEqualityCompare(compiler, this);
485 return; 485 return;
486 } 486 }
487 if (receiver_class_id() == kDouble) { 487 if (receiver_class_id() == kDouble) {
488 EmitDoubleEqualityCompare(compiler, this); 488 EmitDoubleEqualityCompare(compiler, this);
489 return; 489 return;
490 } 490 }
491 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 491 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
492 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, 492 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(),
493 *ic_data(), cid(), token_pos(), try_index()); 493 deopt_id(), token_pos(), try_index());
494 } else { 494 } else {
495 Register left = locs()->in(0).reg(); 495 Register left = locs()->in(0).reg();
496 Register right = locs()->in(1).reg(); 496 Register right = locs()->in(1).reg();
497 __ pushl(left); 497 __ pushl(left);
498 __ pushl(right); 498 __ pushl(right);
499 EmitEqualityAsInstanceCall(compiler, this); 499 EmitEqualityAsInstanceCall(compiler, this);
500 } 500 }
501 } 501 }
502 502
503 503
(...skipping 11 matching lines...) Expand all
515 } 515 }
516 ASSERT(operands_class_id() == kObject); 516 ASSERT(operands_class_id() == kObject);
517 return MakeCallSummary(); 517 return MakeCallSummary();
518 } 518 }
519 519
520 520
521 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 521 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
522 const LocationSummary& locs, 522 const LocationSummary& locs,
523 Token::Kind kind, 523 Token::Kind kind,
524 BranchInstr* branch, 524 BranchInstr* branch,
525 intptr_t cid, 525 intptr_t deopt_id,
526 intptr_t token_pos, 526 intptr_t token_pos,
527 intptr_t try_index) { 527 intptr_t try_index) {
528 Register left = locs.in(0).reg(); 528 Register left = locs.in(0).reg();
529 Register right = locs.in(1).reg(); 529 Register right = locs.in(1).reg();
530 Register temp = locs.temp(0).reg(); 530 Register temp = locs.temp(0).reg();
531 Label* deopt = compiler->AddDeoptStub(cid, 531 Label* deopt = compiler->AddDeoptStub(deopt_id,
532 token_pos, 532 token_pos,
533 try_index, 533 try_index,
534 kDeoptSmiCompareSmi, 534 kDeoptSmiCompareSmi,
535 left, 535 left,
536 right); 536 right);
537 __ movl(temp, left); 537 __ movl(temp, left);
538 __ orl(temp, right); 538 __ orl(temp, right);
539 __ testl(temp, Immediate(kSmiTagMask)); 539 __ testl(temp, Immediate(kSmiTagMask));
540 __ j(NOT_ZERO, deopt); 540 __ j(NOT_ZERO, deopt);
541 541
(...skipping 27 matching lines...) Expand all
569 UNREACHABLE(); 569 UNREACHABLE();
570 return OVERFLOW; 570 return OVERFLOW;
571 } 571 }
572 } 572 }
573 573
574 574
575 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 575 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
576 const LocationSummary& locs, 576 const LocationSummary& locs,
577 Token::Kind kind, 577 Token::Kind kind,
578 BranchInstr* branch, 578 BranchInstr* branch,
579 intptr_t cid, 579 intptr_t deopt_id,
580 intptr_t token_pos, 580 intptr_t token_pos,
581 intptr_t try_index) { 581 intptr_t try_index) {
582 Register left = locs.in(0).reg(); 582 Register left = locs.in(0).reg();
583 Register right = locs.in(1).reg(); 583 Register right = locs.in(1).reg();
584 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. 584 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
585 Register temp = locs.temp(0).reg(); 585 Register temp = locs.temp(0).reg();
586 Label* deopt = compiler->AddDeoptStub(cid, 586 Label* deopt = compiler->AddDeoptStub(deopt_id,
587 token_pos, 587 token_pos,
588 try_index, 588 try_index,
589 kDeoptDoubleComparison, 589 kDeoptDoubleComparison,
590 left, 590 left,
591 right); 591 right);
592 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 592 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
593 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 593 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
594 594
595 Condition true_condition = TokenKindToDoubleCondition(kind); 595 Condition true_condition = TokenKindToDoubleCondition(kind);
596 if (branch != NULL) { 596 if (branch != NULL) {
597 compiler->EmitDoubleCompareBranch( 597 compiler->EmitDoubleCompareBranch(
598 true_condition, XMM0, XMM1, branch); 598 true_condition, XMM0, XMM1, branch);
599 } else { 599 } else {
600 compiler->EmitDoubleCompareBool( 600 compiler->EmitDoubleCompareBool(
601 true_condition, XMM0, XMM1, locs.out().reg()); 601 true_condition, XMM0, XMM1, locs.out().reg());
602 } 602 }
603 } 603 }
604 604
605 605
606 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 606 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
607 if (operands_class_id() == kSmi) { 607 if (operands_class_id() == kSmi) {
608 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, 608 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL,
609 cid(), token_pos(), try_index()); 609 deopt_id(), token_pos(), try_index());
610 return; 610 return;
611 } 611 }
612 if (operands_class_id() == kDouble) { 612 if (operands_class_id() == kDouble) {
613 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, 613 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL,
614 cid(), token_pos(), try_index()); 614 deopt_id(), token_pos(), try_index());
615 return; 615 return;
616 } 616 }
617 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 617 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
618 Label* deopt = compiler->AddDeoptStub(cid(), 618 Label* deopt = compiler->AddDeoptStub(deopt_id(),
619 token_pos(), 619 token_pos(),
620 try_index(), 620 try_index(),
621 kDeoptRelationalOp); 621 kDeoptRelationalOp);
622 // Load receiver into EAX, class into EDI. 622 // Load receiver into EAX, class into EDI.
623 Label done; 623 Label done;
624 const intptr_t kNumArguments = 2; 624 const intptr_t kNumArguments = 2;
625 __ movl(EDI, Immediate(kSmi)); 625 __ movl(EDI, Immediate(kSmi));
626 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); 626 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize));
627 __ testl(EAX, Immediate(kSmiTagMask)); 627 __ testl(EAX, Immediate(kSmiTagMask));
628 __ j(ZERO, &done); 628 __ j(ZERO, &done);
629 __ LoadClassId(EDI, EAX); 629 __ LoadClassId(EDI, EAX);
630 __ Bind(&done); 630 __ Bind(&done);
631 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), 631 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
632 EDI, // Class id register. 632 EDI, // Class id register.
633 kNumArguments, 633 kNumArguments,
634 Array::Handle(), // No named arguments. 634 Array::Handle(), // No named arguments.
635 deopt, // Deoptimize target. 635 deopt, // Deoptimize target.
636 NULL, // Fallthrough when done. 636 NULL, // Fallthrough when done.
637 cid(), 637 deopt_id(),
638 token_pos(), 638 token_pos(),
639 try_index()); 639 try_index());
640 return; 640 return;
641 } 641 }
642 const String& function_name = 642 const String& function_name =
643 String::ZoneHandle(Symbols::New(Token::Str(kind()))); 643 String::ZoneHandle(Symbols::New(Token::Str(kind())));
644 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 644 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
645 cid(), 645 deopt_id(),
646 token_pos(), 646 token_pos(),
647 try_index()); 647 try_index());
648 const intptr_t kNumArguments = 2; 648 const intptr_t kNumArguments = 2;
649 const intptr_t kNumArgsChecked = 2; // Type-feedback. 649 const intptr_t kNumArgsChecked = 2; // Type-feedback.
650 compiler->GenerateInstanceCall(cid(), 650 compiler->GenerateInstanceCall(deopt_id(),
651 token_pos(), 651 token_pos(),
652 try_index(), 652 try_index(),
653 function_name, 653 function_name,
654 kNumArguments, 654 kNumArguments,
655 Array::ZoneHandle(), // No optional arguments. 655 Array::ZoneHandle(), // No optional arguments.
656 kNumArgsChecked); 656 kNumArgsChecked);
657 ASSERT(locs()->out().reg() == EAX); 657 ASSERT(locs()->out().reg() == EAX);
658 } 658 }
659 659
660 660
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 return locs; 715 return locs;
716 } else { 716 } else {
717 ASSERT(receiver_type() == kIllegalObjectKind); 717 ASSERT(receiver_type() == kIllegalObjectKind);
718 return MakeCallSummary(); 718 return MakeCallSummary();
719 } 719 }
720 } 720 }
721 721
722 722
723 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, 723 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler,
724 LoadIndexedComp* comp) { 724 LoadIndexedComp* comp) {
725 Label* deopt = compiler->AddDeoptStub(comp->cid(), 725 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
726 comp->token_pos(), 726 comp->token_pos(),
727 comp->try_index(), 727 comp->try_index(),
728 kDeoptLoadIndexedPolymorphic); 728 kDeoptLoadIndexedPolymorphic);
729 ASSERT(comp->ic_data()->NumberOfChecks() > 0); 729 ASSERT(comp->ic_data()->NumberOfChecks() > 0);
730 ASSERT(comp->HasICData()); 730 ASSERT(comp->HasICData());
731 const ICData& ic_data = *comp->ic_data(); 731 const ICData& ic_data = *comp->ic_data();
732 ASSERT(ic_data.num_args_tested() == 1); 732 ASSERT(ic_data.num_args_tested() == 1);
733 // No indexed access on Smi. 733 // No indexed access on Smi.
734 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); 734 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi);
735 // Load receiver into EAX. 735 // Load receiver into EAX.
736 const intptr_t kNumArguments = 2; 736 const intptr_t kNumArguments = 2;
737 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); 737 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize));
738 __ testl(EAX, Immediate(kSmiTagMask)); 738 __ testl(EAX, Immediate(kSmiTagMask));
739 __ j(ZERO, deopt); 739 __ j(ZERO, deopt);
740 __ LoadClassId(EDI, EAX); 740 __ LoadClassId(EDI, EAX);
741 compiler->EmitTestAndCall(ic_data, 741 compiler->EmitTestAndCall(ic_data,
742 EDI, // Class id register. 742 EDI, // Class id register.
743 kNumArguments, 743 kNumArguments,
744 Array::Handle(), // No named arguments. 744 Array::Handle(), // No named arguments.
745 deopt, // Deoptimize target. 745 deopt, // Deoptimize target.
746 NULL, // Fallthrough when done. 746 NULL, // Fallthrough when done.
747 comp->cid(), 747 comp->deopt_id(),
748 comp->token_pos(), 748 comp->token_pos(),
749 comp->try_index()); 749 comp->try_index());
750 } 750 }
751 751
752 752
753 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { 753 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) {
754 if (receiver_type() == kIllegalObjectKind) { 754 if (receiver_type() == kIllegalObjectKind) {
755 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 755 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
756 EmitLoadIndexedPolymorphic(compiler, this); 756 EmitLoadIndexedPolymorphic(compiler, this);
757 } else { 757 } else {
758 compiler->EmitLoadIndexedGeneric(this); 758 compiler->EmitLoadIndexedGeneric(this);
759 } 759 }
760 ASSERT(locs()->out().reg() == EAX); 760 ASSERT(locs()->out().reg() == EAX);
761 return; 761 return;
762 } 762 }
763 763
764 Register receiver = locs()->in(0).reg(); 764 Register receiver = locs()->in(0).reg();
765 Register index = locs()->in(1).reg(); 765 Register index = locs()->in(1).reg();
766 Register result = locs()->out().reg(); 766 Register result = locs()->out().reg();
767 Register temp = locs()->temp(0).reg(); 767 Register temp = locs()->temp(0).reg();
768 768
769 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? 769 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ?
770 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; 770 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray;
771 771
772 Label* deopt = compiler->AddDeoptStub(cid(), 772 Label* deopt = compiler->AddDeoptStub(deopt_id(),
773 token_pos(), 773 token_pos(),
774 try_index(), 774 try_index(),
775 deopt_reason, 775 deopt_reason,
776 receiver, 776 receiver,
777 index); 777 index);
778 778
779 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. 779 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi.
780 __ j(ZERO, deopt); 780 __ j(ZERO, deopt);
781 __ CompareClassId(receiver, receiver_type(), temp); 781 __ CompareClassId(receiver, receiver_type(), temp);
782 __ j(NOT_EQUAL, deopt); 782 __ j(NOT_EQUAL, deopt);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 } 833 }
834 } 834 }
835 835
836 836
837 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, 837 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler,
838 StoreIndexedComp* comp) { 838 StoreIndexedComp* comp) {
839 const String& function_name = 839 const String& function_name =
840 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); 840 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX)));
841 841
842 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 842 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
843 comp->cid(), 843 comp->deopt_id(),
844 comp->token_pos(), 844 comp->token_pos(),
845 comp->try_index()); 845 comp->try_index());
846 846
847 const intptr_t kNumArguments = 3; 847 const intptr_t kNumArguments = 3;
848 const intptr_t kNumArgsChecked = 1; // Type-feedback. 848 const intptr_t kNumArgsChecked = 1; // Type-feedback.
849 compiler->GenerateInstanceCall(comp->cid(), 849 compiler->GenerateInstanceCall(comp->deopt_id(),
850 comp->token_pos(), 850 comp->token_pos(),
851 comp->try_index(), 851 comp->try_index(),
852 function_name, 852 function_name,
853 kNumArguments, 853 kNumArguments,
854 Array::ZoneHandle(), // No named arguments. 854 Array::ZoneHandle(), // No named arguments.
855 kNumArgsChecked); 855 kNumArgsChecked);
856 } 856 }
857 857
858 858
859 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, 859 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler,
860 StoreIndexedComp* comp) { 860 StoreIndexedComp* comp) {
861 Label* deopt = compiler->AddDeoptStub(comp->cid(), 861 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
862 comp->token_pos(), 862 comp->token_pos(),
863 comp->try_index(), 863 comp->try_index(),
864 kDeoptStoreIndexedPolymorphic); 864 kDeoptStoreIndexedPolymorphic);
865 ASSERT(comp->ic_data()->NumberOfChecks() > 0); 865 ASSERT(comp->ic_data()->NumberOfChecks() > 0);
866 ASSERT(comp->HasICData()); 866 ASSERT(comp->HasICData());
867 const ICData& ic_data = *comp->ic_data(); 867 const ICData& ic_data = *comp->ic_data();
868 ASSERT(ic_data.num_args_tested() == 1); 868 ASSERT(ic_data.num_args_tested() == 1);
869 // No indexed access on Smi. 869 // No indexed access on Smi.
870 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); 870 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi);
871 // Load receiver into EAX. 871 // Load receiver into EAX.
872 const intptr_t kNumArguments = 3; 872 const intptr_t kNumArguments = 3;
873 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); 873 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize));
874 __ testl(EAX, Immediate(kSmiTagMask)); 874 __ testl(EAX, Immediate(kSmiTagMask));
875 __ j(ZERO, deopt); 875 __ j(ZERO, deopt);
876 __ LoadClassId(EDI, EAX); 876 __ LoadClassId(EDI, EAX);
877 compiler->EmitTestAndCall(ic_data, 877 compiler->EmitTestAndCall(ic_data,
878 EDI, // Class id register. 878 EDI, // Class id register.
879 kNumArguments, 879 kNumArguments,
880 Array::Handle(), // No named arguments. 880 Array::Handle(), // No named arguments.
881 deopt, // Deoptimize target. 881 deopt, // Deoptimize target.
882 NULL, // Fallthrough when done. 882 NULL, // Fallthrough when done.
883 comp->cid(), 883 comp->deopt_id(),
884 comp->token_pos(), 884 comp->token_pos(),
885 comp->try_index()); 885 comp->try_index());
886 } 886 }
887 887
888 888
889 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { 889 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) {
890 if (receiver_type() == kIllegalObjectKind) { 890 if (receiver_type() == kIllegalObjectKind) {
891 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 891 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
892 EmitStoreIndexedPolymorphic(compiler, this); 892 EmitStoreIndexedPolymorphic(compiler, this);
893 } else { 893 } else {
894 EmitStoreIndexedGeneric(compiler, this); 894 EmitStoreIndexedGeneric(compiler, this);
895 } 895 }
896 return; 896 return;
897 } 897 }
898 898
899 Register receiver = locs()->in(0).reg(); 899 Register receiver = locs()->in(0).reg();
900 Register index = locs()->in(1).reg(); 900 Register index = locs()->in(1).reg();
901 Register value = locs()->in(2).reg(); 901 Register value = locs()->in(2).reg();
902 Register temp = locs()->temp(0).reg(); 902 Register temp = locs()->temp(0).reg();
903 903
904 Label* deopt = compiler->AddDeoptStub(cid(), 904 Label* deopt = compiler->AddDeoptStub(deopt_id(),
905 token_pos(), 905 token_pos(),
906 try_index(), 906 try_index(),
907 kDeoptStoreIndexed, 907 kDeoptStoreIndexed,
908 receiver, 908 receiver,
909 index, 909 index,
910 value); 910 value);
911 911
912 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. 912 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi.
913 __ j(ZERO, deopt); 913 __ j(ZERO, deopt);
914 __ CompareClassId(receiver, receiver_type(), temp); 914 __ CompareClassId(receiver, receiver_type(), temp);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 950
951 951
952 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { 952 LocationSummary* InstanceSetterComp::MakeLocationSummary() const {
953 return MakeCallSummary(); 953 return MakeCallSummary();
954 } 954 }
955 955
956 956
957 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { 957 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) {
958 Label* deopt = NULL; 958 Label* deopt = NULL;
959 if (compiler->is_optimizing()) { 959 if (compiler->is_optimizing()) {
960 deopt = compiler->AddDeoptStub(cid(), 960 deopt = compiler->AddDeoptStub(deopt_id(),
961 token_pos(), 961 token_pos(),
962 try_index(), 962 try_index(),
963 kDeoptInstanceSetter); 963 kDeoptInstanceSetter);
964 } 964 }
965 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 965 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
966 // No index-setter on Smi's. 966 // No index-setter on Smi's.
967 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi); 967 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi);
968 // Load receiver into EAX. 968 // Load receiver into EAX.
969 const intptr_t kNumArguments = 2; 969 const intptr_t kNumArguments = 2;
970 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); 970 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize));
971 __ testl(EAX, Immediate(kSmiTagMask)); 971 __ testl(EAX, Immediate(kSmiTagMask));
972 __ j(ZERO, deopt); 972 __ j(ZERO, deopt);
973 __ LoadClassId(EDI, EAX); 973 __ LoadClassId(EDI, EAX);
974 compiler->EmitTestAndCall(*ic_data(), 974 compiler->EmitTestAndCall(*ic_data(),
975 EDI, // Class id register. 975 EDI, // Class id register.
976 kNumArguments, 976 kNumArguments,
977 Array::Handle(), // No named arguments. 977 Array::Handle(), // No named arguments.
978 deopt, // Deoptimize target. 978 deopt, // Deoptimize target.
979 NULL, // Fallthrough when done. 979 NULL, // Fallthrough when done.
980 cid(), 980 deopt_id(),
981 token_pos(), 981 token_pos(),
982 try_index()); 982 try_index());
983 983
984 } else if (compiler->is_optimizing()) { 984 } else if (compiler->is_optimizing()) {
985 // Get some IC data then optimize again. 985 // Get some IC data then optimize again.
986 __ jmp(deopt); 986 __ jmp(deopt);
987 } else { 987 } else {
988 // Unoptimized code. 988 // Unoptimized code.
989 const String& function_name = 989 const String& function_name =
990 String::ZoneHandle(Field::SetterSymbol(field_name())); 990 String::ZoneHandle(Field::SetterSymbol(field_name()));
991 991
992 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 992 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
993 cid(), 993 deopt_id(),
994 token_pos(), 994 token_pos(),
995 try_index()); 995 try_index());
996 const intptr_t kArgumentCount = 2; 996 const intptr_t kArgumentCount = 2;
997 const intptr_t kCheckedArgumentCount = 1; 997 const intptr_t kCheckedArgumentCount = 1;
998 compiler->GenerateInstanceCall(cid(), 998 compiler->GenerateInstanceCall(deopt_id(),
999 token_pos(), 999 token_pos(),
1000 try_index(), 1000 try_index(),
1001 function_name, 1001 function_name,
1002 kArgumentCount, 1002 kArgumentCount,
1003 Array::ZoneHandle(), 1003 Array::ZoneHandle(),
1004 kCheckedArgumentCount); 1004 kCheckedArgumentCount);
1005 } 1005 }
1006 } 1006 }
1007 1007
1008 1008
1009 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { 1009 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const {
1010 // TODO(fschneider): For this instruction the input register may be 1010 // TODO(fschneider): For this instruction the input register may be
1011 // reused for the result (but is not required to) because the input 1011 // reused for the result (but is not required to) because the input
1012 // is not used after the result is defined. We should consider adding 1012 // is not used after the result is defined. We should consider adding
1013 // this information to the input policy. 1013 // this information to the input policy.
1014 return LocationSummary::Make(1, 1014 return LocationSummary::Make(1,
1015 Location::RequiresRegister(), 1015 Location::RequiresRegister(),
1016 LocationSummary::kNoCall); 1016 LocationSummary::kNoCall);
1017 } 1017 }
1018 1018
1019 1019
1020 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1020 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1021 Register instance_reg = locs()->in(0).reg(); 1021 Register instance_reg = locs()->in(0).reg();
1022 Register result_reg = locs()->out().reg(); 1022 Register result_reg = locs()->out().reg();
1023 1023
1024 if (HasICData()) { 1024 if (HasICData()) {
1025 ASSERT(original() != NULL); 1025 ASSERT(original() != NULL);
1026 Label* deopt = compiler->AddDeoptStub(original()->cid(), 1026 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
1027 original()->token_pos(), 1027 original()->token_pos(),
1028 original()->try_index(), 1028 original()->try_index(),
1029 kDeoptInstanceGetterSameTarget, 1029 kDeoptInstanceGetterSameTarget,
1030 instance_reg); 1030 instance_reg);
1031 // Smis do not have instance fields (Smi class is always first). 1031 // Smis do not have instance fields (Smi class is always first).
1032 // Use 'result' as temporary register. 1032 // Use 'result' as temporary register.
1033 ASSERT(result_reg != instance_reg); 1033 ASSERT(result_reg != instance_reg);
1034 ASSERT(ic_data() != NULL); 1034 ASSERT(ic_data() != NULL);
1035 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 1035 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
1036 } 1036 }
(...skipping 26 matching lines...) Expand all
1063 summary->set_out(Location::RegisterLocation(EAX)); 1063 summary->set_out(Location::RegisterLocation(EAX));
1064 return summary; 1064 return summary;
1065 } 1065 }
1066 1066
1067 1067
1068 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1068 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1069 ASSERT(locs()->in(0).reg() == EAX); // Value. 1069 ASSERT(locs()->in(0).reg() == EAX); // Value.
1070 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. 1070 ASSERT(locs()->in(1).reg() == ECX); // Instantiator.
1071 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. 1071 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments.
1072 1072
1073 compiler->GenerateInstanceOf(cid(), 1073 compiler->GenerateInstanceOf(deopt_id(),
1074 token_pos(), 1074 token_pos(),
1075 try_index(), 1075 try_index(),
1076 type(), 1076 type(),
1077 negate_result()); 1077 negate_result());
1078 ASSERT(locs()->out().reg() == EAX); 1078 ASSERT(locs()->out().reg() == EAX);
1079 } 1079 }
1080 1080
1081 1081
1082 LocationSummary* CreateArrayComp::MakeLocationSummary() const { 1082 LocationSummary* CreateArrayComp::MakeLocationSummary() const {
1083 // TODO(regis): The elements of the array could be considered as arguments to 1083 // 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
1136 const Class& cls = Class::ZoneHandle(constructor().owner()); 1136 const Class& cls = Class::ZoneHandle(constructor().owner());
1137 Register type_arguments = locs()->in(0).reg(); 1137 Register type_arguments = locs()->in(0).reg();
1138 Register instantiator_type_arguments = locs()->in(1).reg(); 1138 Register instantiator_type_arguments = locs()->in(1).reg();
1139 Register result = locs()->out().reg(); 1139 Register result = locs()->out().reg();
1140 1140
1141 // Push the result place holder initialized to NULL. 1141 // Push the result place holder initialized to NULL.
1142 __ PushObject(Object::ZoneHandle()); 1142 __ PushObject(Object::ZoneHandle());
1143 __ PushObject(cls); 1143 __ PushObject(cls);
1144 __ pushl(type_arguments); 1144 __ pushl(type_arguments);
1145 __ pushl(instantiator_type_arguments); 1145 __ pushl(instantiator_type_arguments);
1146 compiler->GenerateCallRuntime(cid(), 1146 compiler->GenerateCallRuntime(deopt_id(),
1147 token_pos(), 1147 token_pos(),
1148 try_index(), 1148 try_index(),
1149 kAllocateObjectWithBoundsCheckRuntimeEntry); 1149 kAllocateObjectWithBoundsCheckRuntimeEntry);
1150 // Pop instantiator type arguments, type arguments, and class. 1150 // Pop instantiator type arguments, type arguments, and class.
1151 // source location. 1151 // source location.
1152 __ Drop(3); 1152 __ Drop(3);
1153 __ popl(result); // Pop new instance. 1153 __ popl(result); // Pop new instance.
1154 } 1154 }
1155 1155
1156 1156
1157 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { 1157 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const {
1158 return LocationSummary::Make(1, 1158 return LocationSummary::Make(1,
1159 Location::RequiresRegister(), 1159 Location::RequiresRegister(),
1160 LocationSummary::kNoCall); 1160 LocationSummary::kNoCall);
1161 } 1161 }
1162 1162
1163 1163
1164 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1164 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1165 Register instance_reg = locs()->in(0).reg(); 1165 Register instance_reg = locs()->in(0).reg();
1166 Register result_reg = locs()->out().reg(); 1166 Register result_reg = locs()->out().reg();
1167 if (HasICData()) { 1167 if (HasICData()) {
1168 ASSERT(original() != NULL); 1168 ASSERT(original() != NULL);
1169 Label* deopt = compiler->AddDeoptStub(original()->cid(), 1169 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
1170 original()->token_pos(), 1170 original()->token_pos(),
1171 original()->try_index(), 1171 original()->try_index(),
1172 kDeoptInstanceGetterSameTarget, 1172 kDeoptInstanceGetterSameTarget,
1173 instance_reg); 1173 instance_reg);
1174 // Smis do not have instance fields (Smi class is always first). 1174 // Smis do not have instance fields (Smi class is always first).
1175 // Use 'result' as temporary register. 1175 // Use 'result' as temporary register.
1176 ASSERT(result_reg != instance_reg); 1176 ASSERT(result_reg != instance_reg);
1177 ASSERT(ic_data() != NULL); 1177 ASSERT(ic_data() != NULL);
1178 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 1178 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
1179 } 1179 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1225 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 1225 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
1226 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), 1226 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()),
1227 Immediate(Smi::RawValue(len))); 1227 Immediate(Smi::RawValue(len)));
1228 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 1228 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
1229 __ Bind(&type_arguments_uninstantiated); 1229 __ Bind(&type_arguments_uninstantiated);
1230 } 1230 }
1231 // A runtime call to instantiate the type arguments is required. 1231 // A runtime call to instantiate the type arguments is required.
1232 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1232 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1233 __ PushObject(type_arguments()); 1233 __ PushObject(type_arguments());
1234 __ pushl(instantiator_reg); // Push instantiator type arguments. 1234 __ pushl(instantiator_reg); // Push instantiator type arguments.
1235 compiler->GenerateCallRuntime(cid(), 1235 compiler->GenerateCallRuntime(deopt_id(),
1236 token_pos(), 1236 token_pos(),
1237 try_index(), 1237 try_index(),
1238 kInstantiateTypeArgumentsRuntimeEntry); 1238 kInstantiateTypeArgumentsRuntimeEntry);
1239 __ Drop(2); // Drop instantiator and uninstantiated type arguments. 1239 __ Drop(2); // Drop instantiator and uninstantiated type arguments.
1240 __ popl(result_reg); // Pop instantiated type arguments. 1240 __ popl(result_reg); // Pop instantiated type arguments.
1241 __ Bind(&type_arguments_instantiated); 1241 __ Bind(&type_arguments_instantiated);
1242 ASSERT(instantiator_reg == result_reg); 1242 ASSERT(instantiator_reg == result_reg);
1243 // 'result_reg': Instantiated type arguments. 1243 // 'result_reg': Instantiated type arguments.
1244 } 1244 }
1245 1245
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 return locs; 1405 return locs;
1406 } 1406 }
1407 1407
1408 1408
1409 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1409 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1410 Register context_value = locs()->in(0).reg(); 1410 Register context_value = locs()->in(0).reg();
1411 Register result = locs()->out().reg(); 1411 Register result = locs()->out().reg();
1412 1412
1413 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1413 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1414 __ pushl(context_value); 1414 __ pushl(context_value);
1415 compiler->GenerateCallRuntime(cid(), 1415 compiler->GenerateCallRuntime(deopt_id(),
1416 token_pos(), 1416 token_pos(),
1417 try_index(), 1417 try_index(),
1418 kCloneContextRuntimeEntry); 1418 kCloneContextRuntimeEntry);
1419 __ popl(result); // Remove argument. 1419 __ popl(result); // Remove argument.
1420 __ popl(result); // Get result (cloned context). 1420 __ popl(result); // Get result (cloned context).
1421 } 1421 }
1422 1422
1423 1423
1424 LocationSummary* CatchEntryComp::MakeLocationSummary() const { 1424 LocationSummary* CatchEntryComp::MakeLocationSummary() const {
1425 return LocationSummary::Make(0, 1425 return LocationSummary::Make(0,
(...skipping 30 matching lines...) Expand all
1456 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 1456 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1457 return summary; 1457 return summary;
1458 } 1458 }
1459 1459
1460 1460
1461 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1461 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1462 __ cmpl(ESP, 1462 __ cmpl(ESP,
1463 Address::Absolute(Isolate::Current()->stack_limit_address())); 1463 Address::Absolute(Isolate::Current()->stack_limit_address()));
1464 Label no_stack_overflow; 1464 Label no_stack_overflow;
1465 __ j(ABOVE, &no_stack_overflow); 1465 __ j(ABOVE, &no_stack_overflow);
1466 compiler->GenerateCallRuntime(cid(), 1466 compiler->GenerateCallRuntime(deopt_id(),
1467 token_pos(), 1467 token_pos(),
1468 try_index(), 1468 try_index(),
1469 kStackOverflowRuntimeEntry); 1469 kStackOverflowRuntimeEntry);
1470 __ Bind(&no_stack_overflow); 1470 __ Bind(&no_stack_overflow);
1471 } 1471 }
1472 1472
1473 1473
1474 LocationSummary* BinaryOpComp::MakeLocationSummary() const { 1474 LocationSummary* BinaryOpComp::MakeLocationSummary() const {
1475 const intptr_t kNumInputs = 2; 1475 const intptr_t kNumInputs = 2;
1476 1476
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1535 } 1535 }
1536 } 1536 }
1537 1537
1538 1538
1539 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { 1539 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
1540 Register left = comp->locs()->in(0).reg(); 1540 Register left = comp->locs()->in(0).reg();
1541 Register right = comp->locs()->in(1).reg(); 1541 Register right = comp->locs()->in(1).reg();
1542 Register result = comp->locs()->out().reg(); 1542 Register result = comp->locs()->out().reg();
1543 Register temp = comp->locs()->temp(0).reg(); 1543 Register temp = comp->locs()->temp(0).reg();
1544 ASSERT(left == result); 1544 ASSERT(left == result);
1545 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1545 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(),
1546 comp->instance_call()->token_pos(), 1546 comp->instance_call()->token_pos(),
1547 comp->instance_call()->try_index(), 1547 comp->instance_call()->try_index(),
1548 kDeoptSmiBinaryOp, 1548 kDeoptSmiBinaryOp,
1549 temp, 1549 temp,
1550 right); 1550 right);
1551 // TODO(vegorov): for many binary operations this pattern can be rearranged 1551 // TODO(vegorov): for many binary operations this pattern can be rearranged
1552 // to save one move. 1552 // to save one move.
1553 __ movl(temp, left); 1553 __ movl(temp, left);
1554 __ orl(left, right); 1554 __ orl(left, right);
1555 __ testl(left, Immediate(kSmiTagMask)); 1555 __ testl(left, Immediate(kSmiTagMask));
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1646 __ shll(left, right_temp); 1646 __ shll(left, right_temp);
1647 __ jmp(&done); 1647 __ jmp(&done);
1648 { 1648 {
1649 __ Bind(&call_method); 1649 __ Bind(&call_method);
1650 Function& target = Function::ZoneHandle( 1650 Function& target = Function::ZoneHandle(
1651 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); 1651 comp->ic_data()->GetTargetForReceiverClassId(kSmi));
1652 ASSERT(!target.IsNull()); 1652 ASSERT(!target.IsNull());
1653 const intptr_t kArgumentCount = 2; 1653 const intptr_t kArgumentCount = 2;
1654 __ pushl(temp); 1654 __ pushl(temp);
1655 __ pushl(right); 1655 __ pushl(right);
1656 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1656 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1657 comp->instance_call()->token_pos(), 1657 comp->instance_call()->token_pos(),
1658 comp->instance_call()->try_index(), 1658 comp->instance_call()->try_index(),
1659 target, 1659 target,
1660 kArgumentCount, 1660 kArgumentCount,
1661 Array::Handle()); // No argument names. 1661 Array::Handle()); // No argument names.
1662 ASSERT(result == EAX); 1662 ASSERT(result == EAX);
1663 } 1663 }
1664 __ Bind(&done); 1664 __ Bind(&done);
1665 break; 1665 break;
1666 } 1666 }
(...skipping 26 matching lines...) Expand all
1693 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi 1693 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi
1694 // receiver and a Mint or Smi argument. We fall back to the run time call if 1694 // receiver and a Mint or Smi argument. We fall back to the run time call if
1695 // both receiver and argument are Mint or if one of them is Mint and the other 1695 // both receiver and argument are Mint or if one of them is Mint and the other
1696 // is a negative Smi. 1696 // is a negative Smi.
1697 Register left = comp->locs()->in(0).reg(); 1697 Register left = comp->locs()->in(0).reg();
1698 Register right = comp->locs()->in(1).reg(); 1698 Register right = comp->locs()->in(1).reg();
1699 Register result = comp->locs()->out().reg(); 1699 Register result = comp->locs()->out().reg();
1700 Register temp = comp->locs()->temp(0).reg(); 1700 Register temp = comp->locs()->temp(0).reg();
1701 ASSERT(left == result); 1701 ASSERT(left == result);
1702 ASSERT(comp->op_kind() == Token::kBIT_AND); 1702 ASSERT(comp->op_kind() == Token::kBIT_AND);
1703 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1703 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(),
1704 comp->instance_call()->token_pos(), 1704 comp->instance_call()->token_pos(),
1705 comp->instance_call()->try_index(), 1705 comp->instance_call()->try_index(),
1706 kDeoptMintBinaryOp, 1706 kDeoptMintBinaryOp,
1707 left, 1707 left,
1708 right); 1708 right);
1709 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; 1709 Label mint_static_call, smi_static_call, non_smi, smi_smi, done;
1710 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? 1710 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi?
1711 __ j(NOT_ZERO, &non_smi); 1711 __ j(NOT_ZERO, &non_smi);
1712 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? 1712 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi?
1713 __ j(ZERO, &smi_smi); 1713 __ j(ZERO, &smi_smi);
(...skipping 27 matching lines...) Expand all
1741 1741
1742 __ Bind(&smi_static_call); 1742 __ Bind(&smi_static_call);
1743 { 1743 {
1744 Function& target = Function::ZoneHandle( 1744 Function& target = Function::ZoneHandle(
1745 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); 1745 comp->ic_data()->GetTargetForReceiverClassId(kSmi));
1746 if (target.IsNull()) { 1746 if (target.IsNull()) {
1747 __ jmp(deopt); 1747 __ jmp(deopt);
1748 } else { 1748 } else {
1749 __ pushl(left); 1749 __ pushl(left);
1750 __ pushl(right); 1750 __ pushl(right);
1751 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1751 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1752 comp->instance_call()->token_pos(), 1752 comp->instance_call()->token_pos(),
1753 comp->instance_call()->try_index(), 1753 comp->instance_call()->try_index(),
1754 target, 1754 target,
1755 comp->instance_call()->ArgumentCount(), 1755 comp->instance_call()->ArgumentCount(),
1756 comp->instance_call()->argument_names()); 1756 comp->instance_call()->argument_names());
1757 ASSERT(result == EAX); 1757 ASSERT(result == EAX);
1758 __ jmp(&done); 1758 __ jmp(&done);
1759 } 1759 }
1760 } 1760 }
1761 1761
1762 __ Bind(&mint_static_call); 1762 __ Bind(&mint_static_call);
1763 { 1763 {
1764 Function& target = Function::ZoneHandle( 1764 Function& target = Function::ZoneHandle(
1765 comp->ic_data()->GetTargetForReceiverClassId(kMint)); 1765 comp->ic_data()->GetTargetForReceiverClassId(kMint));
1766 if (target.IsNull()) { 1766 if (target.IsNull()) {
1767 __ jmp(deopt); 1767 __ jmp(deopt);
1768 } else { 1768 } else {
1769 __ pushl(left); 1769 __ pushl(left);
1770 __ pushl(right); 1770 __ pushl(right);
1771 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1771 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1772 comp->instance_call()->token_pos(), 1772 comp->instance_call()->token_pos(),
1773 comp->instance_call()->try_index(), 1773 comp->instance_call()->try_index(),
1774 target, 1774 target,
1775 comp->instance_call()->ArgumentCount(), 1775 comp->instance_call()->ArgumentCount(),
1776 comp->instance_call()->argument_names()); 1776 comp->instance_call()->argument_names());
1777 ASSERT(result == EAX); 1777 ASSERT(result == EAX);
1778 } 1778 }
1779 } 1779 }
1780 __ Bind(&done); 1780 __ Bind(&done);
1781 } 1781 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1814 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); 1814 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
1815 compiler->GenerateCall(instance_call()->token_pos(), 1815 compiler->GenerateCall(instance_call()->token_pos(),
1816 instance_call()->try_index(), 1816 instance_call()->try_index(),
1817 &label, 1817 &label,
1818 PcDescriptors::kOther); 1818 PcDescriptors::kOther);
1819 // Newly allocated object is now in the result register (RAX). 1819 // Newly allocated object is now in the result register (RAX).
1820 ASSERT(result == EAX); 1820 ASSERT(result == EAX);
1821 __ popl(right); 1821 __ popl(right);
1822 __ popl(left); 1822 __ popl(left);
1823 1823
1824 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1824 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1825 instance_call()->token_pos(), 1825 instance_call()->token_pos(),
1826 instance_call()->try_index(), 1826 instance_call()->try_index(),
1827 kDeoptDoubleBinaryOp, 1827 kDeoptDoubleBinaryOp,
1828 left, 1828 left,
1829 right); 1829 right);
1830 1830
1831 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 1831 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
1832 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 1832 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
1833 1833
1834 switch (op_kind()) { 1834 switch (op_kind()) {
(...skipping 25 matching lines...) Expand all
1860 ASSERT(ic_data.num_args_tested() == 1); 1860 ASSERT(ic_data.num_args_tested() == 1);
1861 // TODO(srdjan): Implement for more checks. 1861 // TODO(srdjan): Implement for more checks.
1862 ASSERT(ic_data.NumberOfChecks() == 1); 1862 ASSERT(ic_data.NumberOfChecks() == 1);
1863 intptr_t test_class_id; 1863 intptr_t test_class_id;
1864 Function& target = Function::Handle(); 1864 Function& target = Function::Handle();
1865 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1865 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1866 1866
1867 Register value = locs()->in(0).reg(); 1867 Register value = locs()->in(0).reg();
1868 Register result = locs()->out().reg(); 1868 Register result = locs()->out().reg();
1869 ASSERT(value == result); 1869 ASSERT(value == result);
1870 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1870 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1871 instance_call()->token_pos(), 1871 instance_call()->token_pos(),
1872 instance_call()->try_index(), 1872 instance_call()->try_index(),
1873 kDeoptUnaryOp, 1873 kDeoptUnaryOp,
1874 value); 1874 value);
1875 if (test_class_id == kSmi) { 1875 if (test_class_id == kSmi) {
1876 __ testl(value, Immediate(kSmiTagMask)); 1876 __ testl(value, Immediate(kSmiTagMask));
1877 __ j(NOT_ZERO, deopt); 1877 __ j(NOT_ZERO, deopt);
1878 switch (op_kind()) { 1878 switch (op_kind()) {
1879 case Token::kNEGATE: 1879 case Token::kNEGATE:
1880 __ negl(value); 1880 __ negl(value);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1912 1912
1913 // TODO(srdjan): Implement for more checks. 1913 // TODO(srdjan): Implement for more checks.
1914 ASSERT(ic_data.NumberOfChecks() == 1); 1914 ASSERT(ic_data.NumberOfChecks() == 1);
1915 intptr_t test_class_id; 1915 intptr_t test_class_id;
1916 Function& target = Function::Handle(); 1916 Function& target = Function::Handle();
1917 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1917 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1918 1918
1919 Register value = locs()->in(0).reg(); 1919 Register value = locs()->in(0).reg();
1920 Register result = locs()->out().reg(); 1920 Register result = locs()->out().reg();
1921 ASSERT(value == result); 1921 ASSERT(value == result);
1922 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1922 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1923 instance_call()->token_pos(), 1923 instance_call()->token_pos(),
1924 instance_call()->try_index(), 1924 instance_call()->try_index(),
1925 kDeoptUnaryOp, 1925 kDeoptUnaryOp,
1926 value); 1926 value);
1927 if (test_class_id == kDouble) { 1927 if (test_class_id == kDouble) {
1928 Register temp = locs()->temp(0).reg(); 1928 Register temp = locs()->temp(0).reg();
1929 __ testl(value, Immediate(kSmiTagMask)); 1929 __ testl(value, Immediate(kSmiTagMask));
1930 __ j(ZERO, deopt); // Smi. 1930 __ j(ZERO, deopt); // Smi.
1931 __ CompareClassId(value, kDouble, temp); 1931 __ CompareClassId(value, kDouble, temp);
1932 __ j(NOT_EQUAL, deopt); 1932 __ j(NOT_EQUAL, deopt);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1970 } 1970 }
1971 } 1971 }
1972 1972
1973 1973
1974 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1974 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1975 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; 1975 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX;
1976 Register result = locs()->out().reg(); 1976 Register result = locs()->out().reg();
1977 1977
1978 const DeoptReasonId deopt_reason = (from() == kDouble) ? 1978 const DeoptReasonId deopt_reason = (from() == kDouble) ?
1979 kDeoptDoubleToDouble : kDeoptIntegerToDouble; 1979 kDeoptDoubleToDouble : kDeoptIntegerToDouble;
1980 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1980 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1981 instance_call()->token_pos(), 1981 instance_call()->token_pos(),
1982 instance_call()->try_index(), 1982 instance_call()->try_index(),
1983 deopt_reason, 1983 deopt_reason,
1984 value); 1984 value);
1985 1985
1986 if (from() == kDouble) { 1986 if (from() == kDouble) {
1987 Register temp = locs()->temp(0).reg(); 1987 Register temp = locs()->temp(0).reg();
1988 __ testl(value, Immediate(kSmiTagMask)); 1988 __ testl(value, Immediate(kSmiTagMask));
1989 __ j(ZERO, deopt); // Deoptimize if Smi. 1989 __ j(ZERO, deopt); // Deoptimize if Smi.
1990 __ CompareClassId(value, kDouble, temp); 1990 __ CompareClassId(value, kDouble, temp);
(...skipping 24 matching lines...) Expand all
2015 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); 2015 __ movsd(FieldAddress(result, Double::value_offset()), XMM0);
2016 } 2016 }
2017 2017
2018 2018
2019 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { 2019 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const {
2020 return MakeCallSummary(); 2020 return MakeCallSummary();
2021 } 2021 }
2022 2022
2023 2023
2024 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2024 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2025 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 2025 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2026 instance_call()->token_pos(), 2026 instance_call()->token_pos(),
2027 instance_call()->try_index(), 2027 instance_call()->try_index(),
2028 kDeoptPolymorphicInstanceCallTestFail); 2028 kDeoptPolymorphicInstanceCallTestFail);
2029 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { 2029 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) {
2030 __ jmp(deopt); 2030 __ jmp(deopt);
2031 return; 2031 return;
2032 } 2032 }
2033 ASSERT(HasICData()); 2033 ASSERT(HasICData());
2034 ASSERT(ic_data()->num_args_tested() == 1); 2034 ASSERT(ic_data()->num_args_tested() == 1);
2035 Label handle_smi; 2035 Label handle_smi;
2036 Label* is_smi_label = 2036 Label* is_smi_label =
2037 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; 2037 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt;
2038 2038
2039 // Load receiver into EAX. 2039 // Load receiver into EAX.
2040 __ movl(EAX, 2040 __ movl(EAX,
2041 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); 2041 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize));
2042 __ testl(EAX, Immediate(kSmiTagMask)); 2042 __ testl(EAX, Immediate(kSmiTagMask));
2043 __ j(ZERO, is_smi_label); 2043 __ j(ZERO, is_smi_label);
2044 Label done; 2044 Label done;
2045 __ LoadClassId(EDI, EAX); 2045 __ LoadClassId(EDI, EAX);
2046 compiler->EmitTestAndCall(*ic_data(), 2046 compiler->EmitTestAndCall(*ic_data(),
2047 EDI, // Class id register. 2047 EDI, // Class id register.
2048 instance_call()->ArgumentCount(), 2048 instance_call()->ArgumentCount(),
2049 instance_call()->argument_names(), 2049 instance_call()->argument_names(),
2050 deopt, 2050 deopt,
2051 (is_smi_label == &handle_smi) ? &done : NULL, 2051 (is_smi_label == &handle_smi) ? &done : NULL,
2052 instance_call()->cid(), 2052 instance_call()->deopt_id(),
2053 instance_call()->token_pos(), 2053 instance_call()->token_pos(),
2054 instance_call()->try_index()); 2054 instance_call()->try_index());
2055 if (is_smi_label == &handle_smi) { 2055 if (is_smi_label == &handle_smi) {
2056 __ Bind(&handle_smi); 2056 __ Bind(&handle_smi);
2057 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); 2057 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi);
2058 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); 2058 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0));
2059 compiler->GenerateStaticCall(instance_call()->cid(), 2059 compiler->GenerateStaticCall(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 target, 2062 target,
2063 instance_call()->ArgumentCount(), 2063 instance_call()->ArgumentCount(),
2064 instance_call()->argument_names()); 2064 instance_call()->argument_names());
2065 } 2065 }
2066 __ Bind(&done); 2066 __ Bind(&done);
2067 } 2067 }
2068 2068
2069 2069
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2123 Register right = locs()->in(1).reg(); 2123 Register right = locs()->in(1).reg();
2124 __ cmpl(left, right); 2124 __ cmpl(left, right);
2125 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 2125 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2126 EmitBranchOnCondition(compiler, cond); 2126 EmitBranchOnCondition(compiler, cond);
2127 return; 2127 return;
2128 } 2128 }
2129 // Relational or equality. 2129 // Relational or equality.
2130 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2130 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2131 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { 2131 if (ICDataWithBothClassIds(*ic_data(), kSmi)) {
2132 EmitSmiComparisonOp(compiler, *locs(), kind(), this, 2132 EmitSmiComparisonOp(compiler, *locs(), kind(), this,
2133 cid(), token_pos(), try_index()); 2133 deopt_id(), token_pos(), try_index());
2134 return; 2134 return;
2135 } 2135 }
2136 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { 2136 if (ICDataWithBothClassIds(*ic_data(), kDouble)) {
2137 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, 2137 EmitDoubleComparisonOp(compiler, *locs(), kind(), this,
2138 cid(), token_pos(), try_index()); 2138 deopt_id(), token_pos(), try_index());
2139 return; 2139 return;
2140 } 2140 }
2141 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. 2141 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2142 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { 2142 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2143 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), 2143 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(),
2144 cid(), token_pos(), try_index()); 2144 deopt_id(), token_pos(), try_index());
2145 return; 2145 return;
2146 } 2146 }
2147 // Otherwise polymorphic dispatch? 2147 // Otherwise polymorphic dispatch?
2148 } 2148 }
2149 // Not equal is always split into '==' and negate, 2149 // Not equal is always split into '==' and negate,
2150 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; 2150 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
2151 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); 2151 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind();
2152 const String& function_name = 2152 const String& function_name =
2153 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); 2153 String::ZoneHandle(Symbols::New(Token::Str(call_kind)));
2154 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 2154 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
2155 cid(), 2155 deopt_id(),
2156 token_pos(), 2156 token_pos(),
2157 try_index()); 2157 try_index());
2158 const intptr_t kNumArguments = 2; 2158 const intptr_t kNumArguments = 2;
2159 const intptr_t kNumArgsChecked = 2; // Type-feedback. 2159 const intptr_t kNumArgsChecked = 2; // Type-feedback.
2160 compiler->GenerateInstanceCall(cid(), 2160 compiler->GenerateInstanceCall(deopt_id(),
2161 token_pos(), 2161 token_pos(),
2162 try_index(), 2162 try_index(),
2163 function_name, 2163 function_name,
2164 kNumArguments, 2164 kNumArguments,
2165 Array::ZoneHandle(), // No optional arguments. 2165 Array::ZoneHandle(), // No optional arguments.
2166 kNumArgsChecked); 2166 kNumArgsChecked);
2167 ASSERT(locs()->out().reg() == EAX); 2167 ASSERT(locs()->out().reg() == EAX);
2168 __ CompareObject(locs()->out().reg(), compiler->bool_true()); 2168 __ CompareObject(locs()->out().reg(), compiler->bool_true());
2169 EmitBranchOnCondition(compiler, branch_condition); 2169 EmitBranchOnCondition(compiler, branch_condition);
2170 } 2170 }
2171 2171
2172 } // namespace dart 2172 } // namespace dart
2173 2173
2174 #undef __ 2174 #undef __
2175 2175
2176 #endif // defined TARGET_ARCH_X64 2176 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698