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_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 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 __ 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 LocationSummary::kNoCall); | 959 LocationSummary::kNoCall); |
960 } | 960 } |
961 | 961 |
962 | 962 |
963 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 963 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
964 Register instance_reg = locs()->in(0).reg(); | 964 Register instance_reg = locs()->in(0).reg(); |
965 Register result_reg = locs()->out().reg(); | 965 Register result_reg = locs()->out().reg(); |
966 | 966 |
967 if (HasICData()) { | 967 if (HasICData()) { |
968 ASSERT(original() != NULL); | 968 ASSERT(original() != NULL); |
969 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 969 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
970 original()->token_pos(), | 970 original()->token_pos(), |
971 original()->try_index(), | 971 original()->try_index(), |
972 kDeoptInstanceGetterSameTarget, | 972 kDeoptInstanceGetterSameTarget, |
973 instance_reg); | 973 instance_reg); |
974 // Smis do not have instance fields (Smi class is always first). | 974 // Smis do not have instance fields (Smi class is always first). |
975 // Use 'result' as temporary register. | 975 // Use 'result' as temporary register. |
976 ASSERT(result_reg != instance_reg); | 976 ASSERT(result_reg != instance_reg); |
977 ASSERT(ic_data() != NULL); | 977 ASSERT(ic_data() != NULL); |
978 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 978 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
979 } | 979 } |
(...skipping 26 matching lines...) Expand all Loading... |
1006 summary->set_out(Location::RegisterLocation(EAX)); | 1006 summary->set_out(Location::RegisterLocation(EAX)); |
1007 return summary; | 1007 return summary; |
1008 } | 1008 } |
1009 | 1009 |
1010 | 1010 |
1011 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1011 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1012 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1012 ASSERT(locs()->in(0).reg() == EAX); // Value. |
1013 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 1013 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
1014 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 1014 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
1015 | 1015 |
1016 compiler->GenerateInstanceOf(cid(), | 1016 compiler->GenerateInstanceOf(deopt_id(), |
1017 token_pos(), | 1017 token_pos(), |
1018 try_index(), | 1018 try_index(), |
1019 type(), | 1019 type(), |
1020 negate_result()); | 1020 negate_result()); |
1021 ASSERT(locs()->out().reg() == EAX); | 1021 ASSERT(locs()->out().reg() == EAX); |
1022 } | 1022 } |
1023 | 1023 |
1024 | 1024 |
1025 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1025 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
1026 return MakeCallSummary(); | 1026 return MakeCallSummary(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1065 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1065 const Class& cls = Class::ZoneHandle(constructor().owner()); |
1066 Register type_arguments = locs()->in(0).reg(); | 1066 Register type_arguments = locs()->in(0).reg(); |
1067 Register instantiator_type_arguments = locs()->in(1).reg(); | 1067 Register instantiator_type_arguments = locs()->in(1).reg(); |
1068 Register result = locs()->out().reg(); | 1068 Register result = locs()->out().reg(); |
1069 | 1069 |
1070 // Push the result place holder initialized to NULL. | 1070 // Push the result place holder initialized to NULL. |
1071 __ PushObject(Object::ZoneHandle()); | 1071 __ PushObject(Object::ZoneHandle()); |
1072 __ PushObject(cls); | 1072 __ PushObject(cls); |
1073 __ pushl(type_arguments); | 1073 __ pushl(type_arguments); |
1074 __ pushl(instantiator_type_arguments); | 1074 __ pushl(instantiator_type_arguments); |
1075 compiler->GenerateCallRuntime(cid(), | 1075 compiler->GenerateCallRuntime(deopt_id(), |
1076 token_pos(), | 1076 token_pos(), |
1077 try_index(), | 1077 try_index(), |
1078 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1078 kAllocateObjectWithBoundsCheckRuntimeEntry); |
1079 // Pop instantiator type arguments, type arguments, and class. | 1079 // Pop instantiator type arguments, type arguments, and class. |
1080 // source location. | 1080 // source location. |
1081 __ Drop(3); | 1081 __ Drop(3); |
1082 __ popl(result); // Pop new instance. | 1082 __ popl(result); // Pop new instance. |
1083 } | 1083 } |
1084 | 1084 |
1085 | 1085 |
1086 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1086 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
1087 return LocationSummary::Make(1, | 1087 return LocationSummary::Make(1, |
1088 Location::RequiresRegister(), | 1088 Location::RequiresRegister(), |
1089 LocationSummary::kNoCall); | 1089 LocationSummary::kNoCall); |
1090 } | 1090 } |
1091 | 1091 |
1092 | 1092 |
1093 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1093 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1094 Register instance_reg = locs()->in(0).reg(); | 1094 Register instance_reg = locs()->in(0).reg(); |
1095 Register result_reg = locs()->out().reg(); | 1095 Register result_reg = locs()->out().reg(); |
1096 if (HasICData()) { | 1096 if (HasICData()) { |
1097 ASSERT(original() != NULL); | 1097 ASSERT(original() != NULL); |
1098 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1098 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
1099 original()->token_pos(), | 1099 original()->token_pos(), |
1100 original()->try_index(), | 1100 original()->try_index(), |
1101 kDeoptInstanceGetterSameTarget, | 1101 kDeoptInstanceGetterSameTarget, |
1102 instance_reg); | 1102 instance_reg); |
1103 // Smis do not have instance fields (Smi class is always first). | 1103 // Smis do not have instance fields (Smi class is always first). |
1104 // Use 'result' as temporary register. | 1104 // Use 'result' as temporary register. |
1105 ASSERT(result_reg != instance_reg); | 1105 ASSERT(result_reg != instance_reg); |
1106 ASSERT(ic_data() != NULL); | 1106 ASSERT(ic_data() != NULL); |
1107 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1107 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
1108 } | 1108 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1154 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1154 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
1155 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1155 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1156 Immediate(Smi::RawValue(len))); | 1156 Immediate(Smi::RawValue(len))); |
1157 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1157 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1158 __ Bind(&type_arguments_uninstantiated); | 1158 __ Bind(&type_arguments_uninstantiated); |
1159 } | 1159 } |
1160 // A runtime call to instantiate the type arguments is required. | 1160 // A runtime call to instantiate the type arguments is required. |
1161 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1161 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1162 __ PushObject(type_arguments()); | 1162 __ PushObject(type_arguments()); |
1163 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1163 __ pushl(instantiator_reg); // Push instantiator type arguments. |
1164 compiler->GenerateCallRuntime(cid(), | 1164 compiler->GenerateCallRuntime(deopt_id(), |
1165 token_pos(), | 1165 token_pos(), |
1166 try_index(), | 1166 try_index(), |
1167 kInstantiateTypeArgumentsRuntimeEntry); | 1167 kInstantiateTypeArgumentsRuntimeEntry); |
1168 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1168 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
1169 __ popl(result_reg); // Pop instantiated type arguments. | 1169 __ popl(result_reg); // Pop instantiated type arguments. |
1170 __ Bind(&type_arguments_instantiated); | 1170 __ Bind(&type_arguments_instantiated); |
1171 ASSERT(instantiator_reg == result_reg); | 1171 ASSERT(instantiator_reg == result_reg); |
1172 // 'result_reg': Instantiated type arguments. | 1172 // 'result_reg': Instantiated type arguments. |
1173 } | 1173 } |
1174 | 1174 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 return locs; | 1334 return locs; |
1335 } | 1335 } |
1336 | 1336 |
1337 | 1337 |
1338 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1338 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1339 Register context_value = locs()->in(0).reg(); | 1339 Register context_value = locs()->in(0).reg(); |
1340 Register result = locs()->out().reg(); | 1340 Register result = locs()->out().reg(); |
1341 | 1341 |
1342 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1342 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1343 __ pushl(context_value); | 1343 __ pushl(context_value); |
1344 compiler->GenerateCallRuntime(cid(), | 1344 compiler->GenerateCallRuntime(deopt_id(), |
1345 token_pos(), | 1345 token_pos(), |
1346 try_index(), | 1346 try_index(), |
1347 kCloneContextRuntimeEntry); | 1347 kCloneContextRuntimeEntry); |
1348 __ popl(result); // Remove argument. | 1348 __ popl(result); // Remove argument. |
1349 __ popl(result); // Get result (cloned context). | 1349 __ popl(result); // Get result (cloned context). |
1350 } | 1350 } |
1351 | 1351 |
1352 | 1352 |
1353 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1353 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
1354 return LocationSummary::Make(0, | 1354 return LocationSummary::Make(0, |
(...skipping 30 matching lines...) Expand all Loading... |
1385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
1386 return summary; | 1386 return summary; |
1387 } | 1387 } |
1388 | 1388 |
1389 | 1389 |
1390 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1390 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1391 __ cmpl(ESP, | 1391 __ cmpl(ESP, |
1392 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1392 Address::Absolute(Isolate::Current()->stack_limit_address())); |
1393 Label no_stack_overflow; | 1393 Label no_stack_overflow; |
1394 __ j(ABOVE, &no_stack_overflow); | 1394 __ j(ABOVE, &no_stack_overflow); |
1395 compiler->GenerateCallRuntime(cid(), | 1395 compiler->GenerateCallRuntime(deopt_id(), |
1396 token_pos(), | 1396 token_pos(), |
1397 try_index(), | 1397 try_index(), |
1398 kStackOverflowRuntimeEntry); | 1398 kStackOverflowRuntimeEntry); |
1399 __ Bind(&no_stack_overflow); | 1399 __ Bind(&no_stack_overflow); |
1400 } | 1400 } |
1401 | 1401 |
1402 | 1402 |
1403 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1403 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
1404 const intptr_t kNumInputs = 2; | 1404 const intptr_t kNumInputs = 2; |
1405 | 1405 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 } | 1464 } |
1465 } | 1465 } |
1466 | 1466 |
1467 | 1467 |
1468 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1468 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
1469 Register left = comp->locs()->in(0).reg(); | 1469 Register left = comp->locs()->in(0).reg(); |
1470 Register right = comp->locs()->in(1).reg(); | 1470 Register right = comp->locs()->in(1).reg(); |
1471 Register result = comp->locs()->out().reg(); | 1471 Register result = comp->locs()->out().reg(); |
1472 Register temp = comp->locs()->temp(0).reg(); | 1472 Register temp = comp->locs()->temp(0).reg(); |
1473 ASSERT(left == result); | 1473 ASSERT(left == result); |
1474 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1474 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
1475 comp->instance_call()->token_pos(), | 1475 comp->instance_call()->token_pos(), |
1476 comp->instance_call()->try_index(), | 1476 comp->instance_call()->try_index(), |
1477 kDeoptSmiBinaryOp, | 1477 kDeoptSmiBinaryOp, |
1478 temp, | 1478 temp, |
1479 right); | 1479 right); |
1480 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1480 // TODO(vegorov): for many binary operations this pattern can be rearranged |
1481 // to save one move. | 1481 // to save one move. |
1482 __ movl(temp, left); | 1482 __ movl(temp, left); |
1483 __ orl(left, right); | 1483 __ orl(left, right); |
1484 __ testl(left, Immediate(kSmiTagMask)); | 1484 __ testl(left, Immediate(kSmiTagMask)); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1575 __ shll(left, right_temp); | 1575 __ shll(left, right_temp); |
1576 __ jmp(&done); | 1576 __ jmp(&done); |
1577 { | 1577 { |
1578 __ Bind(&call_method); | 1578 __ Bind(&call_method); |
1579 Function& target = Function::ZoneHandle( | 1579 Function& target = Function::ZoneHandle( |
1580 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1580 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1581 ASSERT(!target.IsNull()); | 1581 ASSERT(!target.IsNull()); |
1582 const intptr_t kArgumentCount = 2; | 1582 const intptr_t kArgumentCount = 2; |
1583 __ pushl(temp); | 1583 __ pushl(temp); |
1584 __ pushl(right); | 1584 __ pushl(right); |
1585 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1585 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1586 comp->instance_call()->token_pos(), | 1586 comp->instance_call()->token_pos(), |
1587 comp->instance_call()->try_index(), | 1587 comp->instance_call()->try_index(), |
1588 target, | 1588 target, |
1589 kArgumentCount, | 1589 kArgumentCount, |
1590 Array::Handle()); // No argument names. | 1590 Array::Handle()); // No argument names. |
1591 ASSERT(result == EAX); | 1591 ASSERT(result == EAX); |
1592 } | 1592 } |
1593 __ Bind(&done); | 1593 __ Bind(&done); |
1594 break; | 1594 break; |
1595 } | 1595 } |
(...skipping 26 matching lines...) Expand all Loading... |
1622 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1622 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
1623 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1623 // receiver and a Mint or Smi argument. We fall back to the run time call if |
1624 // both receiver and argument are Mint or if one of them is Mint and the other | 1624 // both receiver and argument are Mint or if one of them is Mint and the other |
1625 // is a negative Smi. | 1625 // is a negative Smi. |
1626 Register left = comp->locs()->in(0).reg(); | 1626 Register left = comp->locs()->in(0).reg(); |
1627 Register right = comp->locs()->in(1).reg(); | 1627 Register right = comp->locs()->in(1).reg(); |
1628 Register result = comp->locs()->out().reg(); | 1628 Register result = comp->locs()->out().reg(); |
1629 Register temp = comp->locs()->temp(0).reg(); | 1629 Register temp = comp->locs()->temp(0).reg(); |
1630 ASSERT(left == result); | 1630 ASSERT(left == result); |
1631 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1631 ASSERT(comp->op_kind() == Token::kBIT_AND); |
1632 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1632 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
1633 comp->instance_call()->token_pos(), | 1633 comp->instance_call()->token_pos(), |
1634 comp->instance_call()->try_index(), | 1634 comp->instance_call()->try_index(), |
1635 kDeoptMintBinaryOp, | 1635 kDeoptMintBinaryOp, |
1636 left, | 1636 left, |
1637 right); | 1637 right); |
1638 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1638 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
1639 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1639 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
1640 __ j(NOT_ZERO, &non_smi); | 1640 __ j(NOT_ZERO, &non_smi); |
1641 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1641 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1642 __ j(ZERO, &smi_smi); | 1642 __ j(ZERO, &smi_smi); |
(...skipping 27 matching lines...) Expand all Loading... |
1670 | 1670 |
1671 __ Bind(&smi_static_call); | 1671 __ Bind(&smi_static_call); |
1672 { | 1672 { |
1673 Function& target = Function::ZoneHandle( | 1673 Function& target = Function::ZoneHandle( |
1674 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1674 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1675 if (target.IsNull()) { | 1675 if (target.IsNull()) { |
1676 __ jmp(deopt); | 1676 __ jmp(deopt); |
1677 } else { | 1677 } else { |
1678 __ pushl(left); | 1678 __ pushl(left); |
1679 __ pushl(right); | 1679 __ pushl(right); |
1680 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1680 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1681 comp->instance_call()->token_pos(), | 1681 comp->instance_call()->token_pos(), |
1682 comp->instance_call()->try_index(), | 1682 comp->instance_call()->try_index(), |
1683 target, | 1683 target, |
1684 comp->instance_call()->ArgumentCount(), | 1684 comp->instance_call()->ArgumentCount(), |
1685 comp->instance_call()->argument_names()); | 1685 comp->instance_call()->argument_names()); |
1686 ASSERT(result == EAX); | 1686 ASSERT(result == EAX); |
1687 __ jmp(&done); | 1687 __ jmp(&done); |
1688 } | 1688 } |
1689 } | 1689 } |
1690 | 1690 |
1691 __ Bind(&mint_static_call); | 1691 __ Bind(&mint_static_call); |
1692 { | 1692 { |
1693 Function& target = Function::ZoneHandle( | 1693 Function& target = Function::ZoneHandle( |
1694 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1694 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
1695 if (target.IsNull()) { | 1695 if (target.IsNull()) { |
1696 __ jmp(deopt); | 1696 __ jmp(deopt); |
1697 } else { | 1697 } else { |
1698 __ pushl(left); | 1698 __ pushl(left); |
1699 __ pushl(right); | 1699 __ pushl(right); |
1700 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1700 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
1701 comp->instance_call()->token_pos(), | 1701 comp->instance_call()->token_pos(), |
1702 comp->instance_call()->try_index(), | 1702 comp->instance_call()->try_index(), |
1703 target, | 1703 target, |
1704 comp->instance_call()->ArgumentCount(), | 1704 comp->instance_call()->ArgumentCount(), |
1705 comp->instance_call()->argument_names()); | 1705 comp->instance_call()->argument_names()); |
1706 ASSERT(result == EAX); | 1706 ASSERT(result == EAX); |
1707 } | 1707 } |
1708 } | 1708 } |
1709 __ Bind(&done); | 1709 __ Bind(&done); |
1710 } | 1710 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1743 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1743 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1744 compiler->GenerateCall(instance_call()->token_pos(), | 1744 compiler->GenerateCall(instance_call()->token_pos(), |
1745 instance_call()->try_index(), | 1745 instance_call()->try_index(), |
1746 &label, | 1746 &label, |
1747 PcDescriptors::kOther); | 1747 PcDescriptors::kOther); |
1748 // Newly allocated object is now in the result register (RAX). | 1748 // Newly allocated object is now in the result register (RAX). |
1749 ASSERT(result == EAX); | 1749 ASSERT(result == EAX); |
1750 __ popl(right); | 1750 __ popl(right); |
1751 __ popl(left); | 1751 __ popl(left); |
1752 | 1752 |
1753 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1753 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1754 instance_call()->token_pos(), | 1754 instance_call()->token_pos(), |
1755 instance_call()->try_index(), | 1755 instance_call()->try_index(), |
1756 kDeoptDoubleBinaryOp, | 1756 kDeoptDoubleBinaryOp, |
1757 left, | 1757 left, |
1758 right); | 1758 right); |
1759 | 1759 |
1760 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1760 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
1761 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1761 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
1762 | 1762 |
1763 switch (op_kind()) { | 1763 switch (op_kind()) { |
(...skipping 25 matching lines...) Expand all Loading... |
1789 ASSERT(ic_data.num_args_tested() == 1); | 1789 ASSERT(ic_data.num_args_tested() == 1); |
1790 // TODO(srdjan): Implement for more checks. | 1790 // TODO(srdjan): Implement for more checks. |
1791 ASSERT(ic_data.NumberOfChecks() == 1); | 1791 ASSERT(ic_data.NumberOfChecks() == 1); |
1792 intptr_t test_class_id; | 1792 intptr_t test_class_id; |
1793 Function& target = Function::Handle(); | 1793 Function& target = Function::Handle(); |
1794 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1794 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1795 | 1795 |
1796 Register value = locs()->in(0).reg(); | 1796 Register value = locs()->in(0).reg(); |
1797 Register result = locs()->out().reg(); | 1797 Register result = locs()->out().reg(); |
1798 ASSERT(value == result); | 1798 ASSERT(value == result); |
1799 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1799 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1800 instance_call()->token_pos(), | 1800 instance_call()->token_pos(), |
1801 instance_call()->try_index(), | 1801 instance_call()->try_index(), |
1802 kDeoptUnaryOp, | 1802 kDeoptUnaryOp, |
1803 value); | 1803 value); |
1804 if (test_class_id == kSmi) { | 1804 if (test_class_id == kSmi) { |
1805 __ testl(value, Immediate(kSmiTagMask)); | 1805 __ testl(value, Immediate(kSmiTagMask)); |
1806 __ j(NOT_ZERO, deopt); | 1806 __ j(NOT_ZERO, deopt); |
1807 switch (op_kind()) { | 1807 switch (op_kind()) { |
1808 case Token::kNEGATE: | 1808 case Token::kNEGATE: |
1809 __ negl(value); | 1809 __ negl(value); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1841 | 1841 |
1842 // TODO(srdjan): Implement for more checks. | 1842 // TODO(srdjan): Implement for more checks. |
1843 ASSERT(ic_data.NumberOfChecks() == 1); | 1843 ASSERT(ic_data.NumberOfChecks() == 1); |
1844 intptr_t test_class_id; | 1844 intptr_t test_class_id; |
1845 Function& target = Function::Handle(); | 1845 Function& target = Function::Handle(); |
1846 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1846 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1847 | 1847 |
1848 Register value = locs()->in(0).reg(); | 1848 Register value = locs()->in(0).reg(); |
1849 Register result = locs()->out().reg(); | 1849 Register result = locs()->out().reg(); |
1850 ASSERT(value == result); | 1850 ASSERT(value == result); |
1851 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1851 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1852 instance_call()->token_pos(), | 1852 instance_call()->token_pos(), |
1853 instance_call()->try_index(), | 1853 instance_call()->try_index(), |
1854 kDeoptUnaryOp, | 1854 kDeoptUnaryOp, |
1855 value); | 1855 value); |
1856 if (test_class_id == kDouble) { | 1856 if (test_class_id == kDouble) { |
1857 Register temp = locs()->temp(0).reg(); | 1857 Register temp = locs()->temp(0).reg(); |
1858 __ testl(value, Immediate(kSmiTagMask)); | 1858 __ testl(value, Immediate(kSmiTagMask)); |
1859 __ j(ZERO, deopt); // Smi. | 1859 __ j(ZERO, deopt); // Smi. |
1860 __ CompareClassId(value, kDouble, temp); | 1860 __ CompareClassId(value, kDouble, temp); |
1861 __ j(NOT_EQUAL, deopt); | 1861 __ j(NOT_EQUAL, deopt); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1899 } | 1899 } |
1900 } | 1900 } |
1901 | 1901 |
1902 | 1902 |
1903 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1903 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1904 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | 1904 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; |
1905 Register result = locs()->out().reg(); | 1905 Register result = locs()->out().reg(); |
1906 | 1906 |
1907 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1907 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
1908 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1908 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1909 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1909 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1910 instance_call()->token_pos(), | 1910 instance_call()->token_pos(), |
1911 instance_call()->try_index(), | 1911 instance_call()->try_index(), |
1912 deopt_reason, | 1912 deopt_reason, |
1913 value); | 1913 value); |
1914 | 1914 |
1915 if (from() == kDouble) { | 1915 if (from() == kDouble) { |
1916 Register temp = locs()->temp(0).reg(); | 1916 Register temp = locs()->temp(0).reg(); |
1917 __ testl(value, Immediate(kSmiTagMask)); | 1917 __ testl(value, Immediate(kSmiTagMask)); |
1918 __ j(ZERO, deopt); // Deoptimize if Smi. | 1918 __ j(ZERO, deopt); // Deoptimize if Smi. |
1919 __ CompareClassId(value, kDouble, temp); | 1919 __ CompareClassId(value, kDouble, temp); |
(...skipping 24 matching lines...) Expand all Loading... |
1944 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1944 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
1945 } | 1945 } |
1946 | 1946 |
1947 | 1947 |
1948 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1948 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
1949 return MakeCallSummary(); | 1949 return MakeCallSummary(); |
1950 } | 1950 } |
1951 | 1951 |
1952 | 1952 |
1953 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1953 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1954 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1954 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1955 instance_call()->token_pos(), | 1955 instance_call()->token_pos(), |
1956 instance_call()->try_index(), | 1956 instance_call()->try_index(), |
1957 kDeoptPolymorphicInstanceCallTestFail); | 1957 kDeoptPolymorphicInstanceCallTestFail); |
1958 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1958 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
1959 __ jmp(deopt); | 1959 __ jmp(deopt); |
1960 return; | 1960 return; |
1961 } | 1961 } |
1962 ASSERT(HasICData()); | 1962 ASSERT(HasICData()); |
1963 ASSERT(ic_data()->num_args_tested() == 1); | 1963 ASSERT(ic_data()->num_args_tested() == 1); |
1964 Label handle_smi; | 1964 Label handle_smi; |
1965 Label* is_smi_label = | 1965 Label* is_smi_label = |
1966 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1966 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
1967 | 1967 |
1968 // Load receiver into EAX. | 1968 // Load receiver into EAX. |
1969 __ movl(EAX, | 1969 __ movl(EAX, |
1970 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1970 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
1971 __ testl(EAX, Immediate(kSmiTagMask)); | 1971 __ testl(EAX, Immediate(kSmiTagMask)); |
1972 __ j(ZERO, is_smi_label); | 1972 __ j(ZERO, is_smi_label); |
1973 Label done; | 1973 Label done; |
1974 __ LoadClassId(EDI, EAX); | 1974 __ LoadClassId(EDI, EAX); |
1975 compiler->EmitTestAndCall(*ic_data(), | 1975 compiler->EmitTestAndCall(*ic_data(), |
1976 EDI, // Class id register. | 1976 EDI, // Class id register. |
1977 instance_call()->ArgumentCount(), | 1977 instance_call()->ArgumentCount(), |
1978 instance_call()->argument_names(), | 1978 instance_call()->argument_names(), |
1979 deopt, | 1979 deopt, |
1980 (is_smi_label == &handle_smi) ? &done : NULL, | 1980 (is_smi_label == &handle_smi) ? &done : NULL, |
1981 instance_call()->cid(), | 1981 instance_call()->deopt_id(), |
1982 instance_call()->token_pos(), | 1982 instance_call()->token_pos(), |
1983 instance_call()->try_index()); | 1983 instance_call()->try_index()); |
1984 if (is_smi_label == &handle_smi) { | 1984 if (is_smi_label == &handle_smi) { |
1985 __ Bind(&handle_smi); | 1985 __ Bind(&handle_smi); |
1986 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1986 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
1987 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1987 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
1988 compiler->GenerateStaticCall(instance_call()->cid(), | 1988 compiler->GenerateStaticCall(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 target, | 1991 target, |
1992 instance_call()->ArgumentCount(), | 1992 instance_call()->ArgumentCount(), |
1993 instance_call()->argument_names()); | 1993 instance_call()->argument_names()); |
1994 } | 1994 } |
1995 __ Bind(&done); | 1995 __ Bind(&done); |
1996 } | 1996 } |
1997 | 1997 |
1998 | 1998 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2052 Register right = locs()->in(1).reg(); | 2052 Register right = locs()->in(1).reg(); |
2053 __ cmpl(left, right); | 2053 __ cmpl(left, right); |
2054 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 2054 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
2055 EmitBranchOnCondition(compiler, cond); | 2055 EmitBranchOnCondition(compiler, cond); |
2056 return; | 2056 return; |
2057 } | 2057 } |
2058 // Relational or equality. | 2058 // Relational or equality. |
2059 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2059 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
2060 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { | 2060 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { |
2061 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2061 EmitSmiComparisonOp(compiler, *locs(), kind(), this, |
2062 cid(), token_pos(), try_index()); | 2062 deopt_id(), token_pos(), try_index()); |
2063 return; | 2063 return; |
2064 } | 2064 } |
2065 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2065 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { |
2066 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2066 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, |
2067 cid(), token_pos(), try_index()); | 2067 deopt_id(), token_pos(), try_index()); |
2068 return; | 2068 return; |
2069 } | 2069 } |
2070 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2070 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
2071 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2071 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
2072 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2072 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), |
2073 cid(), token_pos(), try_index()); | 2073 deopt_id(), token_pos(), try_index()); |
2074 return; | 2074 return; |
2075 } | 2075 } |
2076 // Otherwise polymorphic dispatch? | 2076 // Otherwise polymorphic dispatch? |
2077 } | 2077 } |
2078 // Not equal is always split into '==' and negate, | 2078 // Not equal is always split into '==' and negate, |
2079 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 2079 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
2080 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); | 2080 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); |
2081 const String& function_name = | 2081 const String& function_name = |
2082 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); | 2082 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); |
2083 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 2083 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
2084 cid(), | 2084 deopt_id(), |
2085 token_pos(), | 2085 token_pos(), |
2086 try_index()); | 2086 try_index()); |
2087 const intptr_t kNumArguments = 2; | 2087 const intptr_t kNumArguments = 2; |
2088 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 2088 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
2089 compiler->GenerateInstanceCall(cid(), | 2089 compiler->GenerateInstanceCall(deopt_id(), |
2090 token_pos(), | 2090 token_pos(), |
2091 try_index(), | 2091 try_index(), |
2092 function_name, | 2092 function_name, |
2093 kNumArguments, | 2093 kNumArguments, |
2094 Array::ZoneHandle(), // No optional arguments. | 2094 Array::ZoneHandle(), // No optional arguments. |
2095 kNumArgsChecked); | 2095 kNumArgsChecked); |
2096 ASSERT(locs()->out().reg() == EAX); | 2096 ASSERT(locs()->out().reg() == EAX); |
2097 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2097 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
2098 EmitBranchOnCondition(compiler, branch_condition); | 2098 EmitBranchOnCondition(compiler, branch_condition); |
2099 } | 2099 } |
2100 | 2100 |
2101 } // namespace dart | 2101 } // namespace dart |
2102 | 2102 |
2103 #undef __ | 2103 #undef __ |
2104 | 2104 |
2105 #endif // defined TARGET_ARCH_X64 | 2105 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |