OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 break; | 246 break; |
247 case kStack: | 247 case kStack: |
248 __ push(reg); | 248 __ push(reg); |
249 break; | 249 break; |
250 } | 250 } |
251 break; | 251 break; |
252 | 252 |
253 case Expression::kTest: | 253 case Expression::kTest: |
254 // For simplicity we always test the accumulator register. | 254 // For simplicity we always test the accumulator register. |
255 if (!reg.is(result_register())) __ movq(result_register(), reg); | 255 if (!reg.is(result_register())) __ movq(result_register(), reg); |
256 DoTest(context); | 256 DoTest(true_label_, false_label_, NULL); |
257 break; | |
258 | |
259 case Expression::kValueTest: | |
260 case Expression::kTestValue: | |
261 if (!reg.is(result_register())) __ movq(result_register(), reg); | |
262 switch (location_) { | |
263 case kAccumulator: | |
264 break; | |
265 case kStack: | |
266 __ push(result_register()); | |
267 break; | |
268 } | |
269 DoTest(context); | |
270 break; | 257 break; |
271 } | 258 } |
272 } | 259 } |
273 | 260 |
274 | 261 |
275 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 262 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
276 switch (context) { | 263 switch (context) { |
277 case Expression::kUninitialized: | 264 case Expression::kUninitialized: |
278 UNREACHABLE(); | 265 UNREACHABLE(); |
279 case Expression::kEffect: | 266 case Expression::kEffect: |
280 // Nothing to do. | 267 // Nothing to do. |
281 break; | 268 break; |
282 case Expression::kValue: { | 269 case Expression::kValue: { |
283 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); | 270 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
284 switch (location_) { | 271 switch (location_) { |
285 case kAccumulator: | 272 case kAccumulator: |
286 __ movq(result_register(), slot_operand); | 273 __ movq(result_register(), slot_operand); |
287 break; | 274 break; |
288 case kStack: | 275 case kStack: |
289 // Memory operands can be pushed directly. | 276 // Memory operands can be pushed directly. |
290 __ push(slot_operand); | 277 __ push(slot_operand); |
291 break; | 278 break; |
292 } | 279 } |
293 break; | 280 break; |
294 } | 281 } |
295 | 282 |
296 case Expression::kTest: | 283 case Expression::kTest: |
297 Move(result_register(), slot); | 284 Move(result_register(), slot); |
298 DoTest(context); | 285 DoTest(true_label_, false_label_, NULL); |
299 break; | |
300 | |
301 case Expression::kValueTest: | |
302 case Expression::kTestValue: | |
303 Move(result_register(), slot); | |
304 switch (location_) { | |
305 case kAccumulator: | |
306 break; | |
307 case kStack: | |
308 __ push(result_register()); | |
309 break; | |
310 } | |
311 DoTest(context); | |
312 break; | 286 break; |
313 } | 287 } |
314 } | 288 } |
315 | 289 |
316 | 290 |
317 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 291 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
318 switch (context) { | 292 switch (context) { |
319 case Expression::kUninitialized: | 293 case Expression::kUninitialized: |
320 UNREACHABLE(); | 294 UNREACHABLE(); |
321 case Expression::kEffect: | 295 case Expression::kEffect: |
322 // Nothing to do. | 296 // Nothing to do. |
323 break; | 297 break; |
324 case Expression::kValue: | 298 case Expression::kValue: |
325 switch (location_) { | 299 switch (location_) { |
326 case kAccumulator: | 300 case kAccumulator: |
327 __ Move(result_register(), lit->handle()); | 301 __ Move(result_register(), lit->handle()); |
328 break; | 302 break; |
329 case kStack: | 303 case kStack: |
330 __ Push(lit->handle()); | 304 __ Push(lit->handle()); |
331 break; | 305 break; |
332 } | 306 } |
333 break; | 307 break; |
334 | 308 |
335 case Expression::kTest: | 309 case Expression::kTest: |
336 __ Move(result_register(), lit->handle()); | 310 __ Move(result_register(), lit->handle()); |
337 DoTest(context); | 311 DoTest(true_label_, false_label_, NULL); |
338 break; | |
339 | |
340 case Expression::kValueTest: | |
341 case Expression::kTestValue: | |
342 __ Move(result_register(), lit->handle()); | |
343 switch (location_) { | |
344 case kAccumulator: | |
345 break; | |
346 case kStack: | |
347 __ push(result_register()); | |
348 break; | |
349 } | |
350 DoTest(context); | |
351 break; | 312 break; |
352 } | 313 } |
353 } | 314 } |
354 | 315 |
355 | 316 |
356 void FullCodeGenerator::ApplyTOS(Expression::Context context) { | 317 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
357 switch (context) { | 318 switch (context) { |
358 case Expression::kUninitialized: | 319 case Expression::kUninitialized: |
359 UNREACHABLE(); | 320 UNREACHABLE(); |
360 | 321 |
361 case Expression::kEffect: | 322 case Expression::kEffect: |
362 __ Drop(1); | 323 __ Drop(1); |
363 break; | 324 break; |
364 | 325 |
365 case Expression::kValue: | 326 case Expression::kValue: |
366 switch (location_) { | 327 switch (location_) { |
367 case kAccumulator: | 328 case kAccumulator: |
368 __ pop(result_register()); | 329 __ pop(result_register()); |
369 break; | 330 break; |
370 case kStack: | 331 case kStack: |
371 break; | 332 break; |
372 } | 333 } |
373 break; | 334 break; |
374 | 335 |
375 case Expression::kTest: | 336 case Expression::kTest: |
376 __ pop(result_register()); | 337 __ pop(result_register()); |
377 DoTest(context); | 338 DoTest(true_label_, false_label_, NULL); |
378 break; | |
379 | |
380 case Expression::kValueTest: | |
381 case Expression::kTestValue: | |
382 switch (location_) { | |
383 case kAccumulator: | |
384 __ pop(result_register()); | |
385 break; | |
386 case kStack: | |
387 __ movq(result_register(), Operand(rsp, 0)); | |
388 break; | |
389 } | |
390 DoTest(context); | |
391 break; | 339 break; |
392 } | 340 } |
393 } | 341 } |
394 | 342 |
395 | 343 |
396 void FullCodeGenerator::DropAndApply(int count, | 344 void FullCodeGenerator::DropAndApply(int count, |
397 Expression::Context context, | 345 Expression::Context context, |
398 Register reg) { | 346 Register reg) { |
399 ASSERT(count > 0); | 347 ASSERT(count > 0); |
400 ASSERT(!reg.is(rsp)); | 348 ASSERT(!reg.is(rsp)); |
(...skipping 14 matching lines...) Expand all Loading... |
415 case kStack: | 363 case kStack: |
416 if (count > 1) __ Drop(count - 1); | 364 if (count > 1) __ Drop(count - 1); |
417 __ movq(Operand(rsp, 0), reg); | 365 __ movq(Operand(rsp, 0), reg); |
418 break; | 366 break; |
419 } | 367 } |
420 break; | 368 break; |
421 | 369 |
422 case Expression::kTest: | 370 case Expression::kTest: |
423 __ Drop(count); | 371 __ Drop(count); |
424 if (!reg.is(result_register())) __ movq(result_register(), reg); | 372 if (!reg.is(result_register())) __ movq(result_register(), reg); |
425 DoTest(context); | 373 DoTest(true_label_, false_label_, NULL); |
426 break; | |
427 | |
428 case Expression::kValueTest: | |
429 case Expression::kTestValue: | |
430 switch (location_) { | |
431 case kAccumulator: | |
432 __ Drop(count); | |
433 if (!reg.is(result_register())) __ movq(result_register(), reg); | |
434 break; | |
435 case kStack: | |
436 if (count > 1) __ Drop(count - 1); | |
437 __ movq(result_register(), reg); | |
438 __ movq(Operand(rsp, 0), result_register()); | |
439 break; | |
440 } | |
441 DoTest(context); | |
442 break; | 374 break; |
443 } | 375 } |
444 } | 376 } |
445 | 377 |
446 | 378 |
447 void FullCodeGenerator::PrepareTest(Label* materialize_true, | 379 void FullCodeGenerator::PrepareTest(Label* materialize_true, |
448 Label* materialize_false, | 380 Label* materialize_false, |
449 Label** if_true, | 381 Label** if_true, |
450 Label** if_false) { | 382 Label** if_false) { |
451 switch (context_) { | 383 switch (context_) { |
452 case Expression::kUninitialized: | 384 case Expression::kUninitialized: |
453 UNREACHABLE(); | 385 UNREACHABLE(); |
454 break; | 386 break; |
455 case Expression::kEffect: | 387 case Expression::kEffect: |
456 // In an effect context, the true and the false case branch to the | 388 // In an effect context, the true and the false case branch to the |
457 // same label. | 389 // same label. |
458 *if_true = *if_false = materialize_true; | 390 *if_true = *if_false = materialize_true; |
459 break; | 391 break; |
460 case Expression::kValue: | 392 case Expression::kValue: |
461 *if_true = materialize_true; | 393 *if_true = materialize_true; |
462 *if_false = materialize_false; | 394 *if_false = materialize_false; |
463 break; | 395 break; |
464 case Expression::kTest: | 396 case Expression::kTest: |
465 *if_true = true_label_; | 397 *if_true = true_label_; |
466 *if_false = false_label_; | 398 *if_false = false_label_; |
467 break; | 399 break; |
468 case Expression::kValueTest: | |
469 *if_true = materialize_true; | |
470 *if_false = false_label_; | |
471 break; | |
472 case Expression::kTestValue: | |
473 *if_true = true_label_; | |
474 *if_false = materialize_false; | |
475 break; | |
476 } | 400 } |
477 } | 401 } |
478 | 402 |
479 | 403 |
480 void FullCodeGenerator::Apply(Expression::Context context, | 404 void FullCodeGenerator::Apply(Expression::Context context, |
481 Label* materialize_true, | 405 Label* materialize_true, |
482 Label* materialize_false) { | 406 Label* materialize_false) { |
483 switch (context) { | 407 switch (context) { |
484 case Expression::kUninitialized: | 408 case Expression::kUninitialized: |
485 | 409 |
(...skipping 19 matching lines...) Expand all Loading... |
505 __ bind(materialize_false); | 429 __ bind(materialize_false); |
506 __ Push(Factory::false_value()); | 430 __ Push(Factory::false_value()); |
507 break; | 431 break; |
508 } | 432 } |
509 __ bind(&done); | 433 __ bind(&done); |
510 break; | 434 break; |
511 } | 435 } |
512 | 436 |
513 case Expression::kTest: | 437 case Expression::kTest: |
514 break; | 438 break; |
515 | |
516 case Expression::kValueTest: | |
517 __ bind(materialize_true); | |
518 switch (location_) { | |
519 case kAccumulator: | |
520 __ Move(result_register(), Factory::true_value()); | |
521 break; | |
522 case kStack: | |
523 __ Push(Factory::true_value()); | |
524 break; | |
525 } | |
526 __ jmp(true_label_); | |
527 break; | |
528 | |
529 case Expression::kTestValue: | |
530 __ bind(materialize_false); | |
531 switch (location_) { | |
532 case kAccumulator: | |
533 __ Move(result_register(), Factory::false_value()); | |
534 break; | |
535 case kStack: | |
536 __ Push(Factory::false_value()); | |
537 break; | |
538 } | |
539 __ jmp(false_label_); | |
540 break; | |
541 } | 439 } |
542 } | 440 } |
543 | 441 |
544 | 442 |
545 // Convert constant control flow (true or false) to the result expected for | 443 // Convert constant control flow (true or false) to the result expected for |
546 // a given expression context. | 444 // a given expression context. |
547 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { | 445 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { |
548 switch (context) { | 446 switch (context) { |
549 case Expression::kUninitialized: | 447 case Expression::kUninitialized: |
550 UNREACHABLE(); | 448 UNREACHABLE(); |
551 break; | 449 break; |
552 case Expression::kEffect: | 450 case Expression::kEffect: |
553 break; | 451 break; |
554 case Expression::kValue: { | 452 case Expression::kValue: { |
555 Heap::RootListIndex value_root_index = | 453 Heap::RootListIndex value_root_index = |
556 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 454 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
557 switch (location_) { | 455 switch (location_) { |
558 case kAccumulator: | 456 case kAccumulator: |
559 __ LoadRoot(result_register(), value_root_index); | 457 __ LoadRoot(result_register(), value_root_index); |
560 break; | 458 break; |
561 case kStack: | 459 case kStack: |
562 __ PushRoot(value_root_index); | 460 __ PushRoot(value_root_index); |
563 break; | 461 break; |
564 } | 462 } |
565 break; | 463 break; |
566 } | 464 } |
567 case Expression::kTest: | 465 case Expression::kTest: |
568 __ jmp(flag ? true_label_ : false_label_); | 466 __ jmp(flag ? true_label_ : false_label_); |
569 break; | 467 break; |
570 case Expression::kTestValue: | |
571 switch (location_) { | |
572 case kAccumulator: | |
573 // If value is false it's needed. | |
574 if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); | |
575 break; | |
576 case kStack: | |
577 // If value is false it's needed. | |
578 if (!flag) __ PushRoot(Heap::kFalseValueRootIndex); | |
579 break; | |
580 } | |
581 __ jmp(flag ? true_label_ : false_label_); | |
582 break; | |
583 case Expression::kValueTest: | |
584 switch (location_) { | |
585 case kAccumulator: | |
586 // If value is true it's needed. | |
587 if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); | |
588 break; | |
589 case kStack: | |
590 // If value is true it's needed. | |
591 if (flag) __ PushRoot(Heap::kTrueValueRootIndex); | |
592 break; | |
593 } | |
594 __ jmp(flag ? true_label_ : false_label_); | |
595 break; | |
596 } | 468 } |
597 } | 469 } |
598 | 470 |
599 | 471 |
600 void FullCodeGenerator::DoTest(Expression::Context context) { | 472 void FullCodeGenerator::DoTest(Label* if_true, |
601 // The value to test is in the accumulator. If the value might be needed | 473 Label* if_false, |
602 // on the stack (value/test and test/value contexts with a stack location | 474 Label* fall_through) { |
603 // desired), then the value is already duplicated on the stack. | |
604 ASSERT_NE(NULL, true_label_); | |
605 ASSERT_NE(NULL, false_label_); | |
606 | |
607 // In value/test and test/value expression contexts with stack as the | |
608 // desired location, there is already an extra value on the stack. Use a | |
609 // label to discard it if unneeded. | |
610 Label discard; | |
611 Label* if_true = true_label_; | |
612 Label* if_false = false_label_; | |
613 switch (context) { | |
614 case Expression::kUninitialized: | |
615 case Expression::kEffect: | |
616 case Expression::kValue: | |
617 UNREACHABLE(); | |
618 case Expression::kTest: | |
619 break; | |
620 case Expression::kValueTest: | |
621 switch (location_) { | |
622 case kAccumulator: | |
623 break; | |
624 case kStack: | |
625 if_false = &discard; | |
626 break; | |
627 } | |
628 break; | |
629 case Expression::kTestValue: | |
630 switch (location_) { | |
631 case kAccumulator: | |
632 break; | |
633 case kStack: | |
634 if_true = &discard; | |
635 break; | |
636 } | |
637 break; | |
638 } | |
639 | |
640 // Emit the inlined tests assumed by the stub. | 475 // Emit the inlined tests assumed by the stub. |
641 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); | 476 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); |
642 __ j(equal, if_false); | 477 __ j(equal, if_false); |
643 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); | 478 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); |
644 __ j(equal, if_true); | 479 __ j(equal, if_true); |
645 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); | 480 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); |
646 __ j(equal, if_false); | 481 __ j(equal, if_false); |
647 ASSERT_EQ(0, kSmiTag); | 482 ASSERT_EQ(0, kSmiTag); |
648 __ SmiCompare(result_register(), Smi::FromInt(0)); | 483 __ SmiCompare(result_register(), Smi::FromInt(0)); |
649 __ j(equal, if_false); | 484 __ j(equal, if_false); |
650 Condition is_smi = masm_->CheckSmi(result_register()); | 485 Condition is_smi = masm_->CheckSmi(result_register()); |
651 __ j(is_smi, if_true); | 486 __ j(is_smi, if_true); |
652 | 487 |
653 // Save a copy of the value if it may be needed and isn't already saved. | |
654 switch (context) { | |
655 case Expression::kUninitialized: | |
656 case Expression::kEffect: | |
657 case Expression::kValue: | |
658 UNREACHABLE(); | |
659 case Expression::kTest: | |
660 break; | |
661 case Expression::kValueTest: | |
662 switch (location_) { | |
663 case kAccumulator: | |
664 __ push(result_register()); | |
665 break; | |
666 case kStack: | |
667 break; | |
668 } | |
669 break; | |
670 case Expression::kTestValue: | |
671 switch (location_) { | |
672 case kAccumulator: | |
673 __ push(result_register()); | |
674 break; | |
675 case kStack: | |
676 break; | |
677 } | |
678 break; | |
679 } | |
680 | |
681 // Call the ToBoolean stub for all other cases. | 488 // Call the ToBoolean stub for all other cases. |
682 ToBooleanStub stub; | 489 ToBooleanStub stub; |
683 __ push(result_register()); | 490 __ push(result_register()); |
684 __ CallStub(&stub); | 491 __ CallStub(&stub); |
685 __ testq(rax, rax); | 492 __ testq(rax, rax); |
686 | 493 |
687 // The stub returns nonzero for true. Complete based on the context. | 494 // The stub returns nonzero for true. |
688 switch (context) { | 495 Split(not_zero, if_true, if_false, fall_through); |
689 case Expression::kUninitialized: | 496 } |
690 case Expression::kEffect: | |
691 case Expression::kValue: | |
692 UNREACHABLE(); | |
693 | 497 |
694 case Expression::kTest: | |
695 __ j(not_zero, true_label_); | |
696 __ jmp(false_label_); | |
697 break; | |
698 | 498 |
699 case Expression::kValueTest: | 499 void FullCodeGenerator::Split(Condition cc, |
700 switch (location_) { | 500 Label* if_true, |
701 case kAccumulator: | 501 Label* if_false, |
702 __ j(zero, &discard); | 502 Label* fall_through) { |
703 __ pop(result_register()); | 503 if (if_false == fall_through) { |
704 __ jmp(true_label_); | 504 __ j(cc, if_true); |
705 break; | 505 } else if (if_true == fall_through) { |
706 case kStack: | 506 __ j(NegateCondition(cc), if_false); |
707 __ j(not_zero, true_label_); | 507 } else { |
708 break; | 508 __ j(cc, if_true); |
709 } | 509 __ jmp(if_false); |
710 __ bind(&discard); | |
711 __ Drop(1); | |
712 __ jmp(false_label_); | |
713 break; | |
714 | |
715 case Expression::kTestValue: | |
716 switch (location_) { | |
717 case kAccumulator: | |
718 __ j(not_zero, &discard); | |
719 __ pop(result_register()); | |
720 __ jmp(false_label_); | |
721 break; | |
722 case kStack: | |
723 __ j(zero, false_label_); | |
724 break; | |
725 } | |
726 __ bind(&discard); | |
727 __ Drop(1); | |
728 __ jmp(true_label_); | |
729 break; | |
730 } | 510 } |
731 } | 511 } |
732 | 512 |
733 | 513 |
734 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 514 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
735 switch (slot->type()) { | 515 switch (slot->type()) { |
736 case Slot::PARAMETER: | 516 case Slot::PARAMETER: |
737 case Slot::LOCAL: | 517 case Slot::LOCAL: |
738 return Operand(rbp, SlotOffset(slot)); | 518 return Operand(rbp, SlotOffset(slot)); |
739 case Slot::CONTEXT: { | 519 case Slot::CONTEXT: { |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1199 Comment cmnt(masm_, "[ RegExpLiteral"); | 979 Comment cmnt(masm_, "[ RegExpLiteral"); |
1200 Label materialized; | 980 Label materialized; |
1201 // Registers will be used as follows: | 981 // Registers will be used as follows: |
1202 // rdi = JS function. | 982 // rdi = JS function. |
1203 // rcx = literals array. | 983 // rcx = literals array. |
1204 // rbx = regexp literal. | 984 // rbx = regexp literal. |
1205 // rax = regexp literal clone. | 985 // rax = regexp literal clone. |
1206 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 986 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1207 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 987 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
1208 int literal_offset = | 988 int literal_offset = |
1209 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 989 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
1210 __ movq(rbx, FieldOperand(rcx, literal_offset)); | 990 __ movq(rbx, FieldOperand(rcx, literal_offset)); |
1211 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 991 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
1212 __ j(not_equal, &materialized); | 992 __ j(not_equal, &materialized); |
1213 | 993 |
1214 // Create regexp literal using runtime function | 994 // Create regexp literal using runtime function |
1215 // Result will be in rax. | 995 // Result will be in rax. |
1216 __ push(rcx); | 996 __ push(rcx); |
1217 __ Push(Smi::FromInt(expr->literal_index())); | 997 __ Push(Smi::FromInt(expr->literal_index())); |
1218 __ Push(expr->pattern()); | 998 __ Push(expr->pattern()); |
1219 __ Push(expr->flags()); | 999 __ Push(expr->flags()); |
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1980 ASSERT(args->length() == 1); | 1760 ASSERT(args->length() == 1); |
1981 | 1761 |
1982 VisitForValue(args->at(0), kAccumulator); | 1762 VisitForValue(args->at(0), kAccumulator); |
1983 | 1763 |
1984 Label materialize_true, materialize_false; | 1764 Label materialize_true, materialize_false; |
1985 Label* if_true = NULL; | 1765 Label* if_true = NULL; |
1986 Label* if_false = NULL; | 1766 Label* if_false = NULL; |
1987 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1767 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
1988 | 1768 |
1989 Condition positive_smi = __ CheckPositiveSmi(rax); | 1769 Condition positive_smi = __ CheckPositiveSmi(rax); |
1990 __ j(positive_smi, if_true); | 1770 Split(positive_smi, if_true, if_false, NULL); |
1991 __ jmp(if_false); | |
1992 | 1771 |
1993 Apply(context_, if_true, if_false); | 1772 Apply(context_, if_true, if_false); |
1994 } | 1773 } |
1995 | 1774 |
1996 | 1775 |
1997 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { | 1776 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { |
1998 ASSERT(args->length() == 1); | 1777 ASSERT(args->length() == 1); |
1999 | 1778 |
2000 VisitForValue(args->at(0), kAccumulator); | 1779 VisitForValue(args->at(0), kAccumulator); |
2001 | 1780 |
2002 Label materialize_true, materialize_false; | 1781 Label materialize_true, materialize_false; |
2003 Label* if_true = NULL; | 1782 Label* if_true = NULL; |
2004 Label* if_false = NULL; | 1783 Label* if_false = NULL; |
2005 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1784 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2006 | 1785 |
2007 __ JumpIfSmi(rax, if_false); | 1786 __ JumpIfSmi(rax, if_false); |
2008 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 1787 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
2009 __ j(equal, if_true); | 1788 __ j(equal, if_true); |
2010 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1789 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
2011 // Undetectable objects behave like undefined when tested with typeof. | 1790 // Undetectable objects behave like undefined when tested with typeof. |
2012 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 1791 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
2013 Immediate(1 << Map::kIsUndetectable)); | 1792 Immediate(1 << Map::kIsUndetectable)); |
2014 __ j(not_zero, if_false); | 1793 __ j(not_zero, if_false); |
2015 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 1794 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
2016 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); | 1795 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); |
2017 __ j(below, if_false); | 1796 __ j(below, if_false); |
2018 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); | 1797 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); |
2019 __ j(below_equal, if_true); | 1798 Split(below_equal, if_true, if_false, NULL); |
2020 __ jmp(if_false); | |
2021 | 1799 |
2022 Apply(context_, if_true, if_false); | 1800 Apply(context_, if_true, if_false); |
2023 } | 1801 } |
2024 | 1802 |
2025 | 1803 |
2026 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { | 1804 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { |
2027 ASSERT(args->length() == 1); | 1805 ASSERT(args->length() == 1); |
2028 | 1806 |
2029 VisitForValue(args->at(0), kAccumulator); | 1807 VisitForValue(args->at(0), kAccumulator); |
2030 | 1808 |
2031 Label materialize_true, materialize_false; | 1809 Label materialize_true, materialize_false; |
2032 Label* if_true = NULL; | 1810 Label* if_true = NULL; |
2033 Label* if_false = NULL; | 1811 Label* if_false = NULL; |
2034 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1812 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2035 | 1813 |
2036 __ JumpIfSmi(rax, if_false); | 1814 __ JumpIfSmi(rax, if_false); |
2037 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); | 1815 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); |
2038 __ j(above_equal, if_true); | 1816 Split(above_equal, if_true, if_false, NULL); |
2039 __ jmp(if_false); | |
2040 | 1817 |
2041 Apply(context_, if_true, if_false); | 1818 Apply(context_, if_true, if_false); |
2042 } | 1819 } |
2043 | 1820 |
2044 | 1821 |
2045 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 1822 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
2046 ASSERT(args->length() == 1); | 1823 ASSERT(args->length() == 1); |
2047 | 1824 |
2048 VisitForValue(args->at(0), kAccumulator); | 1825 VisitForValue(args->at(0), kAccumulator); |
2049 | 1826 |
2050 Label materialize_true, materialize_false; | 1827 Label materialize_true, materialize_false; |
2051 Label* if_true = NULL; | 1828 Label* if_true = NULL; |
2052 Label* if_false = NULL; | 1829 Label* if_false = NULL; |
2053 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1830 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2054 | 1831 |
2055 __ JumpIfSmi(rax, if_false); | 1832 __ JumpIfSmi(rax, if_false); |
2056 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1833 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
2057 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 1834 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
2058 Immediate(1 << Map::kIsUndetectable)); | 1835 Immediate(1 << Map::kIsUndetectable)); |
2059 __ j(not_zero, if_true); | 1836 Split(not_zero, if_true, if_false, NULL); |
2060 __ jmp(if_false); | |
2061 | 1837 |
2062 Apply(context_, if_true, if_false); | 1838 Apply(context_, if_true, if_false); |
2063 } | 1839 } |
2064 | 1840 |
2065 | 1841 |
2066 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 1842 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
2067 ZoneList<Expression*>* args) { | 1843 ZoneList<Expression*>* args) { |
2068 ASSERT(args->length() == 1); | 1844 ASSERT(args->length() == 1); |
2069 | 1845 |
2070 VisitForValue(args->at(0), kAccumulator); | 1846 VisitForValue(args->at(0), kAccumulator); |
(...skipping 16 matching lines...) Expand all Loading... |
2087 | 1863 |
2088 VisitForValue(args->at(0), kAccumulator); | 1864 VisitForValue(args->at(0), kAccumulator); |
2089 | 1865 |
2090 Label materialize_true, materialize_false; | 1866 Label materialize_true, materialize_false; |
2091 Label* if_true = NULL; | 1867 Label* if_true = NULL; |
2092 Label* if_false = NULL; | 1868 Label* if_false = NULL; |
2093 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1869 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2094 | 1870 |
2095 __ JumpIfSmi(rax, if_false); | 1871 __ JumpIfSmi(rax, if_false); |
2096 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 1872 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
2097 __ j(equal, if_true); | 1873 Split(equal, if_true, if_false, NULL); |
2098 __ jmp(if_false); | |
2099 | 1874 |
2100 Apply(context_, if_true, if_false); | 1875 Apply(context_, if_true, if_false); |
2101 } | 1876 } |
2102 | 1877 |
2103 | 1878 |
2104 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 1879 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
2105 ASSERT(args->length() == 1); | 1880 ASSERT(args->length() == 1); |
2106 | 1881 |
2107 VisitForValue(args->at(0), kAccumulator); | 1882 VisitForValue(args->at(0), kAccumulator); |
2108 | 1883 |
2109 Label materialize_true, materialize_false; | 1884 Label materialize_true, materialize_false; |
2110 Label* if_true = NULL; | 1885 Label* if_true = NULL; |
2111 Label* if_false = NULL; | 1886 Label* if_false = NULL; |
2112 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1887 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2113 | 1888 |
2114 __ JumpIfSmi(rax, if_false); | 1889 __ JumpIfSmi(rax, if_false); |
2115 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); | 1890 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); |
2116 __ j(equal, if_true); | 1891 Split(equal, if_true, if_false, NULL); |
2117 __ jmp(if_false); | |
2118 | 1892 |
2119 Apply(context_, if_true, if_false); | 1893 Apply(context_, if_true, if_false); |
2120 } | 1894 } |
2121 | 1895 |
2122 | 1896 |
2123 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 1897 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
2124 ASSERT(args->length() == 1); | 1898 ASSERT(args->length() == 1); |
2125 | 1899 |
2126 VisitForValue(args->at(0), kAccumulator); | 1900 VisitForValue(args->at(0), kAccumulator); |
2127 | 1901 |
2128 Label materialize_true, materialize_false; | 1902 Label materialize_true, materialize_false; |
2129 Label* if_true = NULL; | 1903 Label* if_true = NULL; |
2130 Label* if_false = NULL; | 1904 Label* if_false = NULL; |
2131 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1905 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2132 | 1906 |
2133 __ JumpIfSmi(rax, if_false); | 1907 __ JumpIfSmi(rax, if_false); |
2134 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); | 1908 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); |
2135 __ j(equal, if_true); | 1909 Split(equal, if_true, if_false, NULL); |
2136 __ jmp(if_false); | |
2137 | 1910 |
2138 Apply(context_, if_true, if_false); | 1911 Apply(context_, if_true, if_false); |
2139 } | 1912 } |
2140 | 1913 |
2141 | 1914 |
2142 | 1915 |
2143 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 1916 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
2144 ASSERT(args->length() == 0); | 1917 ASSERT(args->length() == 0); |
2145 | 1918 |
2146 Label materialize_true, materialize_false; | 1919 Label materialize_true, materialize_false; |
2147 Label* if_true = NULL; | 1920 Label* if_true = NULL; |
2148 Label* if_false = NULL; | 1921 Label* if_false = NULL; |
2149 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1922 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2150 | 1923 |
2151 // Get the frame pointer for the calling frame. | 1924 // Get the frame pointer for the calling frame. |
2152 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 1925 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
2153 | 1926 |
2154 // Skip the arguments adaptor frame if it exists. | 1927 // Skip the arguments adaptor frame if it exists. |
2155 Label check_frame_marker; | 1928 Label check_frame_marker; |
2156 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), | 1929 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), |
2157 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1930 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
2158 __ j(not_equal, &check_frame_marker); | 1931 __ j(not_equal, &check_frame_marker); |
2159 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); | 1932 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); |
2160 | 1933 |
2161 // Check the marker in the calling frame. | 1934 // Check the marker in the calling frame. |
2162 __ bind(&check_frame_marker); | 1935 __ bind(&check_frame_marker); |
2163 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), | 1936 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), |
2164 Smi::FromInt(StackFrame::CONSTRUCT)); | 1937 Smi::FromInt(StackFrame::CONSTRUCT)); |
2165 __ j(equal, if_true); | 1938 Split(equal, if_true, if_false, NULL); |
2166 __ jmp(if_false); | |
2167 | 1939 |
2168 Apply(context_, if_true, if_false); | 1940 Apply(context_, if_true, if_false); |
2169 } | 1941 } |
2170 | 1942 |
2171 | 1943 |
2172 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { | 1944 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { |
2173 ASSERT(args->length() == 2); | 1945 ASSERT(args->length() == 2); |
2174 | 1946 |
2175 // Load the two objects into registers and perform the comparison. | 1947 // Load the two objects into registers and perform the comparison. |
2176 VisitForValue(args->at(0), kStack); | 1948 VisitForValue(args->at(0), kStack); |
2177 VisitForValue(args->at(1), kAccumulator); | 1949 VisitForValue(args->at(1), kAccumulator); |
2178 | 1950 |
2179 Label materialize_true, materialize_false; | 1951 Label materialize_true, materialize_false; |
2180 Label* if_true = NULL; | 1952 Label* if_true = NULL; |
2181 Label* if_false = NULL; | 1953 Label* if_false = NULL; |
2182 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1954 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
2183 | 1955 |
2184 __ pop(rbx); | 1956 __ pop(rbx); |
2185 __ cmpq(rax, rbx); | 1957 __ cmpq(rax, rbx); |
2186 __ j(equal, if_true); | 1958 Split(equal, if_true, if_false, NULL); |
2187 __ jmp(if_false); | |
2188 | 1959 |
2189 Apply(context_, if_true, if_false); | 1960 Apply(context_, if_true, if_false); |
2190 } | 1961 } |
2191 | 1962 |
2192 | 1963 |
2193 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 1964 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
2194 ASSERT(args->length() == 1); | 1965 ASSERT(args->length() == 1); |
2195 | 1966 |
2196 // ArgumentsAccessStub expects the key in edx and the formal | 1967 // ArgumentsAccessStub expects the key in edx and the formal |
2197 // parameter count in eax. | 1968 // parameter count in eax. |
(...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2833 case Expression::kValue: | 2604 case Expression::kValue: |
2834 switch (location_) { | 2605 switch (location_) { |
2835 case kAccumulator: | 2606 case kAccumulator: |
2836 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); | 2607 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); |
2837 break; | 2608 break; |
2838 case kStack: | 2609 case kStack: |
2839 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2610 __ PushRoot(Heap::kUndefinedValueRootIndex); |
2840 break; | 2611 break; |
2841 } | 2612 } |
2842 break; | 2613 break; |
2843 case Expression::kTestValue: | |
2844 // Value is false so it's needed. | |
2845 switch (location_) { | |
2846 case kAccumulator: | |
2847 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); | |
2848 break; | |
2849 case kStack: | |
2850 __ PushRoot(Heap::kUndefinedValueRootIndex); | |
2851 break; | |
2852 } | |
2853 // Fall through. | |
2854 case Expression::kTest: | 2614 case Expression::kTest: |
2855 case Expression::kValueTest: | |
2856 __ jmp(false_label_); | 2615 __ jmp(false_label_); |
2857 break; | 2616 break; |
2858 } | 2617 } |
2859 break; | 2618 break; |
2860 } | 2619 } |
2861 | 2620 |
2862 case Token::NOT: { | 2621 case Token::NOT: { |
2863 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 2622 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
2864 Label materialize_true, materialize_false; | 2623 Label materialize_true, materialize_false; |
2865 Label* if_true = NULL; | 2624 Label* if_true = NULL; |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3026 // Save result for postfix expressions. | 2785 // Save result for postfix expressions. |
3027 if (expr->is_postfix()) { | 2786 if (expr->is_postfix()) { |
3028 switch (context_) { | 2787 switch (context_) { |
3029 case Expression::kUninitialized: | 2788 case Expression::kUninitialized: |
3030 UNREACHABLE(); | 2789 UNREACHABLE(); |
3031 case Expression::kEffect: | 2790 case Expression::kEffect: |
3032 // Do not save result. | 2791 // Do not save result. |
3033 break; | 2792 break; |
3034 case Expression::kValue: | 2793 case Expression::kValue: |
3035 case Expression::kTest: | 2794 case Expression::kTest: |
3036 case Expression::kValueTest: | |
3037 case Expression::kTestValue: | |
3038 // Save the result on the stack. If we have a named or keyed property | 2795 // Save the result on the stack. If we have a named or keyed property |
3039 // we store the result under the receiver that is currently on top | 2796 // we store the result under the receiver that is currently on top |
3040 // of the stack. | 2797 // of the stack. |
3041 switch (assign_type) { | 2798 switch (assign_type) { |
3042 case VARIABLE: | 2799 case VARIABLE: |
3043 __ push(rax); | 2800 __ push(rax); |
3044 break; | 2801 break; |
3045 case NAMED_PROPERTY: | 2802 case NAMED_PROPERTY: |
3046 __ movq(Operand(rsp, kPointerSize), rax); | 2803 __ movq(Operand(rsp, kPointerSize), rax); |
3047 break; | 2804 break; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3131 ApplyTOS(context_); | 2888 ApplyTOS(context_); |
3132 } | 2889 } |
3133 } else { | 2890 } else { |
3134 Apply(context_, rax); | 2891 Apply(context_, rax); |
3135 } | 2892 } |
3136 break; | 2893 break; |
3137 } | 2894 } |
3138 } | 2895 } |
3139 } | 2896 } |
3140 | 2897 |
3141 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | |
3142 Comment cmnt(masm_, "[ BinaryOperation"); | |
3143 switch (expr->op()) { | |
3144 case Token::COMMA: | |
3145 VisitForEffect(expr->left()); | |
3146 Visit(expr->right()); | |
3147 break; | |
3148 | |
3149 case Token::OR: | |
3150 case Token::AND: | |
3151 EmitLogicalOperation(expr); | |
3152 break; | |
3153 | |
3154 case Token::ADD: | |
3155 case Token::SUB: | |
3156 case Token::DIV: | |
3157 case Token::MOD: | |
3158 case Token::MUL: | |
3159 case Token::BIT_OR: | |
3160 case Token::BIT_AND: | |
3161 case Token::BIT_XOR: | |
3162 case Token::SHL: | |
3163 case Token::SHR: | |
3164 case Token::SAR: | |
3165 VisitForValue(expr->left(), kStack); | |
3166 VisitForValue(expr->right(), kAccumulator); | |
3167 EmitBinaryOp(expr->op(), context_); | |
3168 break; | |
3169 | |
3170 default: | |
3171 UNREACHABLE(); | |
3172 } | |
3173 } | |
3174 | |
3175 | 2898 |
3176 void FullCodeGenerator::EmitNullCompare(bool strict, | 2899 void FullCodeGenerator::EmitNullCompare(bool strict, |
3177 Register obj, | 2900 Register obj, |
3178 Register null_const, | 2901 Register null_const, |
3179 Label* if_true, | 2902 Label* if_true, |
3180 Label* if_false, | 2903 Label* if_false, |
3181 Register scratch) { | 2904 Register scratch) { |
3182 __ cmpq(obj, null_const); | 2905 __ cmpq(obj, null_const); |
3183 if (strict) { | 2906 if (strict) { |
3184 __ j(equal, if_true); | 2907 Split(equal, if_true, if_false, NULL); |
3185 } else { | 2908 } else { |
3186 __ j(equal, if_true); | 2909 __ j(equal, if_true); |
3187 __ CompareRoot(obj, Heap::kUndefinedValueRootIndex); | 2910 __ CompareRoot(obj, Heap::kUndefinedValueRootIndex); |
3188 __ j(equal, if_true); | 2911 __ j(equal, if_true); |
3189 __ JumpIfSmi(obj, if_false); | 2912 __ JumpIfSmi(obj, if_false); |
3190 // It can be an undetectable object. | 2913 // It can be an undetectable object. |
3191 __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset)); | 2914 __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset)); |
3192 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 2915 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
3193 Immediate(1 << Map::kIsUndetectable)); | 2916 Immediate(1 << Map::kIsUndetectable)); |
3194 __ j(not_zero, if_true); | 2917 Split(not_zero, if_true, if_false, NULL); |
3195 } | 2918 } |
3196 __ jmp(if_false); | |
3197 } | 2919 } |
3198 | 2920 |
3199 | 2921 |
3200 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2922 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
3201 Comment cmnt(masm_, "[ CompareOperation"); | 2923 Comment cmnt(masm_, "[ CompareOperation"); |
3202 | 2924 |
3203 // Always perform the comparison for its control flow. Pack the result | 2925 // Always perform the comparison for its control flow. Pack the result |
3204 // into the expression's context after the comparison is performed. | 2926 // into the expression's context after the comparison is performed. |
3205 Label materialize_true, materialize_false; | 2927 Label materialize_true, materialize_false; |
3206 Label* if_true = NULL; | 2928 Label* if_true = NULL; |
3207 Label* if_false = NULL; | 2929 Label* if_false = NULL; |
3208 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 2930 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
3209 | 2931 |
3210 VisitForValue(expr->left(), kStack); | 2932 VisitForValue(expr->left(), kStack); |
3211 switch (expr->op()) { | 2933 switch (expr->op()) { |
3212 case Token::IN: | 2934 case Token::IN: |
3213 VisitForValue(expr->right(), kStack); | 2935 VisitForValue(expr->right(), kStack); |
3214 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 2936 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
3215 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 2937 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
3216 __ j(equal, if_true); | 2938 Split(equal, if_true, if_false, NULL); |
3217 __ jmp(if_false); | |
3218 break; | 2939 break; |
3219 | 2940 |
3220 case Token::INSTANCEOF: { | 2941 case Token::INSTANCEOF: { |
3221 VisitForValue(expr->right(), kStack); | 2942 VisitForValue(expr->right(), kStack); |
3222 InstanceofStub stub; | 2943 InstanceofStub stub; |
3223 __ CallStub(&stub); | 2944 __ CallStub(&stub); |
3224 __ testq(rax, rax); | 2945 __ testq(rax, rax); |
3225 __ j(zero, if_true); // The stub returns 0 for true. | 2946 // The stub returns 0 for true. |
3226 __ jmp(if_false); | 2947 Split(zero, if_true, if_false, NULL); |
3227 break; | 2948 break; |
3228 } | 2949 } |
3229 | 2950 |
3230 default: { | 2951 default: { |
3231 VisitForValue(expr->right(), kAccumulator); | 2952 VisitForValue(expr->right(), kAccumulator); |
3232 Condition cc = no_condition; | 2953 Condition cc = no_condition; |
3233 bool strict = false; | 2954 bool strict = false; |
3234 switch (expr->op()) { | 2955 switch (expr->op()) { |
3235 case Token::EQ_STRICT: | 2956 case Token::EQ_STRICT: |
3236 strict = true; | 2957 strict = true; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3284 Label slow_case; | 3005 Label slow_case; |
3285 __ JumpIfNotBothSmi(rax, rdx, &slow_case); | 3006 __ JumpIfNotBothSmi(rax, rdx, &slow_case); |
3286 __ SmiCompare(rdx, rax); | 3007 __ SmiCompare(rdx, rax); |
3287 __ j(cc, if_true); | 3008 __ j(cc, if_true); |
3288 __ jmp(if_false); | 3009 __ jmp(if_false); |
3289 | 3010 |
3290 __ bind(&slow_case); | 3011 __ bind(&slow_case); |
3291 CompareStub stub(cc, strict); | 3012 CompareStub stub(cc, strict); |
3292 __ CallStub(&stub); | 3013 __ CallStub(&stub); |
3293 __ testq(rax, rax); | 3014 __ testq(rax, rax); |
3294 __ j(cc, if_true); | 3015 Split(cc, if_true, if_false, NULL); |
3295 __ jmp(if_false); | |
3296 } | 3016 } |
3297 } | 3017 } |
3298 | 3018 |
3299 // Convert the result of the comparison into one expected for this | 3019 // Convert the result of the comparison into one expected for this |
3300 // expression's context. | 3020 // expression's context. |
3301 Apply(context_, if_true, if_false); | 3021 Apply(context_, if_true, if_false); |
3302 } | 3022 } |
3303 | 3023 |
3304 | 3024 |
3305 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3025 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3358 __ ret(0); | 3078 __ ret(0); |
3359 } | 3079 } |
3360 | 3080 |
3361 | 3081 |
3362 #undef __ | 3082 #undef __ |
3363 | 3083 |
3364 | 3084 |
3365 } } // namespace v8::internal | 3085 } } // namespace v8::internal |
3366 | 3086 |
3367 #endif // V8_TARGET_ARCH_X64 | 3087 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |