OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 // context in the fixed part of the frame. | 344 // context in the fixed part of the frame. |
345 return Operand(rbp, -(index + 3) * kPointerSize); | 345 return Operand(rbp, -(index + 3) * kPointerSize); |
346 } else { | 346 } else { |
347 // Incoming parameter. Skip the return address. | 347 // Incoming parameter. Skip the return address. |
348 return Operand(rbp, -(index - 1) * kPointerSize); | 348 return Operand(rbp, -(index - 1) * kPointerSize); |
349 } | 349 } |
350 } | 350 } |
351 | 351 |
352 | 352 |
353 void LCodeGen::WriteTranslation(LEnvironment* environment, | 353 void LCodeGen::WriteTranslation(LEnvironment* environment, |
354 Translation* translation, | 354 Translation* translation) { |
355 int* arguments_index, | |
356 int* arguments_count) { | |
357 if (environment == NULL) return; | 355 if (environment == NULL) return; |
358 | 356 |
359 // The translation includes one command per value in the environment. | 357 // The translation includes one command per value in the environment. |
360 int translation_size = environment->values()->length(); | 358 int translation_size = environment->values()->length(); |
361 // The output frame height does not include the parameters. | 359 // The output frame height does not include the parameters. |
362 int height = translation_size - environment->parameter_count(); | 360 int height = translation_size - environment->parameter_count(); |
363 | 361 |
364 // Function parameters are arguments to the outermost environment. The | 362 WriteTranslation(environment->outer(), translation); |
365 // arguments index points to the first element of a sequence of tagged | |
366 // values on the stack that represent the arguments. This needs to be | |
367 // kept in sync with the LArgumentsElements implementation. | |
368 *arguments_index = -environment->parameter_count(); | |
369 *arguments_count = environment->parameter_count(); | |
370 | |
371 WriteTranslation(environment->outer(), | |
372 translation, | |
373 arguments_index, | |
374 arguments_count); | |
375 int closure_id = *info()->closure() != *environment->closure() | 363 int closure_id = *info()->closure() != *environment->closure() |
376 ? DefineDeoptimizationLiteral(environment->closure()) | 364 ? DefineDeoptimizationLiteral(environment->closure()) |
377 : Translation::kSelfLiteralId; | 365 : Translation::kSelfLiteralId; |
378 | 366 |
379 switch (environment->frame_type()) { | 367 switch (environment->frame_type()) { |
380 case JS_FUNCTION: | 368 case JS_FUNCTION: |
381 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 369 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
382 break; | 370 break; |
383 case JS_CONSTRUCT: | 371 case JS_CONSTRUCT: |
384 translation->BeginConstructStubFrame(closure_id, translation_size); | 372 translation->BeginConstructStubFrame(closure_id, translation_size); |
385 break; | 373 break; |
386 case JS_GETTER: | 374 case JS_GETTER: |
387 ASSERT(translation_size == 1); | 375 ASSERT(translation_size == 1); |
388 ASSERT(height == 0); | 376 ASSERT(height == 0); |
389 translation->BeginGetterStubFrame(closure_id); | 377 translation->BeginGetterStubFrame(closure_id); |
390 break; | 378 break; |
391 case JS_SETTER: | 379 case JS_SETTER: |
392 ASSERT(translation_size == 2); | 380 ASSERT(translation_size == 2); |
393 ASSERT(height == 0); | 381 ASSERT(height == 0); |
394 translation->BeginSetterStubFrame(closure_id); | 382 translation->BeginSetterStubFrame(closure_id); |
395 break; | 383 break; |
396 case ARGUMENTS_ADAPTOR: | 384 case ARGUMENTS_ADAPTOR: |
397 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 385 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
398 break; | 386 break; |
399 } | 387 } |
400 | |
401 // Inlined frames which push their arguments cause the index to be | |
402 // bumped and a new stack area to be used for materialization. | |
403 if (environment->entry() != NULL && | |
404 environment->entry()->arguments_pushed()) { | |
405 *arguments_index = *arguments_index < 0 | |
406 ? GetStackSlotCount() | |
407 : *arguments_index + *arguments_count; | |
408 *arguments_count = environment->entry()->arguments_count() + 1; | |
409 } | |
410 | |
411 for (int i = 0; i < translation_size; ++i) { | 388 for (int i = 0; i < translation_size; ++i) { |
412 LOperand* value = environment->values()->at(i); | 389 LOperand* value = environment->values()->at(i); |
413 // spilled_registers_ and spilled_double_registers_ are either | 390 // spilled_registers_ and spilled_double_registers_ are either |
414 // both NULL or both set. | 391 // both NULL or both set. |
415 if (environment->spilled_registers() != NULL && value != NULL) { | 392 if (environment->spilled_registers() != NULL && value != NULL) { |
416 if (value->IsRegister() && | 393 if (value->IsRegister() && |
417 environment->spilled_registers()[value->index()] != NULL) { | 394 environment->spilled_registers()[value->index()] != NULL) { |
418 translation->MarkDuplicate(); | 395 translation->MarkDuplicate(); |
419 AddToTranslation(translation, | 396 AddToTranslation(translation, |
420 environment->spilled_registers()[value->index()], | 397 environment->spilled_registers()[value->index()], |
421 environment->HasTaggedValueAt(i), | 398 environment->HasTaggedValueAt(i), |
422 environment->HasUint32ValueAt(i), | 399 environment->HasUint32ValueAt(i)); |
423 *arguments_index, | |
424 *arguments_count); | |
425 } else if ( | 400 } else if ( |
426 value->IsDoubleRegister() && | 401 value->IsDoubleRegister() && |
427 environment->spilled_double_registers()[value->index()] != NULL) { | 402 environment->spilled_double_registers()[value->index()] != NULL) { |
428 translation->MarkDuplicate(); | 403 translation->MarkDuplicate(); |
429 AddToTranslation( | 404 AddToTranslation( |
430 translation, | 405 translation, |
431 environment->spilled_double_registers()[value->index()], | 406 environment->spilled_double_registers()[value->index()], |
432 false, | 407 false, |
433 false, | 408 false); |
434 *arguments_index, | |
435 *arguments_count); | |
436 } | 409 } |
437 } | 410 } |
438 | 411 |
439 AddToTranslation(translation, | 412 AddToTranslation(translation, |
440 value, | 413 value, |
441 environment->HasTaggedValueAt(i), | 414 environment->HasTaggedValueAt(i), |
442 environment->HasUint32ValueAt(i), | 415 environment->HasUint32ValueAt(i)); |
443 *arguments_index, | |
444 *arguments_count); | |
445 } | 416 } |
446 } | 417 } |
447 | 418 |
448 | 419 |
449 void LCodeGen::AddToTranslation(Translation* translation, | 420 void LCodeGen::AddToTranslation(Translation* translation, |
450 LOperand* op, | 421 LOperand* op, |
451 bool is_tagged, | 422 bool is_tagged, |
452 bool is_uint32, | 423 bool is_uint32) { |
453 int arguments_index, | |
454 int arguments_count) { | |
455 if (op == NULL) { | 424 if (op == NULL) { |
456 // TODO(twuerthinger): Introduce marker operands to indicate that this value | 425 // TODO(twuerthinger): Introduce marker operands to indicate that this value |
457 // is not present and must be reconstructed from the deoptimizer. Currently | 426 // is not present and must be reconstructed from the deoptimizer. Currently |
458 // this is only used for the arguments object. | 427 // this is only used for the arguments object. |
459 translation->StoreArgumentsObject(arguments_index, arguments_count); | 428 translation->StoreArgumentsObject(); |
460 } else if (op->IsStackSlot()) { | 429 } else if (op->IsStackSlot()) { |
461 if (is_tagged) { | 430 if (is_tagged) { |
462 translation->StoreStackSlot(op->index()); | 431 translation->StoreStackSlot(op->index()); |
463 } else if (is_uint32) { | 432 } else if (is_uint32) { |
464 translation->StoreUint32StackSlot(op->index()); | 433 translation->StoreUint32StackSlot(op->index()); |
465 } else { | 434 } else { |
466 translation->StoreInt32StackSlot(op->index()); | 435 translation->StoreInt32StackSlot(op->index()); |
467 } | 436 } |
468 } else if (op->IsDoubleStackSlot()) { | 437 } else if (op->IsDoubleStackSlot()) { |
469 translation->StoreDoubleStackSlot(op->index()); | 438 translation->StoreDoubleStackSlot(op->index()); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 // 0 ..................................................... size-1 | 524 // 0 ..................................................... size-1 |
556 // [parameters] [locals] [expression stack including arguments] | 525 // [parameters] [locals] [expression stack including arguments] |
557 | 526 |
558 // Layout of the translation: | 527 // Layout of the translation: |
559 // 0 ........................................................ size - 1 + 4 | 528 // 0 ........................................................ size - 1 + 4 |
560 // [expression stack including arguments] [locals] [4 words] [parameters] | 529 // [expression stack including arguments] [locals] [4 words] [parameters] |
561 // |>------------ translation_size ------------<| | 530 // |>------------ translation_size ------------<| |
562 | 531 |
563 int frame_count = 0; | 532 int frame_count = 0; |
564 int jsframe_count = 0; | 533 int jsframe_count = 0; |
565 int args_index = 0; | |
566 int args_count = 0; | |
567 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { | 534 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { |
568 ++frame_count; | 535 ++frame_count; |
569 if (e->frame_type() == JS_FUNCTION) { | 536 if (e->frame_type() == JS_FUNCTION) { |
570 ++jsframe_count; | 537 ++jsframe_count; |
571 } | 538 } |
572 } | 539 } |
573 Translation translation(&translations_, frame_count, jsframe_count, zone()); | 540 Translation translation(&translations_, frame_count, jsframe_count, |
574 WriteTranslation(environment, &translation, &args_index, &args_count); | 541 environment->zone()); |
| 542 WriteTranslation(environment, &translation); |
575 int deoptimization_index = deoptimizations_.length(); | 543 int deoptimization_index = deoptimizations_.length(); |
576 int pc_offset = masm()->pc_offset(); | 544 int pc_offset = masm()->pc_offset(); |
577 environment->Register(deoptimization_index, | 545 environment->Register(deoptimization_index, |
578 translation.index(), | 546 translation.index(), |
579 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 547 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
580 deoptimizations_.Add(environment, environment->zone()); | 548 deoptimizations_.Add(environment, environment->zone()); |
581 } | 549 } |
582 } | 550 } |
583 | 551 |
584 | 552 |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 } | 779 } |
812 | 780 |
813 | 781 |
814 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 782 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
815 // Nothing to do. | 783 // Nothing to do. |
816 } | 784 } |
817 | 785 |
818 | 786 |
819 void LCodeGen::DoModI(LModI* instr) { | 787 void LCodeGen::DoModI(LModI* instr) { |
820 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 788 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
821 Register dividend = ToRegister(instr->left()); | 789 Register dividend = ToRegister(instr->InputAt(0)); |
822 | 790 |
823 int32_t divisor = | 791 int32_t divisor = |
824 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 792 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
825 | 793 |
826 if (divisor < 0) divisor = -divisor; | 794 if (divisor < 0) divisor = -divisor; |
827 | 795 |
828 Label positive_dividend, done; | 796 Label positive_dividend, done; |
829 __ testl(dividend, dividend); | 797 __ testl(dividend, dividend); |
830 __ j(not_sign, &positive_dividend, Label::kNear); | 798 __ j(not_sign, &positive_dividend, Label::kNear); |
831 __ negl(dividend); | 799 __ negl(dividend); |
832 __ andl(dividend, Immediate(divisor - 1)); | 800 __ andl(dividend, Immediate(divisor - 1)); |
833 __ negl(dividend); | 801 __ negl(dividend); |
834 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 802 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
835 __ j(not_zero, &done, Label::kNear); | 803 __ j(not_zero, &done, Label::kNear); |
836 DeoptimizeIf(no_condition, instr->environment()); | 804 DeoptimizeIf(no_condition, instr->environment()); |
837 } else { | 805 } else { |
838 __ jmp(&done, Label::kNear); | 806 __ jmp(&done, Label::kNear); |
839 } | 807 } |
840 __ bind(&positive_dividend); | 808 __ bind(&positive_dividend); |
841 __ andl(dividend, Immediate(divisor - 1)); | 809 __ andl(dividend, Immediate(divisor - 1)); |
842 __ bind(&done); | 810 __ bind(&done); |
843 } else { | 811 } else { |
844 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; | 812 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; |
845 Register left_reg = ToRegister(instr->left()); | 813 Register left_reg = ToRegister(instr->InputAt(0)); |
846 Register right_reg = ToRegister(instr->right()); | 814 Register right_reg = ToRegister(instr->InputAt(1)); |
847 Register result_reg = ToRegister(instr->result()); | 815 Register result_reg = ToRegister(instr->result()); |
848 | 816 |
849 ASSERT(left_reg.is(rax)); | 817 ASSERT(left_reg.is(rax)); |
850 ASSERT(result_reg.is(rdx)); | 818 ASSERT(result_reg.is(rdx)); |
851 ASSERT(!right_reg.is(rax)); | 819 ASSERT(!right_reg.is(rax)); |
852 ASSERT(!right_reg.is(rdx)); | 820 ASSERT(!right_reg.is(rdx)); |
853 | 821 |
854 // Check for x % 0. | 822 // Check for x % 0. |
855 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 823 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
856 __ testl(right_reg, right_reg); | 824 __ testl(right_reg, right_reg); |
857 DeoptimizeIf(zero, instr->environment()); | 825 DeoptimizeIf(zero, instr->environment()); |
858 } | 826 } |
859 | 827 |
860 __ testl(left_reg, left_reg); | 828 __ testl(left_reg, left_reg); |
861 __ j(zero, &remainder_eq_dividend, Label::kNear); | 829 __ j(zero, &remainder_eq_dividend, Label::kNear); |
862 __ j(sign, &slow, Label::kNear); | 830 __ j(sign, &slow, Label::kNear); |
863 | 831 |
864 __ testl(right_reg, right_reg); | 832 __ testl(right_reg, right_reg); |
865 __ j(not_sign, &both_positive, Label::kNear); | 833 __ j(not_sign, &both_positive, Label::kNear); |
866 // The sign of the divisor doesn't matter. | 834 // The sign of the divisor doesn't matter. |
867 __ neg(right_reg); | 835 __ neg(right_reg); |
868 | 836 |
869 __ bind(&both_positive); | 837 __ bind(&both_positive); |
870 // If the dividend is smaller than the nonnegative | 838 // If the dividend is smaller than the nonnegative |
871 // divisor, the dividend is the result. | 839 // divisor, the dividend is the result. |
872 __ cmpl(left_reg, right_reg); | 840 __ cmpl(left_reg, right_reg); |
873 __ j(less, &remainder_eq_dividend, Label::kNear); | 841 __ j(less, &remainder_eq_dividend, Label::kNear); |
874 | 842 |
875 // Check if the divisor is a PowerOfTwo integer. | 843 // Check if the divisor is a PowerOfTwo integer. |
876 Register scratch = ToRegister(instr->temp()); | 844 Register scratch = ToRegister(instr->TempAt(0)); |
877 __ movl(scratch, right_reg); | 845 __ movl(scratch, right_reg); |
878 __ subl(scratch, Immediate(1)); | 846 __ subl(scratch, Immediate(1)); |
879 __ testl(scratch, right_reg); | 847 __ testl(scratch, right_reg); |
880 __ j(not_zero, &do_subtraction, Label::kNear); | 848 __ j(not_zero, &do_subtraction, Label::kNear); |
881 __ andl(left_reg, scratch); | 849 __ andl(left_reg, scratch); |
882 __ jmp(&remainder_eq_dividend, Label::kNear); | 850 __ jmp(&remainder_eq_dividend, Label::kNear); |
883 | 851 |
884 __ bind(&do_subtraction); | 852 __ bind(&do_subtraction); |
885 const int kUnfolds = 3; | 853 const int kUnfolds = 3; |
886 // Try a few subtractions of the dividend. | 854 // Try a few subtractions of the dividend. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 | 891 |
924 __ bind(&remainder_eq_dividend); | 892 __ bind(&remainder_eq_dividend); |
925 __ movl(result_reg, left_reg); | 893 __ movl(result_reg, left_reg); |
926 | 894 |
927 __ bind(&done); | 895 __ bind(&done); |
928 } | 896 } |
929 } | 897 } |
930 | 898 |
931 | 899 |
932 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | 900 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { |
933 ASSERT(instr->right()->IsConstantOperand()); | 901 ASSERT(instr->InputAt(1)->IsConstantOperand()); |
934 | 902 |
935 const Register dividend = ToRegister(instr->left()); | 903 const Register dividend = ToRegister(instr->InputAt(0)); |
936 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); | 904 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1))); |
937 const Register result = ToRegister(instr->result()); | 905 const Register result = ToRegister(instr->result()); |
938 | 906 |
939 switch (divisor) { | 907 switch (divisor) { |
940 case 0: | 908 case 0: |
941 DeoptimizeIf(no_condition, instr->environment()); | 909 DeoptimizeIf(no_condition, instr->environment()); |
942 return; | 910 return; |
943 | 911 |
944 case 1: | 912 case 1: |
945 if (!result.is(dividend)) { | 913 if (!result.is(dividend)) { |
946 __ movl(result, dividend); | 914 __ movl(result, dividend); |
(...skipping 24 matching lines...) Expand all Loading... |
971 DeoptimizeIf(zero, instr->environment()); | 939 DeoptimizeIf(zero, instr->environment()); |
972 } | 940 } |
973 __ sar(result, Immediate(power)); | 941 __ sar(result, Immediate(power)); |
974 } else { | 942 } else { |
975 if (!result.is(dividend)) { | 943 if (!result.is(dividend)) { |
976 __ movl(result, dividend); | 944 __ movl(result, dividend); |
977 } | 945 } |
978 __ sarl(result, Immediate(power)); | 946 __ sarl(result, Immediate(power)); |
979 } | 947 } |
980 } else { | 948 } else { |
981 Register reg1 = ToRegister(instr->temp()); | 949 Register reg1 = ToRegister(instr->TempAt(0)); |
982 Register reg2 = ToRegister(instr->result()); | 950 Register reg2 = ToRegister(instr->result()); |
983 | 951 |
984 // Find b which: 2^b < divisor_abs < 2^(b+1). | 952 // Find b which: 2^b < divisor_abs < 2^(b+1). |
985 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); | 953 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); |
986 unsigned shift = 32 + b; // Precision +1bit (effectively). | 954 unsigned shift = 32 + b; // Precision +1bit (effectively). |
987 double multiplier_f = | 955 double multiplier_f = |
988 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; | 956 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; |
989 int64_t multiplier; | 957 int64_t multiplier; |
990 if (multiplier_f - floor(multiplier_f) < 0.5) { | 958 if (multiplier_f - floor(multiplier_f) < 0.5) { |
991 multiplier = static_cast<int64_t>(floor(multiplier_f)); | 959 multiplier = static_cast<int64_t>(floor(multiplier_f)); |
(...skipping 14 matching lines...) Expand all Loading... |
1006 // Result just fit in r64, because it's int32 * uint32. | 974 // Result just fit in r64, because it's int32 * uint32. |
1007 __ imul(reg2, reg1); | 975 __ imul(reg2, reg1); |
1008 | 976 |
1009 __ addq(reg2, Immediate(1 << 30)); | 977 __ addq(reg2, Immediate(1 << 30)); |
1010 __ sar(reg2, Immediate(shift)); | 978 __ sar(reg2, Immediate(shift)); |
1011 } | 979 } |
1012 } | 980 } |
1013 | 981 |
1014 | 982 |
1015 void LCodeGen::DoDivI(LDivI* instr) { | 983 void LCodeGen::DoDivI(LDivI* instr) { |
1016 LOperand* right = instr->right(); | 984 LOperand* right = instr->InputAt(1); |
1017 ASSERT(ToRegister(instr->result()).is(rax)); | 985 ASSERT(ToRegister(instr->result()).is(rax)); |
1018 ASSERT(ToRegister(instr->left()).is(rax)); | 986 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
1019 ASSERT(!ToRegister(instr->right()).is(rax)); | 987 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); |
1020 ASSERT(!ToRegister(instr->right()).is(rdx)); | 988 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); |
1021 | 989 |
1022 Register left_reg = rax; | 990 Register left_reg = rax; |
1023 | 991 |
1024 // Check for x / 0. | 992 // Check for x / 0. |
1025 Register right_reg = ToRegister(right); | 993 Register right_reg = ToRegister(right); |
1026 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 994 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1027 __ testl(right_reg, right_reg); | 995 __ testl(right_reg, right_reg); |
1028 DeoptimizeIf(zero, instr->environment()); | 996 DeoptimizeIf(zero, instr->environment()); |
1029 } | 997 } |
1030 | 998 |
(...skipping 21 matching lines...) Expand all Loading... |
1052 __ cdq(); | 1020 __ cdq(); |
1053 __ idivl(right_reg); | 1021 __ idivl(right_reg); |
1054 | 1022 |
1055 // Deoptimize if remainder is not 0. | 1023 // Deoptimize if remainder is not 0. |
1056 __ testl(rdx, rdx); | 1024 __ testl(rdx, rdx); |
1057 DeoptimizeIf(not_zero, instr->environment()); | 1025 DeoptimizeIf(not_zero, instr->environment()); |
1058 } | 1026 } |
1059 | 1027 |
1060 | 1028 |
1061 void LCodeGen::DoMulI(LMulI* instr) { | 1029 void LCodeGen::DoMulI(LMulI* instr) { |
1062 Register left = ToRegister(instr->left()); | 1030 Register left = ToRegister(instr->InputAt(0)); |
1063 LOperand* right = instr->right(); | 1031 LOperand* right = instr->InputAt(1); |
1064 | 1032 |
1065 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1033 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1066 __ movl(kScratchRegister, left); | 1034 __ movl(kScratchRegister, left); |
1067 } | 1035 } |
1068 | 1036 |
1069 bool can_overflow = | 1037 bool can_overflow = |
1070 instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1038 instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1071 if (right->IsConstantOperand()) { | 1039 if (right->IsConstantOperand()) { |
1072 int right_value = ToInteger32(LConstantOperand::cast(right)); | 1040 int right_value = ToInteger32(LConstantOperand::cast(right)); |
1073 if (right_value == -1) { | 1041 if (right_value == -1) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 if (can_overflow) { | 1086 if (can_overflow) { |
1119 DeoptimizeIf(overflow, instr->environment()); | 1087 DeoptimizeIf(overflow, instr->environment()); |
1120 } | 1088 } |
1121 | 1089 |
1122 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1090 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1123 // Bail out if the result is supposed to be negative zero. | 1091 // Bail out if the result is supposed to be negative zero. |
1124 Label done; | 1092 Label done; |
1125 __ testl(left, left); | 1093 __ testl(left, left); |
1126 __ j(not_zero, &done, Label::kNear); | 1094 __ j(not_zero, &done, Label::kNear); |
1127 if (right->IsConstantOperand()) { | 1095 if (right->IsConstantOperand()) { |
1128 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 1096 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { |
1129 DeoptimizeIf(no_condition, instr->environment()); | 1097 DeoptimizeIf(no_condition, instr->environment()); |
1130 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { | |
1131 __ cmpl(kScratchRegister, Immediate(0)); | |
1132 DeoptimizeIf(less, instr->environment()); | |
1133 } | 1098 } |
1134 } else if (right->IsStackSlot()) { | 1099 } else if (right->IsStackSlot()) { |
1135 __ orl(kScratchRegister, ToOperand(right)); | 1100 __ orl(kScratchRegister, ToOperand(right)); |
1136 DeoptimizeIf(sign, instr->environment()); | 1101 DeoptimizeIf(sign, instr->environment()); |
1137 } else { | 1102 } else { |
1138 // Test the non-zero operand for negative sign. | 1103 // Test the non-zero operand for negative sign. |
1139 __ orl(kScratchRegister, ToRegister(right)); | 1104 __ orl(kScratchRegister, ToRegister(right)); |
1140 DeoptimizeIf(sign, instr->environment()); | 1105 DeoptimizeIf(sign, instr->environment()); |
1141 } | 1106 } |
1142 __ bind(&done); | 1107 __ bind(&done); |
1143 } | 1108 } |
1144 } | 1109 } |
1145 | 1110 |
1146 | 1111 |
1147 void LCodeGen::DoBitI(LBitI* instr) { | 1112 void LCodeGen::DoBitI(LBitI* instr) { |
1148 LOperand* left = instr->left(); | 1113 LOperand* left = instr->InputAt(0); |
1149 LOperand* right = instr->right(); | 1114 LOperand* right = instr->InputAt(1); |
1150 ASSERT(left->Equals(instr->result())); | 1115 ASSERT(left->Equals(instr->result())); |
1151 ASSERT(left->IsRegister()); | 1116 ASSERT(left->IsRegister()); |
1152 | 1117 |
1153 if (right->IsConstantOperand()) { | 1118 if (right->IsConstantOperand()) { |
1154 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 1119 int right_operand = ToInteger32(LConstantOperand::cast(right)); |
1155 switch (instr->op()) { | 1120 switch (instr->op()) { |
1156 case Token::BIT_AND: | 1121 case Token::BIT_AND: |
1157 __ andl(ToRegister(left), Immediate(right_operand)); | 1122 __ andl(ToRegister(left), Immediate(right_operand)); |
1158 break; | 1123 break; |
1159 case Token::BIT_OR: | 1124 case Token::BIT_OR: |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1195 break; | 1160 break; |
1196 default: | 1161 default: |
1197 UNREACHABLE(); | 1162 UNREACHABLE(); |
1198 break; | 1163 break; |
1199 } | 1164 } |
1200 } | 1165 } |
1201 } | 1166 } |
1202 | 1167 |
1203 | 1168 |
1204 void LCodeGen::DoShiftI(LShiftI* instr) { | 1169 void LCodeGen::DoShiftI(LShiftI* instr) { |
1205 LOperand* left = instr->left(); | 1170 LOperand* left = instr->InputAt(0); |
1206 LOperand* right = instr->right(); | 1171 LOperand* right = instr->InputAt(1); |
1207 ASSERT(left->Equals(instr->result())); | 1172 ASSERT(left->Equals(instr->result())); |
1208 ASSERT(left->IsRegister()); | 1173 ASSERT(left->IsRegister()); |
1209 if (right->IsRegister()) { | 1174 if (right->IsRegister()) { |
1210 ASSERT(ToRegister(right).is(rcx)); | 1175 ASSERT(ToRegister(right).is(rcx)); |
1211 | 1176 |
1212 switch (instr->op()) { | 1177 switch (instr->op()) { |
1213 case Token::SAR: | 1178 case Token::SAR: |
1214 __ sarl_cl(ToRegister(left)); | 1179 __ sarl_cl(ToRegister(left)); |
1215 break; | 1180 break; |
1216 case Token::SHR: | 1181 case Token::SHR: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1251 break; | 1216 break; |
1252 default: | 1217 default: |
1253 UNREACHABLE(); | 1218 UNREACHABLE(); |
1254 break; | 1219 break; |
1255 } | 1220 } |
1256 } | 1221 } |
1257 } | 1222 } |
1258 | 1223 |
1259 | 1224 |
1260 void LCodeGen::DoSubI(LSubI* instr) { | 1225 void LCodeGen::DoSubI(LSubI* instr) { |
1261 LOperand* left = instr->left(); | 1226 LOperand* left = instr->InputAt(0); |
1262 LOperand* right = instr->right(); | 1227 LOperand* right = instr->InputAt(1); |
1263 ASSERT(left->Equals(instr->result())); | 1228 ASSERT(left->Equals(instr->result())); |
1264 | 1229 |
1265 if (right->IsConstantOperand()) { | 1230 if (right->IsConstantOperand()) { |
1266 __ subl(ToRegister(left), | 1231 __ subl(ToRegister(left), |
1267 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1232 Immediate(ToInteger32(LConstantOperand::cast(right)))); |
1268 } else if (right->IsRegister()) { | 1233 } else if (right->IsRegister()) { |
1269 __ subl(ToRegister(left), ToRegister(right)); | 1234 __ subl(ToRegister(left), ToRegister(right)); |
1270 } else { | 1235 } else { |
1271 __ subl(ToRegister(left), ToOperand(right)); | 1236 __ subl(ToRegister(left), ToOperand(right)); |
1272 } | 1237 } |
(...skipping 13 matching lines...) Expand all Loading... |
1286 void LCodeGen::DoConstantD(LConstantD* instr) { | 1251 void LCodeGen::DoConstantD(LConstantD* instr) { |
1287 ASSERT(instr->result()->IsDoubleRegister()); | 1252 ASSERT(instr->result()->IsDoubleRegister()); |
1288 XMMRegister res = ToDoubleRegister(instr->result()); | 1253 XMMRegister res = ToDoubleRegister(instr->result()); |
1289 double v = instr->value(); | 1254 double v = instr->value(); |
1290 uint64_t int_val = BitCast<uint64_t, double>(v); | 1255 uint64_t int_val = BitCast<uint64_t, double>(v); |
1291 // Use xor to produce +0.0 in a fast and compact way, but avoid to | 1256 // Use xor to produce +0.0 in a fast and compact way, but avoid to |
1292 // do so if the constant is -0.0. | 1257 // do so if the constant is -0.0. |
1293 if (int_val == 0) { | 1258 if (int_val == 0) { |
1294 __ xorps(res, res); | 1259 __ xorps(res, res); |
1295 } else { | 1260 } else { |
1296 Register tmp = ToRegister(instr->temp()); | 1261 Register tmp = ToRegister(instr->TempAt(0)); |
1297 __ Set(tmp, int_val); | 1262 __ Set(tmp, int_val); |
1298 __ movq(res, tmp); | 1263 __ movq(res, tmp); |
1299 } | 1264 } |
1300 } | 1265 } |
1301 | 1266 |
1302 | 1267 |
1303 void LCodeGen::DoConstantT(LConstantT* instr) { | 1268 void LCodeGen::DoConstantT(LConstantT* instr) { |
1304 Handle<Object> value = instr->value(); | 1269 Handle<Object> value = instr->value(); |
1305 if (value->IsSmi()) { | 1270 if (value->IsSmi()) { |
1306 __ Move(ToRegister(instr->result()), value); | 1271 __ Move(ToRegister(instr->result()), value); |
1307 } else { | 1272 } else { |
1308 __ LoadHeapObject(ToRegister(instr->result()), | 1273 __ LoadHeapObject(ToRegister(instr->result()), |
1309 Handle<HeapObject>::cast(value)); | 1274 Handle<HeapObject>::cast(value)); |
1310 } | 1275 } |
1311 } | 1276 } |
1312 | 1277 |
1313 | 1278 |
1314 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1279 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
1315 Register result = ToRegister(instr->result()); | 1280 Register result = ToRegister(instr->result()); |
1316 Register array = ToRegister(instr->value()); | 1281 Register array = ToRegister(instr->InputAt(0)); |
1317 __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); | 1282 __ movq(result, FieldOperand(array, JSArray::kLengthOffset)); |
1318 } | 1283 } |
1319 | 1284 |
1320 | 1285 |
1321 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { | 1286 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { |
1322 Register result = ToRegister(instr->result()); | 1287 Register result = ToRegister(instr->result()); |
1323 Register array = ToRegister(instr->value()); | 1288 Register array = ToRegister(instr->InputAt(0)); |
1324 __ movq(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); | 1289 __ movq(result, FieldOperand(array, FixedArrayBase::kLengthOffset)); |
1325 } | 1290 } |
1326 | 1291 |
1327 | 1292 |
1328 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1293 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1329 Register result = ToRegister(instr->result()); | 1294 Register result = ToRegister(instr->result()); |
1330 Register map = ToRegister(instr->value()); | 1295 Register map = ToRegister(instr->InputAt(0)); |
1331 __ EnumLength(result, map); | 1296 __ EnumLength(result, map); |
1332 } | 1297 } |
1333 | 1298 |
1334 | 1299 |
1335 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1300 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
1336 Register result = ToRegister(instr->result()); | 1301 Register result = ToRegister(instr->result()); |
1337 Register input = ToRegister(instr->value()); | 1302 Register input = ToRegister(instr->InputAt(0)); |
1338 | 1303 |
1339 // Load map into |result|. | 1304 // Load map into |result|. |
1340 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); | 1305 __ movq(result, FieldOperand(input, HeapObject::kMapOffset)); |
1341 // Load the map's "bit field 2" into |result|. We only need the first byte. | 1306 // Load the map's "bit field 2" into |result|. We only need the first byte. |
1342 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); | 1307 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset)); |
1343 // Retrieve elements_kind from bit field 2. | 1308 // Retrieve elements_kind from bit field 2. |
1344 __ and_(result, Immediate(Map::kElementsKindMask)); | 1309 __ and_(result, Immediate(Map::kElementsKindMask)); |
1345 __ shr(result, Immediate(Map::kElementsKindShift)); | 1310 __ shr(result, Immediate(Map::kElementsKindShift)); |
1346 } | 1311 } |
1347 | 1312 |
1348 | 1313 |
1349 void LCodeGen::DoValueOf(LValueOf* instr) { | 1314 void LCodeGen::DoValueOf(LValueOf* instr) { |
1350 Register input = ToRegister(instr->value()); | 1315 Register input = ToRegister(instr->InputAt(0)); |
1351 Register result = ToRegister(instr->result()); | 1316 Register result = ToRegister(instr->result()); |
1352 ASSERT(input.is(result)); | 1317 ASSERT(input.is(result)); |
1353 Label done; | 1318 Label done; |
1354 // If the object is a smi return the object. | 1319 // If the object is a smi return the object. |
1355 __ JumpIfSmi(input, &done, Label::kNear); | 1320 __ JumpIfSmi(input, &done, Label::kNear); |
1356 | 1321 |
1357 // If the object is not a value type, return the object. | 1322 // If the object is not a value type, return the object. |
1358 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); | 1323 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); |
1359 __ j(not_equal, &done, Label::kNear); | 1324 __ j(not_equal, &done, Label::kNear); |
1360 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); | 1325 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); |
1361 | 1326 |
1362 __ bind(&done); | 1327 __ bind(&done); |
1363 } | 1328 } |
1364 | 1329 |
1365 | 1330 |
1366 void LCodeGen::DoDateField(LDateField* instr) { | 1331 void LCodeGen::DoDateField(LDateField* instr) { |
1367 Register object = ToRegister(instr->date()); | 1332 Register object = ToRegister(instr->InputAt(0)); |
1368 Register result = ToRegister(instr->result()); | 1333 Register result = ToRegister(instr->result()); |
1369 Smi* index = instr->index(); | 1334 Smi* index = instr->index(); |
1370 Label runtime, done, not_date_object; | 1335 Label runtime, done, not_date_object; |
1371 ASSERT(object.is(result)); | 1336 ASSERT(object.is(result)); |
1372 ASSERT(object.is(rax)); | 1337 ASSERT(object.is(rax)); |
1373 | 1338 |
1374 Condition cc = masm()->CheckSmi(object); | 1339 Condition cc = masm()->CheckSmi(object); |
1375 DeoptimizeIf(cc, instr->environment()); | 1340 DeoptimizeIf(cc, instr->environment()); |
1376 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); | 1341 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); |
1377 DeoptimizeIf(not_equal, instr->environment()); | 1342 DeoptimizeIf(not_equal, instr->environment()); |
(...skipping 21 matching lines...) Expand all Loading... |
1399 __ movq(rsi, index, RelocInfo::NONE); | 1364 __ movq(rsi, index, RelocInfo::NONE); |
1400 #endif | 1365 #endif |
1401 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1366 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
1402 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1367 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1403 __ bind(&done); | 1368 __ bind(&done); |
1404 } | 1369 } |
1405 } | 1370 } |
1406 | 1371 |
1407 | 1372 |
1408 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1373 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1409 LOperand* input = instr->value(); | 1374 LOperand* input = instr->InputAt(0); |
1410 ASSERT(input->Equals(instr->result())); | 1375 ASSERT(input->Equals(instr->result())); |
1411 __ not_(ToRegister(input)); | 1376 __ not_(ToRegister(input)); |
1412 } | 1377 } |
1413 | 1378 |
1414 | 1379 |
1415 void LCodeGen::DoThrow(LThrow* instr) { | 1380 void LCodeGen::DoThrow(LThrow* instr) { |
1416 __ push(ToRegister(instr->value())); | 1381 __ push(ToRegister(instr->InputAt(0))); |
1417 CallRuntime(Runtime::kThrow, 1, instr); | 1382 CallRuntime(Runtime::kThrow, 1, instr); |
1418 | 1383 |
1419 if (FLAG_debug_code) { | 1384 if (FLAG_debug_code) { |
1420 Comment("Unreachable code."); | 1385 Comment("Unreachable code."); |
1421 __ int3(); | 1386 __ int3(); |
1422 } | 1387 } |
1423 } | 1388 } |
1424 | 1389 |
1425 | 1390 |
1426 void LCodeGen::DoAddI(LAddI* instr) { | 1391 void LCodeGen::DoAddI(LAddI* instr) { |
1427 LOperand* left = instr->left(); | 1392 LOperand* left = instr->InputAt(0); |
1428 LOperand* right = instr->right(); | 1393 LOperand* right = instr->InputAt(1); |
1429 ASSERT(left->Equals(instr->result())); | 1394 ASSERT(left->Equals(instr->result())); |
1430 | 1395 |
1431 if (right->IsConstantOperand()) { | 1396 if (right->IsConstantOperand()) { |
1432 __ addl(ToRegister(left), | 1397 __ addl(ToRegister(left), |
1433 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1398 Immediate(ToInteger32(LConstantOperand::cast(right)))); |
1434 } else if (right->IsRegister()) { | 1399 } else if (right->IsRegister()) { |
1435 __ addl(ToRegister(left), ToRegister(right)); | 1400 __ addl(ToRegister(left), ToRegister(right)); |
1436 } else { | 1401 } else { |
1437 __ addl(ToRegister(left), ToOperand(right)); | 1402 __ addl(ToRegister(left), ToOperand(right)); |
1438 } | 1403 } |
1439 | 1404 |
1440 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1405 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1441 DeoptimizeIf(overflow, instr->environment()); | 1406 DeoptimizeIf(overflow, instr->environment()); |
1442 } | 1407 } |
1443 } | 1408 } |
1444 | 1409 |
1445 | 1410 |
1446 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1411 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1447 LOperand* left = instr->left(); | 1412 LOperand* left = instr->InputAt(0); |
1448 LOperand* right = instr->right(); | 1413 LOperand* right = instr->InputAt(1); |
1449 ASSERT(left->Equals(instr->result())); | 1414 ASSERT(left->Equals(instr->result())); |
1450 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1415 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
1451 if (instr->hydrogen()->representation().IsInteger32()) { | 1416 if (instr->hydrogen()->representation().IsInteger32()) { |
1452 Label return_left; | 1417 Label return_left; |
1453 Condition condition = (operation == HMathMinMax::kMathMin) | 1418 Condition condition = (operation == HMathMinMax::kMathMin) |
1454 ? less_equal | 1419 ? less_equal |
1455 : greater_equal; | 1420 : greater_equal; |
1456 Register left_reg = ToRegister(left); | 1421 Register left_reg = ToRegister(left); |
1457 if (right->IsConstantOperand()) { | 1422 if (right->IsConstantOperand()) { |
1458 Immediate right_imm = | 1423 Immediate right_imm = |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 __ j(parity_even, &return_left, Label::kNear); | 1468 __ j(parity_even, &return_left, Label::kNear); |
1504 __ bind(&return_right); | 1469 __ bind(&return_right); |
1505 __ movsd(left_reg, right_reg); | 1470 __ movsd(left_reg, right_reg); |
1506 | 1471 |
1507 __ bind(&return_left); | 1472 __ bind(&return_left); |
1508 } | 1473 } |
1509 } | 1474 } |
1510 | 1475 |
1511 | 1476 |
1512 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1477 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1513 XMMRegister left = ToDoubleRegister(instr->left()); | 1478 XMMRegister left = ToDoubleRegister(instr->InputAt(0)); |
1514 XMMRegister right = ToDoubleRegister(instr->right()); | 1479 XMMRegister right = ToDoubleRegister(instr->InputAt(1)); |
1515 XMMRegister result = ToDoubleRegister(instr->result()); | 1480 XMMRegister result = ToDoubleRegister(instr->result()); |
1516 // All operations except MOD are computed in-place. | 1481 // All operations except MOD are computed in-place. |
1517 ASSERT(instr->op() == Token::MOD || left.is(result)); | 1482 ASSERT(instr->op() == Token::MOD || left.is(result)); |
1518 switch (instr->op()) { | 1483 switch (instr->op()) { |
1519 case Token::ADD: | 1484 case Token::ADD: |
1520 __ addsd(left, right); | 1485 __ addsd(left, right); |
1521 break; | 1486 break; |
1522 case Token::SUB: | 1487 case Token::SUB: |
1523 __ subsd(left, right); | 1488 __ subsd(left, right); |
1524 break; | 1489 break; |
(...skipping 13 matching lines...) Expand all Loading... |
1538 __ movaps(result, xmm0); | 1503 __ movaps(result, xmm0); |
1539 break; | 1504 break; |
1540 default: | 1505 default: |
1541 UNREACHABLE(); | 1506 UNREACHABLE(); |
1542 break; | 1507 break; |
1543 } | 1508 } |
1544 } | 1509 } |
1545 | 1510 |
1546 | 1511 |
1547 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1512 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
1548 ASSERT(ToRegister(instr->left()).is(rdx)); | 1513 ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); |
1549 ASSERT(ToRegister(instr->right()).is(rax)); | 1514 ASSERT(ToRegister(instr->InputAt(1)).is(rax)); |
1550 ASSERT(ToRegister(instr->result()).is(rax)); | 1515 ASSERT(ToRegister(instr->result()).is(rax)); |
1551 | 1516 |
1552 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1517 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
1553 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1518 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1554 __ nop(); // Signals no inlined code. | 1519 __ nop(); // Signals no inlined code. |
1555 } | 1520 } |
1556 | 1521 |
1557 | 1522 |
1558 int LCodeGen::GetNextEmittedBlock(int block) { | 1523 int LCodeGen::GetNextEmittedBlock(int block) { |
1559 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1524 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
(...skipping 23 matching lines...) Expand all Loading... |
1583 } | 1548 } |
1584 } | 1549 } |
1585 | 1550 |
1586 | 1551 |
1587 void LCodeGen::DoBranch(LBranch* instr) { | 1552 void LCodeGen::DoBranch(LBranch* instr) { |
1588 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1553 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1589 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1554 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1590 | 1555 |
1591 Representation r = instr->hydrogen()->value()->representation(); | 1556 Representation r = instr->hydrogen()->value()->representation(); |
1592 if (r.IsInteger32()) { | 1557 if (r.IsInteger32()) { |
1593 Register reg = ToRegister(instr->value()); | 1558 Register reg = ToRegister(instr->InputAt(0)); |
1594 __ testl(reg, reg); | 1559 __ testl(reg, reg); |
1595 EmitBranch(true_block, false_block, not_zero); | 1560 EmitBranch(true_block, false_block, not_zero); |
1596 } else if (r.IsDouble()) { | 1561 } else if (r.IsDouble()) { |
1597 XMMRegister reg = ToDoubleRegister(instr->value()); | 1562 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
1598 __ xorps(xmm0, xmm0); | 1563 __ xorps(xmm0, xmm0); |
1599 __ ucomisd(reg, xmm0); | 1564 __ ucomisd(reg, xmm0); |
1600 EmitBranch(true_block, false_block, not_equal); | 1565 EmitBranch(true_block, false_block, not_equal); |
1601 } else { | 1566 } else { |
1602 ASSERT(r.IsTagged()); | 1567 ASSERT(r.IsTagged()); |
1603 Register reg = ToRegister(instr->value()); | 1568 Register reg = ToRegister(instr->InputAt(0)); |
1604 HType type = instr->hydrogen()->value()->type(); | 1569 HType type = instr->hydrogen()->value()->type(); |
1605 if (type.IsBoolean()) { | 1570 if (type.IsBoolean()) { |
1606 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1571 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1607 EmitBranch(true_block, false_block, equal); | 1572 EmitBranch(true_block, false_block, equal); |
1608 } else if (type.IsSmi()) { | 1573 } else if (type.IsSmi()) { |
1609 __ SmiCompare(reg, Smi::FromInt(0)); | 1574 __ SmiCompare(reg, Smi::FromInt(0)); |
1610 EmitBranch(true_block, false_block, not_equal); | 1575 EmitBranch(true_block, false_block, not_equal); |
1611 } else { | 1576 } else { |
1612 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1577 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1613 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1578 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1730 case Token::IN: | 1695 case Token::IN: |
1731 case Token::INSTANCEOF: | 1696 case Token::INSTANCEOF: |
1732 default: | 1697 default: |
1733 UNREACHABLE(); | 1698 UNREACHABLE(); |
1734 } | 1699 } |
1735 return cond; | 1700 return cond; |
1736 } | 1701 } |
1737 | 1702 |
1738 | 1703 |
1739 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1704 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
1740 LOperand* left = instr->left(); | 1705 LOperand* left = instr->InputAt(0); |
1741 LOperand* right = instr->right(); | 1706 LOperand* right = instr->InputAt(1); |
1742 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1707 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1743 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1708 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1744 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1709 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
1745 | 1710 |
1746 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 1711 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
1747 // We can statically evaluate the comparison. | 1712 // We can statically evaluate the comparison. |
1748 double left_val = ToDouble(LConstantOperand::cast(left)); | 1713 double left_val = ToDouble(LConstantOperand::cast(left)); |
1749 double right_val = ToDouble(LConstantOperand::cast(right)); | 1714 double right_val = ToDouble(LConstantOperand::cast(right)); |
1750 int next_block = | 1715 int next_block = |
1751 EvalComparison(instr->op(), left_val, right_val) ? true_block | 1716 EvalComparison(instr->op(), left_val, right_val) ? true_block |
(...skipping 26 matching lines...) Expand all Loading... |
1778 __ cmpl(ToRegister(left), ToOperand(right)); | 1743 __ cmpl(ToRegister(left), ToOperand(right)); |
1779 } | 1744 } |
1780 } | 1745 } |
1781 } | 1746 } |
1782 EmitBranch(true_block, false_block, cc); | 1747 EmitBranch(true_block, false_block, cc); |
1783 } | 1748 } |
1784 } | 1749 } |
1785 | 1750 |
1786 | 1751 |
1787 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 1752 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
1788 Register left = ToRegister(instr->left()); | 1753 Register left = ToRegister(instr->InputAt(0)); |
1789 Register right = ToRegister(instr->right()); | 1754 Register right = ToRegister(instr->InputAt(1)); |
1790 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1755 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1791 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1756 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1792 | 1757 |
1793 __ cmpq(left, right); | 1758 __ cmpq(left, right); |
1794 EmitBranch(true_block, false_block, equal); | 1759 EmitBranch(true_block, false_block, equal); |
1795 } | 1760 } |
1796 | 1761 |
1797 | 1762 |
1798 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 1763 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
1799 Register left = ToRegister(instr->left()); | 1764 Register left = ToRegister(instr->InputAt(0)); |
1800 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1765 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1801 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1766 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1802 | 1767 |
1803 __ cmpq(left, Immediate(instr->hydrogen()->right())); | 1768 __ cmpq(left, Immediate(instr->hydrogen()->right())); |
1804 EmitBranch(true_block, false_block, equal); | 1769 EmitBranch(true_block, false_block, equal); |
1805 } | 1770 } |
1806 | 1771 |
1807 | 1772 |
1808 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { | 1773 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { |
1809 Register reg = ToRegister(instr->value()); | 1774 Register reg = ToRegister(instr->InputAt(0)); |
1810 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1775 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1811 | 1776 |
1812 // If the expression is known to be untagged or a smi, then it's definitely | 1777 // If the expression is known to be untagged or a smi, then it's definitely |
1813 // not null, and it can't be a an undetectable object. | 1778 // not null, and it can't be a an undetectable object. |
1814 if (instr->hydrogen()->representation().IsSpecialization() || | 1779 if (instr->hydrogen()->representation().IsSpecialization() || |
1815 instr->hydrogen()->type().IsSmi()) { | 1780 instr->hydrogen()->type().IsSmi()) { |
1816 EmitGoto(false_block); | 1781 EmitGoto(false_block); |
1817 return; | 1782 return; |
1818 } | 1783 } |
1819 | 1784 |
1820 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1785 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1821 Heap::RootListIndex nil_value = instr->nil() == kNullValue ? | 1786 Heap::RootListIndex nil_value = instr->nil() == kNullValue ? |
1822 Heap::kNullValueRootIndex : | 1787 Heap::kNullValueRootIndex : |
1823 Heap::kUndefinedValueRootIndex; | 1788 Heap::kUndefinedValueRootIndex; |
1824 __ CompareRoot(reg, nil_value); | 1789 __ CompareRoot(reg, nil_value); |
1825 if (instr->kind() == kStrictEquality) { | 1790 if (instr->kind() == kStrictEquality) { |
1826 EmitBranch(true_block, false_block, equal); | 1791 EmitBranch(true_block, false_block, equal); |
1827 } else { | 1792 } else { |
1828 Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ? | 1793 Heap::RootListIndex other_nil_value = instr->nil() == kNullValue ? |
1829 Heap::kUndefinedValueRootIndex : | 1794 Heap::kUndefinedValueRootIndex : |
1830 Heap::kNullValueRootIndex; | 1795 Heap::kNullValueRootIndex; |
1831 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1796 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1832 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1797 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1833 __ j(equal, true_label); | 1798 __ j(equal, true_label); |
1834 __ CompareRoot(reg, other_nil_value); | 1799 __ CompareRoot(reg, other_nil_value); |
1835 __ j(equal, true_label); | 1800 __ j(equal, true_label); |
1836 __ JumpIfSmi(reg, false_label); | 1801 __ JumpIfSmi(reg, false_label); |
1837 // Check for undetectable objects by looking in the bit field in | 1802 // Check for undetectable objects by looking in the bit field in |
1838 // the map. The object has already been smi checked. | 1803 // the map. The object has already been smi checked. |
1839 Register scratch = ToRegister(instr->temp()); | 1804 Register scratch = ToRegister(instr->TempAt(0)); |
1840 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1805 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
1841 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 1806 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
1842 Immediate(1 << Map::kIsUndetectable)); | 1807 Immediate(1 << Map::kIsUndetectable)); |
1843 EmitBranch(true_block, false_block, not_zero); | 1808 EmitBranch(true_block, false_block, not_zero); |
1844 } | 1809 } |
1845 } | 1810 } |
1846 | 1811 |
1847 | 1812 |
1848 Condition LCodeGen::EmitIsObject(Register input, | 1813 Condition LCodeGen::EmitIsObject(Register input, |
1849 Label* is_not_object, | 1814 Label* is_not_object, |
(...skipping 14 matching lines...) Expand all Loading... |
1864 __ movzxbl(kScratchRegister, | 1829 __ movzxbl(kScratchRegister, |
1865 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); | 1830 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
1866 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1831 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1867 __ j(below, is_not_object); | 1832 __ j(below, is_not_object); |
1868 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 1833 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
1869 return below_equal; | 1834 return below_equal; |
1870 } | 1835 } |
1871 | 1836 |
1872 | 1837 |
1873 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1838 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
1874 Register reg = ToRegister(instr->value()); | 1839 Register reg = ToRegister(instr->InputAt(0)); |
1875 | 1840 |
1876 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1841 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1877 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1842 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1878 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1843 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1879 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1844 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1880 | 1845 |
1881 Condition true_cond = EmitIsObject(reg, false_label, true_label); | 1846 Condition true_cond = EmitIsObject(reg, false_label, true_label); |
1882 | 1847 |
1883 EmitBranch(true_block, false_block, true_cond); | 1848 EmitBranch(true_block, false_block, true_cond); |
1884 } | 1849 } |
1885 | 1850 |
1886 | 1851 |
1887 Condition LCodeGen::EmitIsString(Register input, | 1852 Condition LCodeGen::EmitIsString(Register input, |
1888 Register temp1, | 1853 Register temp1, |
1889 Label* is_not_string) { | 1854 Label* is_not_string) { |
1890 __ JumpIfSmi(input, is_not_string); | 1855 __ JumpIfSmi(input, is_not_string); |
1891 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 1856 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); |
1892 | 1857 |
1893 return cond; | 1858 return cond; |
1894 } | 1859 } |
1895 | 1860 |
1896 | 1861 |
1897 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 1862 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
1898 Register reg = ToRegister(instr->value()); | 1863 Register reg = ToRegister(instr->InputAt(0)); |
1899 Register temp = ToRegister(instr->temp()); | 1864 Register temp = ToRegister(instr->TempAt(0)); |
1900 | 1865 |
1901 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1866 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1902 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1867 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1903 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1868 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1904 | 1869 |
1905 Condition true_cond = EmitIsString(reg, temp, false_label); | 1870 Condition true_cond = EmitIsString(reg, temp, false_label); |
1906 | 1871 |
1907 EmitBranch(true_block, false_block, true_cond); | 1872 EmitBranch(true_block, false_block, true_cond); |
1908 } | 1873 } |
1909 | 1874 |
1910 | 1875 |
1911 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1876 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
1912 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1877 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1913 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1878 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1914 | 1879 |
1915 Condition is_smi; | 1880 Condition is_smi; |
1916 if (instr->value()->IsRegister()) { | 1881 if (instr->InputAt(0)->IsRegister()) { |
1917 Register input = ToRegister(instr->value()); | 1882 Register input = ToRegister(instr->InputAt(0)); |
1918 is_smi = masm()->CheckSmi(input); | 1883 is_smi = masm()->CheckSmi(input); |
1919 } else { | 1884 } else { |
1920 Operand input = ToOperand(instr->value()); | 1885 Operand input = ToOperand(instr->InputAt(0)); |
1921 is_smi = masm()->CheckSmi(input); | 1886 is_smi = masm()->CheckSmi(input); |
1922 } | 1887 } |
1923 EmitBranch(true_block, false_block, is_smi); | 1888 EmitBranch(true_block, false_block, is_smi); |
1924 } | 1889 } |
1925 | 1890 |
1926 | 1891 |
1927 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 1892 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
1928 Register input = ToRegister(instr->value()); | 1893 Register input = ToRegister(instr->InputAt(0)); |
1929 Register temp = ToRegister(instr->temp()); | 1894 Register temp = ToRegister(instr->TempAt(0)); |
1930 | 1895 |
1931 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1896 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1932 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1897 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1933 | 1898 |
1934 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 1899 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
1935 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 1900 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
1936 __ testb(FieldOperand(temp, Map::kBitFieldOffset), | 1901 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
1937 Immediate(1 << Map::kIsUndetectable)); | 1902 Immediate(1 << Map::kIsUndetectable)); |
1938 EmitBranch(true_block, false_block, not_zero); | 1903 EmitBranch(true_block, false_block, not_zero); |
1939 } | 1904 } |
(...skipping 28 matching lines...) Expand all Loading... |
1968 InstanceType to = instr->to(); | 1933 InstanceType to = instr->to(); |
1969 if (from == to) return equal; | 1934 if (from == to) return equal; |
1970 if (to == LAST_TYPE) return above_equal; | 1935 if (to == LAST_TYPE) return above_equal; |
1971 if (from == FIRST_TYPE) return below_equal; | 1936 if (from == FIRST_TYPE) return below_equal; |
1972 UNREACHABLE(); | 1937 UNREACHABLE(); |
1973 return equal; | 1938 return equal; |
1974 } | 1939 } |
1975 | 1940 |
1976 | 1941 |
1977 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1942 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
1978 Register input = ToRegister(instr->value()); | 1943 Register input = ToRegister(instr->InputAt(0)); |
1979 | 1944 |
1980 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1945 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1981 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1946 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1982 | 1947 |
1983 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1948 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1984 | 1949 |
1985 __ JumpIfSmi(input, false_label); | 1950 __ JumpIfSmi(input, false_label); |
1986 | 1951 |
1987 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); | 1952 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); |
1988 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 1953 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
1989 } | 1954 } |
1990 | 1955 |
1991 | 1956 |
1992 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 1957 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
1993 Register input = ToRegister(instr->value()); | 1958 Register input = ToRegister(instr->InputAt(0)); |
1994 Register result = ToRegister(instr->result()); | 1959 Register result = ToRegister(instr->result()); |
1995 | 1960 |
1996 __ AbortIfNotString(input); | 1961 __ AbortIfNotString(input); |
1997 | 1962 |
1998 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); | 1963 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); |
1999 ASSERT(String::kHashShift >= kSmiTagSize); | 1964 ASSERT(String::kHashShift >= kSmiTagSize); |
2000 __ IndexFromHash(result, result); | 1965 __ IndexFromHash(result, result); |
2001 } | 1966 } |
2002 | 1967 |
2003 | 1968 |
2004 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1969 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2005 LHasCachedArrayIndexAndBranch* instr) { | 1970 LHasCachedArrayIndexAndBranch* instr) { |
2006 Register input = ToRegister(instr->value()); | 1971 Register input = ToRegister(instr->InputAt(0)); |
2007 | 1972 |
2008 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1973 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2009 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1974 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2010 | 1975 |
2011 __ testl(FieldOperand(input, String::kHashFieldOffset), | 1976 __ testl(FieldOperand(input, String::kHashFieldOffset), |
2012 Immediate(String::kContainsCachedArrayIndexMask)); | 1977 Immediate(String::kContainsCachedArrayIndexMask)); |
2013 EmitBranch(true_block, false_block, equal); | 1978 EmitBranch(true_block, false_block, equal); |
2014 } | 1979 } |
2015 | 1980 |
2016 | 1981 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 // classes and it doesn't have to because you can't access it with natives | 2041 // classes and it doesn't have to because you can't access it with natives |
2077 // syntax. Since both sides are symbols it is sufficient to use an identity | 2042 // syntax. Since both sides are symbols it is sufficient to use an identity |
2078 // comparison. | 2043 // comparison. |
2079 ASSERT(class_name->IsSymbol()); | 2044 ASSERT(class_name->IsSymbol()); |
2080 __ Cmp(temp, class_name); | 2045 __ Cmp(temp, class_name); |
2081 // End with the answer in the z flag. | 2046 // End with the answer in the z flag. |
2082 } | 2047 } |
2083 | 2048 |
2084 | 2049 |
2085 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2050 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2086 Register input = ToRegister(instr->value()); | 2051 Register input = ToRegister(instr->InputAt(0)); |
2087 Register temp = ToRegister(instr->temp()); | 2052 Register temp = ToRegister(instr->TempAt(0)); |
2088 Register temp2 = ToRegister(instr->temp2()); | 2053 Register temp2 = ToRegister(instr->TempAt(1)); |
2089 Handle<String> class_name = instr->hydrogen()->class_name(); | 2054 Handle<String> class_name = instr->hydrogen()->class_name(); |
2090 | 2055 |
2091 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2056 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2092 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2057 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2093 | 2058 |
2094 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2059 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
2095 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2060 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2096 | 2061 |
2097 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 2062 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
2098 | 2063 |
2099 EmitBranch(true_block, false_block, equal); | 2064 EmitBranch(true_block, false_block, equal); |
2100 } | 2065 } |
2101 | 2066 |
2102 | 2067 |
2103 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2068 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2104 Register reg = ToRegister(instr->value()); | 2069 Register reg = ToRegister(instr->InputAt(0)); |
2105 int true_block = instr->true_block_id(); | 2070 int true_block = instr->true_block_id(); |
2106 int false_block = instr->false_block_id(); | 2071 int false_block = instr->false_block_id(); |
2107 | 2072 |
2108 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2073 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
2109 EmitBranch(true_block, false_block, equal); | 2074 EmitBranch(true_block, false_block, equal); |
2110 } | 2075 } |
2111 | 2076 |
2112 | 2077 |
2113 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2078 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2114 InstanceofStub stub(InstanceofStub::kNoFlags); | 2079 InstanceofStub stub(InstanceofStub::kNoFlags); |
2115 __ push(ToRegister(instr->left())); | 2080 __ push(ToRegister(instr->InputAt(0))); |
2116 __ push(ToRegister(instr->right())); | 2081 __ push(ToRegister(instr->InputAt(1))); |
2117 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2082 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2118 Label true_value, done; | 2083 Label true_value, done; |
2119 __ testq(rax, rax); | 2084 __ testq(rax, rax); |
2120 __ j(zero, &true_value, Label::kNear); | 2085 __ j(zero, &true_value, Label::kNear); |
2121 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2086 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
2122 __ jmp(&done, Label::kNear); | 2087 __ jmp(&done, Label::kNear); |
2123 __ bind(&true_value); | 2088 __ bind(&true_value); |
2124 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2089 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
2125 __ bind(&done); | 2090 __ bind(&done); |
2126 } | 2091 } |
(...skipping 13 matching lines...) Expand all Loading... |
2140 private: | 2105 private: |
2141 LInstanceOfKnownGlobal* instr_; | 2106 LInstanceOfKnownGlobal* instr_; |
2142 Label map_check_; | 2107 Label map_check_; |
2143 }; | 2108 }; |
2144 | 2109 |
2145 | 2110 |
2146 DeferredInstanceOfKnownGlobal* deferred; | 2111 DeferredInstanceOfKnownGlobal* deferred; |
2147 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2112 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
2148 | 2113 |
2149 Label done, false_result; | 2114 Label done, false_result; |
2150 Register object = ToRegister(instr->value()); | 2115 Register object = ToRegister(instr->InputAt(0)); |
2151 | 2116 |
2152 // A Smi is not an instance of anything. | 2117 // A Smi is not an instance of anything. |
2153 __ JumpIfSmi(object, &false_result); | 2118 __ JumpIfSmi(object, &false_result); |
2154 | 2119 |
2155 // This is the inlined call site instanceof cache. The two occurences of the | 2120 // This is the inlined call site instanceof cache. The two occurences of the |
2156 // hole value will be patched to the last map/result pair generated by the | 2121 // hole value will be patched to the last map/result pair generated by the |
2157 // instanceof stub. | 2122 // instanceof stub. |
2158 Label cache_miss; | 2123 Label cache_miss; |
2159 // Use a temp register to avoid memory operands with variable lengths. | 2124 // Use a temp register to avoid memory operands with variable lengths. |
2160 Register map = ToRegister(instr->temp()); | 2125 Register map = ToRegister(instr->TempAt(0)); |
2161 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 2126 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |
2162 __ bind(deferred->map_check()); // Label for calculating code patching. | 2127 __ bind(deferred->map_check()); // Label for calculating code patching. |
2163 Handle<JSGlobalPropertyCell> cache_cell = | 2128 Handle<JSGlobalPropertyCell> cache_cell = |
2164 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); | 2129 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); |
2165 __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); | 2130 __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); |
2166 __ cmpq(map, Operand(kScratchRegister, 0)); | 2131 __ cmpq(map, Operand(kScratchRegister, 0)); |
2167 __ j(not_equal, &cache_miss, Label::kNear); | 2132 __ j(not_equal, &cache_miss, Label::kNear); |
2168 // Patched to load either true or false. | 2133 // Patched to load either true or false. |
2169 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2134 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
2170 #ifdef DEBUG | 2135 #ifdef DEBUG |
(...skipping 22 matching lines...) Expand all Loading... |
2193 | 2158 |
2194 | 2159 |
2195 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 2160 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
2196 Label* map_check) { | 2161 Label* map_check) { |
2197 { | 2162 { |
2198 PushSafepointRegistersScope scope(this); | 2163 PushSafepointRegistersScope scope(this); |
2199 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 2164 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
2200 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); | 2165 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); |
2201 InstanceofStub stub(flags); | 2166 InstanceofStub stub(flags); |
2202 | 2167 |
2203 __ push(ToRegister(instr->value())); | 2168 __ push(ToRegister(instr->InputAt(0))); |
2204 __ PushHeapObject(instr->function()); | 2169 __ PushHeapObject(instr->function()); |
2205 | 2170 |
2206 static const int kAdditionalDelta = 10; | 2171 static const int kAdditionalDelta = 10; |
2207 int delta = | 2172 int delta = |
2208 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2173 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
2209 ASSERT(delta >= 0); | 2174 ASSERT(delta >= 0); |
2210 __ push_imm32(delta); | 2175 __ push_imm32(delta); |
2211 | 2176 |
2212 // We are pushing three values on the stack but recording a | 2177 // We are pushing three values on the stack but recording a |
2213 // safepoint with two arguments because stub is going to | 2178 // safepoint with two arguments because stub is going to |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2293 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2258 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
2294 Register value = ToRegister(instr->value()); | 2259 Register value = ToRegister(instr->value()); |
2295 Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell(); | 2260 Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell(); |
2296 | 2261 |
2297 // If the cell we are storing to contains the hole it could have | 2262 // If the cell we are storing to contains the hole it could have |
2298 // been deleted from the property dictionary. In that case, we need | 2263 // been deleted from the property dictionary. In that case, we need |
2299 // to update the property details in the property dictionary to mark | 2264 // to update the property details in the property dictionary to mark |
2300 // it as no longer deleted. We deoptimize in that case. | 2265 // it as no longer deleted. We deoptimize in that case. |
2301 if (instr->hydrogen()->RequiresHoleCheck()) { | 2266 if (instr->hydrogen()->RequiresHoleCheck()) { |
2302 // We have a temp because CompareRoot might clobber kScratchRegister. | 2267 // We have a temp because CompareRoot might clobber kScratchRegister. |
2303 Register cell = ToRegister(instr->temp()); | 2268 Register cell = ToRegister(instr->TempAt(0)); |
2304 ASSERT(!value.is(cell)); | 2269 ASSERT(!value.is(cell)); |
2305 __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); | 2270 __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); |
2306 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); | 2271 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); |
2307 DeoptimizeIf(equal, instr->environment()); | 2272 DeoptimizeIf(equal, instr->environment()); |
2308 // Store the value. | 2273 // Store the value. |
2309 __ movq(Operand(cell, 0), value); | 2274 __ movq(Operand(cell, 0), value); |
2310 } else { | 2275 } else { |
2311 // Store the value. | 2276 // Store the value. |
2312 __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); | 2277 __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL); |
2313 __ movq(Operand(kScratchRegister, 0), value); | 2278 __ movq(Operand(kScratchRegister, 0), value); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 __ j(not_equal, &skip_assignment); | 2326 __ j(not_equal, &skip_assignment); |
2362 } | 2327 } |
2363 } | 2328 } |
2364 __ movq(target, value); | 2329 __ movq(target, value); |
2365 | 2330 |
2366 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2331 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2367 HType type = instr->hydrogen()->value()->type(); | 2332 HType type = instr->hydrogen()->value()->type(); |
2368 SmiCheck check_needed = | 2333 SmiCheck check_needed = |
2369 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2334 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2370 int offset = Context::SlotOffset(instr->slot_index()); | 2335 int offset = Context::SlotOffset(instr->slot_index()); |
2371 Register scratch = ToRegister(instr->temp()); | 2336 Register scratch = ToRegister(instr->TempAt(0)); |
2372 __ RecordWriteContextSlot(context, | 2337 __ RecordWriteContextSlot(context, |
2373 offset, | 2338 offset, |
2374 value, | 2339 value, |
2375 scratch, | 2340 scratch, |
2376 kSaveFPRegs, | 2341 kSaveFPRegs, |
2377 EMIT_REMEMBERED_SET, | 2342 EMIT_REMEMBERED_SET, |
2378 check_needed); | 2343 check_needed); |
2379 } | 2344 } |
2380 | 2345 |
2381 __ bind(&skip_assignment); | 2346 __ bind(&skip_assignment); |
2382 } | 2347 } |
2383 | 2348 |
2384 | 2349 |
2385 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2350 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2386 Register object = ToRegister(instr->object()); | 2351 Register object = ToRegister(instr->InputAt(0)); |
2387 Register result = ToRegister(instr->result()); | 2352 Register result = ToRegister(instr->result()); |
2388 if (instr->hydrogen()->is_in_object()) { | 2353 if (instr->hydrogen()->is_in_object()) { |
2389 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); | 2354 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); |
2390 } else { | 2355 } else { |
2391 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2356 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
2392 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); | 2357 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); |
2393 } | 2358 } |
2394 } | 2359 } |
2395 | 2360 |
2396 | 2361 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2548 __ bind(&non_instance); | 2513 __ bind(&non_instance); |
2549 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); | 2514 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); |
2550 | 2515 |
2551 // All done. | 2516 // All done. |
2552 __ bind(&done); | 2517 __ bind(&done); |
2553 } | 2518 } |
2554 | 2519 |
2555 | 2520 |
2556 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2521 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
2557 Register result = ToRegister(instr->result()); | 2522 Register result = ToRegister(instr->result()); |
2558 Register input = ToRegister(instr->object()); | 2523 Register input = ToRegister(instr->InputAt(0)); |
2559 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); | 2524 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); |
2560 if (FLAG_debug_code) { | 2525 if (FLAG_debug_code) { |
2561 Label done, ok, fail; | 2526 Label done, ok, fail; |
2562 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2527 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2563 Heap::kFixedArrayMapRootIndex); | 2528 Heap::kFixedArrayMapRootIndex); |
2564 __ j(equal, &done, Label::kNear); | 2529 __ j(equal, &done, Label::kNear); |
2565 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2530 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2566 Heap::kFixedCOWArrayMapRootIndex); | 2531 Heap::kFixedCOWArrayMapRootIndex); |
2567 __ j(equal, &done, Label::kNear); | 2532 __ j(equal, &done, Label::kNear); |
2568 Register temp((result.is(rax)) ? rbx : rax); | 2533 Register temp((result.is(rax)) ? rbx : rax); |
(...skipping 15 matching lines...) Expand all Loading... |
2584 __ bind(&ok); | 2549 __ bind(&ok); |
2585 __ pop(temp); | 2550 __ pop(temp); |
2586 __ bind(&done); | 2551 __ bind(&done); |
2587 } | 2552 } |
2588 } | 2553 } |
2589 | 2554 |
2590 | 2555 |
2591 void LCodeGen::DoLoadExternalArrayPointer( | 2556 void LCodeGen::DoLoadExternalArrayPointer( |
2592 LLoadExternalArrayPointer* instr) { | 2557 LLoadExternalArrayPointer* instr) { |
2593 Register result = ToRegister(instr->result()); | 2558 Register result = ToRegister(instr->result()); |
2594 Register input = ToRegister(instr->object()); | 2559 Register input = ToRegister(instr->InputAt(0)); |
2595 __ movq(result, FieldOperand(input, | 2560 __ movq(result, FieldOperand(input, |
2596 ExternalPixelArray::kExternalPointerOffset)); | 2561 ExternalPixelArray::kExternalPointerOffset)); |
2597 } | 2562 } |
2598 | 2563 |
2599 | 2564 |
2600 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2565 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
2601 Register arguments = ToRegister(instr->arguments()); | 2566 Register arguments = ToRegister(instr->arguments()); |
2602 Register length = ToRegister(instr->length()); | 2567 Register length = ToRegister(instr->length()); |
2603 Register result = ToRegister(instr->result()); | 2568 Register result = ToRegister(instr->result()); |
2604 | 2569 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2832 } | 2797 } |
2833 } | 2798 } |
2834 | 2799 |
2835 | 2800 |
2836 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2801 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
2837 Register result = ToRegister(instr->result()); | 2802 Register result = ToRegister(instr->result()); |
2838 | 2803 |
2839 Label done; | 2804 Label done; |
2840 | 2805 |
2841 // If no arguments adaptor frame the number of arguments is fixed. | 2806 // If no arguments adaptor frame the number of arguments is fixed. |
2842 if (instr->elements()->IsRegister()) { | 2807 if (instr->InputAt(0)->IsRegister()) { |
2843 __ cmpq(rbp, ToRegister(instr->elements())); | 2808 __ cmpq(rbp, ToRegister(instr->InputAt(0))); |
2844 } else { | 2809 } else { |
2845 __ cmpq(rbp, ToOperand(instr->elements())); | 2810 __ cmpq(rbp, ToOperand(instr->InputAt(0))); |
2846 } | 2811 } |
2847 __ movl(result, Immediate(scope()->num_parameters())); | 2812 __ movl(result, Immediate(scope()->num_parameters())); |
2848 __ j(equal, &done, Label::kNear); | 2813 __ j(equal, &done, Label::kNear); |
2849 | 2814 |
2850 // Arguments adaptor frame present. Get argument length from there. | 2815 // Arguments adaptor frame present. Get argument length from there. |
2851 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2816 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
2852 __ SmiToInteger32(result, | 2817 __ SmiToInteger32(result, |
2853 Operand(result, | 2818 Operand(result, |
2854 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2819 ArgumentsAdaptorFrameConstants::kLengthOffset)); |
2855 | 2820 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2943 SafepointGenerator safepoint_generator( | 2908 SafepointGenerator safepoint_generator( |
2944 this, pointers, Safepoint::kLazyDeopt); | 2909 this, pointers, Safepoint::kLazyDeopt); |
2945 ParameterCount actual(rax); | 2910 ParameterCount actual(rax); |
2946 __ InvokeFunction(function, actual, CALL_FUNCTION, | 2911 __ InvokeFunction(function, actual, CALL_FUNCTION, |
2947 safepoint_generator, CALL_AS_METHOD); | 2912 safepoint_generator, CALL_AS_METHOD); |
2948 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2913 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2949 } | 2914 } |
2950 | 2915 |
2951 | 2916 |
2952 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2917 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
2953 LOperand* argument = instr->value(); | 2918 LOperand* argument = instr->InputAt(0); |
2954 EmitPushTaggedOperand(argument); | 2919 EmitPushTaggedOperand(argument); |
2955 } | 2920 } |
2956 | 2921 |
2957 | 2922 |
2958 void LCodeGen::DoDrop(LDrop* instr) { | 2923 void LCodeGen::DoDrop(LDrop* instr) { |
2959 __ Drop(instr->count()); | 2924 __ Drop(instr->count()); |
2960 } | 2925 } |
2961 | 2926 |
2962 | 2927 |
2963 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 2928 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3053 ASSERT(ToRegister(instr->result()).is(rax)); | 3018 ASSERT(ToRegister(instr->result()).is(rax)); |
3054 CallKnownFunction(instr->function(), | 3019 CallKnownFunction(instr->function(), |
3055 instr->arity(), | 3020 instr->arity(), |
3056 instr, | 3021 instr, |
3057 CALL_AS_METHOD, | 3022 CALL_AS_METHOD, |
3058 RDI_UNINITIALIZED); | 3023 RDI_UNINITIALIZED); |
3059 } | 3024 } |
3060 | 3025 |
3061 | 3026 |
3062 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 3027 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
3063 Register input_reg = ToRegister(instr->value()); | 3028 Register input_reg = ToRegister(instr->InputAt(0)); |
3064 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3029 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
3065 Heap::kHeapNumberMapRootIndex); | 3030 Heap::kHeapNumberMapRootIndex); |
3066 DeoptimizeIf(not_equal, instr->environment()); | 3031 DeoptimizeIf(not_equal, instr->environment()); |
3067 | 3032 |
3068 Label done; | 3033 Label done; |
3069 Register tmp = input_reg.is(rax) ? rcx : rax; | 3034 Register tmp = input_reg.is(rax) ? rcx : rax; |
3070 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; | 3035 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; |
3071 | 3036 |
3072 // Preserve the value of all registers. | 3037 // Preserve the value of all registers. |
3073 PushSafepointRegistersScope scope(this); | 3038 PushSafepointRegistersScope scope(this); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3105 __ shl(tmp2, Immediate(1)); | 3070 __ shl(tmp2, Immediate(1)); |
3106 __ shr(tmp2, Immediate(1)); | 3071 __ shr(tmp2, Immediate(1)); |
3107 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 3072 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
3108 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 3073 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
3109 | 3074 |
3110 __ bind(&done); | 3075 __ bind(&done); |
3111 } | 3076 } |
3112 | 3077 |
3113 | 3078 |
3114 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 3079 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
3115 Register input_reg = ToRegister(instr->value()); | 3080 Register input_reg = ToRegister(instr->InputAt(0)); |
3116 __ testl(input_reg, input_reg); | 3081 __ testl(input_reg, input_reg); |
3117 Label is_positive; | 3082 Label is_positive; |
3118 __ j(not_sign, &is_positive); | 3083 __ j(not_sign, &is_positive); |
3119 __ negl(input_reg); // Sets flags. | 3084 __ negl(input_reg); // Sets flags. |
3120 DeoptimizeIf(negative, instr->environment()); | 3085 DeoptimizeIf(negative, instr->environment()); |
3121 __ bind(&is_positive); | 3086 __ bind(&is_positive); |
3122 } | 3087 } |
3123 | 3088 |
3124 | 3089 |
3125 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3090 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
3126 // Class for deferred case. | 3091 // Class for deferred case. |
3127 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3092 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3128 public: | 3093 public: |
3129 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3094 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
3130 LUnaryMathOperation* instr) | 3095 LUnaryMathOperation* instr) |
3131 : LDeferredCode(codegen), instr_(instr) { } | 3096 : LDeferredCode(codegen), instr_(instr) { } |
3132 virtual void Generate() { | 3097 virtual void Generate() { |
3133 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3098 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3134 } | 3099 } |
3135 virtual LInstruction* instr() { return instr_; } | 3100 virtual LInstruction* instr() { return instr_; } |
3136 private: | 3101 private: |
3137 LUnaryMathOperation* instr_; | 3102 LUnaryMathOperation* instr_; |
3138 }; | 3103 }; |
3139 | 3104 |
3140 ASSERT(instr->value()->Equals(instr->result())); | 3105 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
3141 Representation r = instr->hydrogen()->value()->representation(); | 3106 Representation r = instr->hydrogen()->value()->representation(); |
3142 | 3107 |
3143 if (r.IsDouble()) { | 3108 if (r.IsDouble()) { |
3144 XMMRegister scratch = xmm0; | 3109 XMMRegister scratch = xmm0; |
3145 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3110 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
3146 __ xorps(scratch, scratch); | 3111 __ xorps(scratch, scratch); |
3147 __ subsd(scratch, input_reg); | 3112 __ subsd(scratch, input_reg); |
3148 __ andpd(input_reg, scratch); | 3113 __ andpd(input_reg, scratch); |
3149 } else if (r.IsInteger32()) { | 3114 } else if (r.IsInteger32()) { |
3150 EmitIntegerMathAbs(instr); | 3115 EmitIntegerMathAbs(instr); |
3151 } else { // Tagged case. | 3116 } else { // Tagged case. |
3152 DeferredMathAbsTaggedHeapNumber* deferred = | 3117 DeferredMathAbsTaggedHeapNumber* deferred = |
3153 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3118 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
3154 Register input_reg = ToRegister(instr->value()); | 3119 Register input_reg = ToRegister(instr->InputAt(0)); |
3155 // Smi check. | 3120 // Smi check. |
3156 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3121 __ JumpIfNotSmi(input_reg, deferred->entry()); |
3157 __ SmiToInteger32(input_reg, input_reg); | 3122 __ SmiToInteger32(input_reg, input_reg); |
3158 EmitIntegerMathAbs(instr); | 3123 EmitIntegerMathAbs(instr); |
3159 __ Integer32ToSmi(input_reg, input_reg); | 3124 __ Integer32ToSmi(input_reg, input_reg); |
3160 __ bind(deferred->exit()); | 3125 __ bind(deferred->exit()); |
3161 } | 3126 } |
3162 } | 3127 } |
3163 | 3128 |
3164 | 3129 |
3165 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3130 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
3166 XMMRegister xmm_scratch = xmm0; | 3131 XMMRegister xmm_scratch = xmm0; |
3167 Register output_reg = ToRegister(instr->result()); | 3132 Register output_reg = ToRegister(instr->result()); |
3168 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3133 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
3169 | 3134 |
3170 if (CpuFeatures::IsSupported(SSE4_1)) { | 3135 if (CpuFeatures::IsSupported(SSE4_1)) { |
3171 CpuFeatures::Scope scope(SSE4_1); | 3136 CpuFeatures::Scope scope(SSE4_1); |
3172 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3137 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3173 // Deoptimize if minus zero. | 3138 // Deoptimize if minus zero. |
3174 __ movq(output_reg, input_reg); | 3139 __ movq(output_reg, input_reg); |
3175 __ subq(output_reg, Immediate(1)); | 3140 __ subq(output_reg, Immediate(1)); |
3176 DeoptimizeIf(overflow, instr->environment()); | 3141 DeoptimizeIf(overflow, instr->environment()); |
3177 } | 3142 } |
3178 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); | 3143 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3217 DeoptimizeIf(overflow, instr->environment()); | 3182 DeoptimizeIf(overflow, instr->environment()); |
3218 | 3183 |
3219 __ bind(&done); | 3184 __ bind(&done); |
3220 } | 3185 } |
3221 } | 3186 } |
3222 | 3187 |
3223 | 3188 |
3224 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3189 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
3225 const XMMRegister xmm_scratch = xmm0; | 3190 const XMMRegister xmm_scratch = xmm0; |
3226 Register output_reg = ToRegister(instr->result()); | 3191 Register output_reg = ToRegister(instr->result()); |
3227 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3192 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
3228 | 3193 |
3229 Label done; | 3194 Label done; |
3230 // xmm_scratch = 0.5 | 3195 // xmm_scratch = 0.5 |
3231 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); | 3196 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); |
3232 __ movq(xmm_scratch, kScratchRegister); | 3197 __ movq(xmm_scratch, kScratchRegister); |
3233 Label below_half; | 3198 Label below_half; |
3234 __ ucomisd(xmm_scratch, input_reg); | 3199 __ ucomisd(xmm_scratch, input_reg); |
3235 // If input_reg is NaN, this doesn't jump. | 3200 // If input_reg is NaN, this doesn't jump. |
3236 __ j(above, &below_half, Label::kNear); | 3201 __ j(above, &below_half, Label::kNear); |
3237 // input = input + 0.5 | 3202 // input = input + 0.5 |
(...skipping 24 matching lines...) Expand all Loading... |
3262 __ ucomisd(input_reg, xmm_scratch); | 3227 __ ucomisd(input_reg, xmm_scratch); |
3263 DeoptimizeIf(below, instr->environment()); | 3228 DeoptimizeIf(below, instr->environment()); |
3264 } | 3229 } |
3265 __ xorl(output_reg, output_reg); | 3230 __ xorl(output_reg, output_reg); |
3266 | 3231 |
3267 __ bind(&done); | 3232 __ bind(&done); |
3268 } | 3233 } |
3269 | 3234 |
3270 | 3235 |
3271 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3236 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
3272 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3237 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
3273 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3238 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
3274 __ sqrtsd(input_reg, input_reg); | 3239 __ sqrtsd(input_reg, input_reg); |
3275 } | 3240 } |
3276 | 3241 |
3277 | 3242 |
3278 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3243 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
3279 XMMRegister xmm_scratch = xmm0; | 3244 XMMRegister xmm_scratch = xmm0; |
3280 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3245 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
3281 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3246 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
3282 | 3247 |
3283 // Note that according to ECMA-262 15.8.2.13: | 3248 // Note that according to ECMA-262 15.8.2.13: |
3284 // Math.pow(-Infinity, 0.5) == Infinity | 3249 // Math.pow(-Infinity, 0.5) == Infinity |
3285 // Math.sqrt(-Infinity) == NaN | 3250 // Math.sqrt(-Infinity) == NaN |
3286 Label done, sqrt; | 3251 Label done, sqrt; |
3287 // Check base for -Infinity. According to IEEE-754, double-precision | 3252 // Check base for -Infinity. According to IEEE-754, double-precision |
3288 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3253 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
3289 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000), RelocInfo::NONE); | 3254 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000), RelocInfo::NONE); |
3290 __ movq(xmm_scratch, kScratchRegister); | 3255 __ movq(xmm_scratch, kScratchRegister); |
(...skipping 20 matching lines...) Expand all Loading... |
3311 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3276 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3312 // Having marked this as a call, we can use any registers. | 3277 // Having marked this as a call, we can use any registers. |
3313 // Just make sure that the input/output registers are the expected ones. | 3278 // Just make sure that the input/output registers are the expected ones. |
3314 | 3279 |
3315 // Choose register conforming to calling convention (when bailing out). | 3280 // Choose register conforming to calling convention (when bailing out). |
3316 #ifdef _WIN64 | 3281 #ifdef _WIN64 |
3317 Register exponent = rdx; | 3282 Register exponent = rdx; |
3318 #else | 3283 #else |
3319 Register exponent = rdi; | 3284 Register exponent = rdi; |
3320 #endif | 3285 #endif |
3321 ASSERT(!instr->right()->IsRegister() || | 3286 ASSERT(!instr->InputAt(1)->IsRegister() || |
3322 ToRegister(instr->right()).is(exponent)); | 3287 ToRegister(instr->InputAt(1)).is(exponent)); |
3323 ASSERT(!instr->right()->IsDoubleRegister() || | 3288 ASSERT(!instr->InputAt(1)->IsDoubleRegister() || |
3324 ToDoubleRegister(instr->right()).is(xmm1)); | 3289 ToDoubleRegister(instr->InputAt(1)).is(xmm1)); |
3325 ASSERT(ToDoubleRegister(instr->left()).is(xmm2)); | 3290 ASSERT(ToDoubleRegister(instr->InputAt(0)).is(xmm2)); |
3326 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); | 3291 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); |
3327 | 3292 |
3328 if (exponent_type.IsTagged()) { | 3293 if (exponent_type.IsTagged()) { |
3329 Label no_deopt; | 3294 Label no_deopt; |
3330 __ JumpIfSmi(exponent, &no_deopt); | 3295 __ JumpIfSmi(exponent, &no_deopt); |
3331 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); | 3296 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); |
3332 DeoptimizeIf(not_equal, instr->environment()); | 3297 DeoptimizeIf(not_equal, instr->environment()); |
3333 __ bind(&no_deopt); | 3298 __ bind(&no_deopt); |
3334 MathPowStub stub(MathPowStub::TAGGED); | 3299 MathPowStub stub(MathPowStub::TAGGED); |
3335 __ CallStub(&stub); | 3300 __ CallStub(&stub); |
(...skipping 21 matching lines...) Expand all Loading... |
3357 | 3322 |
3358 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3323 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
3359 | 3324 |
3360 // Having marked this instruction as a call we can use any | 3325 // Having marked this instruction as a call we can use any |
3361 // registers. | 3326 // registers. |
3362 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3327 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
3363 | 3328 |
3364 // Choose the right register for the first argument depending on | 3329 // Choose the right register for the first argument depending on |
3365 // calling convention. | 3330 // calling convention. |
3366 #ifdef _WIN64 | 3331 #ifdef _WIN64 |
3367 ASSERT(ToRegister(instr->global_object()).is(rcx)); | 3332 ASSERT(ToRegister(instr->InputAt(0)).is(rcx)); |
3368 Register global_object = rcx; | 3333 Register global_object = rcx; |
3369 #else | 3334 #else |
3370 ASSERT(ToRegister(instr->global_object()).is(rdi)); | 3335 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); |
3371 Register global_object = rdi; | 3336 Register global_object = rdi; |
3372 #endif | 3337 #endif |
3373 | 3338 |
3374 static const int kSeedSize = sizeof(uint32_t); | 3339 static const int kSeedSize = sizeof(uint32_t); |
3375 STATIC_ASSERT(kPointerSize == 2 * kSeedSize); | 3340 STATIC_ASSERT(kPointerSize == 2 * kSeedSize); |
3376 | 3341 |
3377 __ movq(global_object, | 3342 __ movq(global_object, |
3378 FieldOperand(global_object, GlobalObject::kNativeContextOffset)); | 3343 FieldOperand(global_object, GlobalObject::kNativeContextOffset)); |
3379 static const int kRandomSeedOffset = | 3344 static const int kRandomSeedOffset = |
3380 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | 3345 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3575 ASSERT(ToRegister(instr->result()).is(rax)); | 3540 ASSERT(ToRegister(instr->result()).is(rax)); |
3576 CallKnownFunction(instr->target(), | 3541 CallKnownFunction(instr->target(), |
3577 instr->arity(), | 3542 instr->arity(), |
3578 instr, | 3543 instr, |
3579 CALL_AS_FUNCTION, | 3544 CALL_AS_FUNCTION, |
3580 RDI_UNINITIALIZED); | 3545 RDI_UNINITIALIZED); |
3581 } | 3546 } |
3582 | 3547 |
3583 | 3548 |
3584 void LCodeGen::DoCallNew(LCallNew* instr) { | 3549 void LCodeGen::DoCallNew(LCallNew* instr) { |
3585 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3550 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); |
3586 ASSERT(ToRegister(instr->result()).is(rax)); | 3551 ASSERT(ToRegister(instr->result()).is(rax)); |
3587 | 3552 |
3588 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3553 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
3589 __ Set(rax, instr->arity()); | 3554 __ Set(rax, instr->arity()); |
3590 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 3555 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
3591 } | 3556 } |
3592 | 3557 |
3593 | 3558 |
3594 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3559 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
3595 CallRuntime(instr->function(), instr->arity(), instr); | 3560 CallRuntime(instr->function(), instr->arity(), instr); |
3596 } | 3561 } |
3597 | 3562 |
3598 | 3563 |
3599 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3564 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3600 Register object = ToRegister(instr->object()); | 3565 Register object = ToRegister(instr->object()); |
3601 Register value = ToRegister(instr->value()); | 3566 Register value = ToRegister(instr->value()); |
3602 int offset = instr->offset(); | 3567 int offset = instr->offset(); |
3603 | 3568 |
3604 if (!instr->transition().is_null()) { | 3569 if (!instr->transition().is_null()) { |
3605 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3570 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
3606 __ Move(FieldOperand(object, HeapObject::kMapOffset), | 3571 __ Move(FieldOperand(object, HeapObject::kMapOffset), |
3607 instr->transition()); | 3572 instr->transition()); |
3608 } else { | 3573 } else { |
3609 Register temp = ToRegister(instr->temp()); | 3574 Register temp = ToRegister(instr->TempAt(0)); |
3610 __ Move(kScratchRegister, instr->transition()); | 3575 __ Move(kScratchRegister, instr->transition()); |
3611 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); | 3576 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); |
3612 // Update the write barrier for the map field. | 3577 // Update the write barrier for the map field. |
3613 __ RecordWriteField(object, | 3578 __ RecordWriteField(object, |
3614 HeapObject::kMapOffset, | 3579 HeapObject::kMapOffset, |
3615 kScratchRegister, | 3580 kScratchRegister, |
3616 temp, | 3581 temp, |
3617 kSaveFPRegs, | 3582 kSaveFPRegs, |
3618 OMIT_REMEMBERED_SET, | 3583 OMIT_REMEMBERED_SET, |
3619 OMIT_SMI_CHECK); | 3584 OMIT_SMI_CHECK); |
3620 } | 3585 } |
3621 } | 3586 } |
3622 | 3587 |
3623 // Do the store. | 3588 // Do the store. |
3624 HType type = instr->hydrogen()->value()->type(); | 3589 HType type = instr->hydrogen()->value()->type(); |
3625 SmiCheck check_needed = | 3590 SmiCheck check_needed = |
3626 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3591 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3627 if (instr->is_in_object()) { | 3592 if (instr->is_in_object()) { |
3628 __ movq(FieldOperand(object, offset), value); | 3593 __ movq(FieldOperand(object, offset), value); |
3629 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3594 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3630 Register temp = ToRegister(instr->temp()); | 3595 Register temp = ToRegister(instr->TempAt(0)); |
3631 // Update the write barrier for the object for in-object properties. | 3596 // Update the write barrier for the object for in-object properties. |
3632 __ RecordWriteField(object, | 3597 __ RecordWriteField(object, |
3633 offset, | 3598 offset, |
3634 value, | 3599 value, |
3635 temp, | 3600 temp, |
3636 kSaveFPRegs, | 3601 kSaveFPRegs, |
3637 EMIT_REMEMBERED_SET, | 3602 EMIT_REMEMBERED_SET, |
3638 check_needed); | 3603 check_needed); |
3639 } | 3604 } |
3640 } else { | 3605 } else { |
3641 Register temp = ToRegister(instr->temp()); | 3606 Register temp = ToRegister(instr->TempAt(0)); |
3642 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3607 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
3643 __ movq(FieldOperand(temp, offset), value); | 3608 __ movq(FieldOperand(temp, offset), value); |
3644 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3609 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3645 // Update the write barrier for the properties array. | 3610 // Update the write barrier for the properties array. |
3646 // object is used as a scratch register. | 3611 // object is used as a scratch register. |
3647 __ RecordWriteField(temp, | 3612 __ RecordWriteField(temp, |
3648 offset, | 3613 offset, |
3649 value, | 3614 value, |
3650 object, | 3615 object, |
3651 kSaveFPRegs, | 3616 kSaveFPRegs, |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3770 } | 3735 } |
3771 } else { | 3736 } else { |
3772 Register reg2 = ToRegister(instr->index()); | 3737 Register reg2 = ToRegister(instr->index()); |
3773 if (FLAG_debug_code && | 3738 if (FLAG_debug_code && |
3774 !instr->hydrogen()->index()->representation().IsTagged()) { | 3739 !instr->hydrogen()->index()->representation().IsTagged()) { |
3775 __ AbortIfNotZeroExtended(reg2); | 3740 __ AbortIfNotZeroExtended(reg2); |
3776 } | 3741 } |
3777 __ cmpq(reg, reg2); | 3742 __ cmpq(reg, reg2); |
3778 } | 3743 } |
3779 } else { | 3744 } else { |
3780 Operand length = ToOperand(instr->length()); | |
3781 if (instr->index()->IsConstantOperand()) { | 3745 if (instr->index()->IsConstantOperand()) { |
3782 int constant_index = | 3746 __ cmpq(ToOperand(instr->length()), |
3783 ToInteger32(LConstantOperand::cast(instr->index())); | 3747 Immediate(ToInteger32(LConstantOperand::cast(instr->index())))); |
3784 if (instr->hydrogen()->length()->representation().IsTagged()) { | |
3785 __ Cmp(length, Smi::FromInt(constant_index)); | |
3786 } else { | |
3787 __ cmpq(length, Immediate(constant_index)); | |
3788 } | |
3789 } else { | 3748 } else { |
3790 __ cmpq(length, ToRegister(instr->index())); | 3749 __ cmpq(ToOperand(instr->length()), ToRegister(instr->index())); |
3791 } | 3750 } |
3792 } | 3751 } |
3793 DeoptimizeIf(below_equal, instr->environment()); | 3752 DeoptimizeIf(below_equal, instr->environment()); |
3794 } | 3753 } |
3795 | 3754 |
3796 | 3755 |
3797 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3756 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
3798 Register value = ToRegister(instr->value()); | 3757 Register value = ToRegister(instr->value()); |
3799 Register elements = ToRegister(instr->object()); | 3758 Register elements = ToRegister(instr->object()); |
3800 LOperand* key = instr->key(); | 3759 LOperand* key = instr->key(); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3890 | 3849 |
3891 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3850 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3892 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3851 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3893 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3852 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3894 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3853 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3895 } | 3854 } |
3896 | 3855 |
3897 | 3856 |
3898 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 3857 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
3899 Register object_reg = ToRegister(instr->object()); | 3858 Register object_reg = ToRegister(instr->object()); |
3900 Register new_map_reg = ToRegister(instr->new_map_temp()); | 3859 Register new_map_reg = ToRegister(instr->new_map_reg()); |
3901 | 3860 |
3902 Handle<Map> from_map = instr->original_map(); | 3861 Handle<Map> from_map = instr->original_map(); |
3903 Handle<Map> to_map = instr->transitioned_map(); | 3862 Handle<Map> to_map = instr->transitioned_map(); |
3904 ElementsKind from_kind = from_map->elements_kind(); | 3863 ElementsKind from_kind = from_map->elements_kind(); |
3905 ElementsKind to_kind = to_map->elements_kind(); | 3864 ElementsKind to_kind = to_map->elements_kind(); |
3906 | 3865 |
3907 Label not_applicable; | 3866 Label not_applicable; |
3908 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3867 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
3909 __ j(not_equal, ¬_applicable); | 3868 __ j(not_equal, ¬_applicable); |
3910 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 3869 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
3911 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 3870 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
3912 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3871 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
3913 // Write barrier. | 3872 // Write barrier. |
3914 ASSERT_NE(instr->temp(), NULL); | 3873 ASSERT_NE(instr->temp_reg(), NULL); |
3915 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3874 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
3916 ToRegister(instr->temp()), kDontSaveFPRegs); | 3875 ToRegister(instr->temp_reg()), kDontSaveFPRegs); |
3917 } else if (IsFastSmiElementsKind(from_kind) && | 3876 } else if (IsFastSmiElementsKind(from_kind) && |
3918 IsFastDoubleElementsKind(to_kind)) { | 3877 IsFastDoubleElementsKind(to_kind)) { |
3919 Register fixed_object_reg = ToRegister(instr->temp()); | 3878 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3920 ASSERT(fixed_object_reg.is(rdx)); | 3879 ASSERT(fixed_object_reg.is(rdx)); |
3921 ASSERT(new_map_reg.is(rbx)); | 3880 ASSERT(new_map_reg.is(rbx)); |
3922 __ movq(fixed_object_reg, object_reg); | 3881 __ movq(fixed_object_reg, object_reg); |
3923 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3882 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
3924 RelocInfo::CODE_TARGET, instr); | 3883 RelocInfo::CODE_TARGET, instr); |
3925 } else if (IsFastDoubleElementsKind(from_kind) && | 3884 } else if (IsFastDoubleElementsKind(from_kind) && |
3926 IsFastObjectElementsKind(to_kind)) { | 3885 IsFastObjectElementsKind(to_kind)) { |
3927 Register fixed_object_reg = ToRegister(instr->temp()); | 3886 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3928 ASSERT(fixed_object_reg.is(rdx)); | 3887 ASSERT(fixed_object_reg.is(rdx)); |
3929 ASSERT(new_map_reg.is(rbx)); | 3888 ASSERT(new_map_reg.is(rbx)); |
3930 __ movq(fixed_object_reg, object_reg); | 3889 __ movq(fixed_object_reg, object_reg); |
3931 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3890 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
3932 RelocInfo::CODE_TARGET, instr); | 3891 RelocInfo::CODE_TARGET, instr); |
3933 } else { | 3892 } else { |
3934 UNREACHABLE(); | 3893 UNREACHABLE(); |
3935 } | 3894 } |
3936 __ bind(¬_applicable); | 3895 __ bind(¬_applicable); |
3937 } | 3896 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4048 | 4007 |
4049 | 4008 |
4050 void LCodeGen::DoStringLength(LStringLength* instr) { | 4009 void LCodeGen::DoStringLength(LStringLength* instr) { |
4051 Register string = ToRegister(instr->string()); | 4010 Register string = ToRegister(instr->string()); |
4052 Register result = ToRegister(instr->result()); | 4011 Register result = ToRegister(instr->result()); |
4053 __ movq(result, FieldOperand(string, String::kLengthOffset)); | 4012 __ movq(result, FieldOperand(string, String::kLengthOffset)); |
4054 } | 4013 } |
4055 | 4014 |
4056 | 4015 |
4057 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4016 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4058 LOperand* input = instr->value(); | 4017 LOperand* input = instr->InputAt(0); |
4059 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4018 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4060 LOperand* output = instr->result(); | 4019 LOperand* output = instr->result(); |
4061 ASSERT(output->IsDoubleRegister()); | 4020 ASSERT(output->IsDoubleRegister()); |
4062 if (input->IsRegister()) { | 4021 if (input->IsRegister()) { |
4063 __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); | 4022 __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); |
4064 } else { | 4023 } else { |
4065 __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); | 4024 __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); |
4066 } | 4025 } |
4067 } | 4026 } |
4068 | 4027 |
4069 | 4028 |
4070 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4029 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
4071 LOperand* input = instr->value(); | 4030 LOperand* input = instr->InputAt(0); |
4072 LOperand* output = instr->result(); | 4031 LOperand* output = instr->result(); |
4073 LOperand* temp = instr->temp(); | 4032 LOperand* temp = instr->TempAt(0); |
4074 | 4033 |
4075 __ LoadUint32(ToDoubleRegister(output), | 4034 __ LoadUint32(ToDoubleRegister(output), |
4076 ToRegister(input), | 4035 ToRegister(input), |
4077 ToDoubleRegister(temp)); | 4036 ToDoubleRegister(temp)); |
4078 } | 4037 } |
4079 | 4038 |
4080 | 4039 |
4081 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4040 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
4082 LOperand* input = instr->value(); | 4041 LOperand* input = instr->InputAt(0); |
4083 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4042 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4084 Register reg = ToRegister(input); | 4043 Register reg = ToRegister(input); |
4085 | 4044 |
4086 __ Integer32ToSmi(reg, reg); | 4045 __ Integer32ToSmi(reg, reg); |
4087 } | 4046 } |
4088 | 4047 |
4089 | 4048 |
4090 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4049 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4091 class DeferredNumberTagU: public LDeferredCode { | 4050 class DeferredNumberTagU: public LDeferredCode { |
4092 public: | 4051 public: |
4093 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4052 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
4094 : LDeferredCode(codegen), instr_(instr) { } | 4053 : LDeferredCode(codegen), instr_(instr) { } |
4095 virtual void Generate() { | 4054 virtual void Generate() { |
4096 codegen()->DoDeferredNumberTagU(instr_); | 4055 codegen()->DoDeferredNumberTagU(instr_); |
4097 } | 4056 } |
4098 virtual LInstruction* instr() { return instr_; } | 4057 virtual LInstruction* instr() { return instr_; } |
4099 private: | 4058 private: |
4100 LNumberTagU* instr_; | 4059 LNumberTagU* instr_; |
4101 }; | 4060 }; |
4102 | 4061 |
4103 LOperand* input = instr->value(); | 4062 LOperand* input = instr->InputAt(0); |
4104 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4063 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4105 Register reg = ToRegister(input); | 4064 Register reg = ToRegister(input); |
4106 | 4065 |
4107 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4066 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4108 __ cmpl(reg, Immediate(Smi::kMaxValue)); | 4067 __ cmpl(reg, Immediate(Smi::kMaxValue)); |
4109 __ j(above, deferred->entry()); | 4068 __ j(above, deferred->entry()); |
4110 __ Integer32ToSmi(reg, reg); | 4069 __ Integer32ToSmi(reg, reg); |
4111 __ bind(deferred->exit()); | 4070 __ bind(deferred->exit()); |
4112 } | 4071 } |
4113 | 4072 |
4114 | 4073 |
4115 void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { | 4074 void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { |
4116 Label slow; | 4075 Label slow; |
4117 Register reg = ToRegister(instr->value()); | 4076 Register reg = ToRegister(instr->InputAt(0)); |
4118 Register tmp = reg.is(rax) ? rcx : rax; | 4077 Register tmp = reg.is(rax) ? rcx : rax; |
4119 | 4078 |
4120 // Preserve the value of all registers. | 4079 // Preserve the value of all registers. |
4121 PushSafepointRegistersScope scope(this); | 4080 PushSafepointRegistersScope scope(this); |
4122 | 4081 |
4123 Label done; | 4082 Label done; |
4124 // Load value into xmm1 which will be preserved across potential call to | 4083 // Load value into xmm1 which will be preserved across potential call to |
4125 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable | 4084 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable |
4126 // XMM registers on x64). | 4085 // XMM registers on x64). |
4127 __ LoadUint32(xmm1, reg, xmm0); | 4086 __ LoadUint32(xmm1, reg, xmm0); |
(...skipping 26 matching lines...) Expand all Loading... |
4154 class DeferredNumberTagD: public LDeferredCode { | 4113 class DeferredNumberTagD: public LDeferredCode { |
4155 public: | 4114 public: |
4156 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4115 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
4157 : LDeferredCode(codegen), instr_(instr) { } | 4116 : LDeferredCode(codegen), instr_(instr) { } |
4158 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4117 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
4159 virtual LInstruction* instr() { return instr_; } | 4118 virtual LInstruction* instr() { return instr_; } |
4160 private: | 4119 private: |
4161 LNumberTagD* instr_; | 4120 LNumberTagD* instr_; |
4162 }; | 4121 }; |
4163 | 4122 |
4164 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 4123 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
4165 Register reg = ToRegister(instr->result()); | 4124 Register reg = ToRegister(instr->result()); |
4166 Register tmp = ToRegister(instr->temp()); | 4125 Register tmp = ToRegister(instr->TempAt(0)); |
4167 | 4126 |
4168 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4127 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
4169 if (FLAG_inline_new) { | 4128 if (FLAG_inline_new) { |
4170 __ AllocateHeapNumber(reg, tmp, deferred->entry()); | 4129 __ AllocateHeapNumber(reg, tmp, deferred->entry()); |
4171 } else { | 4130 } else { |
4172 __ jmp(deferred->entry()); | 4131 __ jmp(deferred->entry()); |
4173 } | 4132 } |
4174 __ bind(deferred->exit()); | 4133 __ bind(deferred->exit()); |
4175 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 4134 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
4176 } | 4135 } |
(...skipping 10 matching lines...) Expand all Loading... |
4187 PushSafepointRegistersScope scope(this); | 4146 PushSafepointRegistersScope scope(this); |
4188 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4147 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
4189 // Ensure that value in rax survives popping registers. | 4148 // Ensure that value in rax survives popping registers. |
4190 __ movq(kScratchRegister, rax); | 4149 __ movq(kScratchRegister, rax); |
4191 } | 4150 } |
4192 __ movq(reg, kScratchRegister); | 4151 __ movq(reg, kScratchRegister); |
4193 } | 4152 } |
4194 | 4153 |
4195 | 4154 |
4196 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4155 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4197 ASSERT(instr->value()->Equals(instr->result())); | 4156 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
4198 Register input = ToRegister(instr->value()); | 4157 Register input = ToRegister(instr->InputAt(0)); |
4199 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4158 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
4200 __ Integer32ToSmi(input, input); | 4159 __ Integer32ToSmi(input, input); |
4201 } | 4160 } |
4202 | 4161 |
4203 | 4162 |
4204 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4163 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4205 ASSERT(instr->value()->Equals(instr->result())); | 4164 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
4206 Register input = ToRegister(instr->value()); | 4165 Register input = ToRegister(instr->InputAt(0)); |
4207 if (instr->needs_check()) { | 4166 if (instr->needs_check()) { |
4208 Condition is_smi = __ CheckSmi(input); | 4167 Condition is_smi = __ CheckSmi(input); |
4209 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); | 4168 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); |
4210 } else { | 4169 } else { |
4211 if (FLAG_debug_code) { | 4170 if (FLAG_debug_code) { |
4212 __ AbortIfNotSmi(input); | 4171 __ AbortIfNotSmi(input); |
4213 } | 4172 } |
4214 } | 4173 } |
4215 __ SmiToInteger32(input, input); | 4174 __ SmiToInteger32(input, input); |
4216 } | 4175 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4261 // Smi to XMM conversion | 4220 // Smi to XMM conversion |
4262 __ bind(&load_smi); | 4221 __ bind(&load_smi); |
4263 __ SmiToInteger32(kScratchRegister, input_reg); | 4222 __ SmiToInteger32(kScratchRegister, input_reg); |
4264 __ cvtlsi2sd(result_reg, kScratchRegister); | 4223 __ cvtlsi2sd(result_reg, kScratchRegister); |
4265 __ bind(&done); | 4224 __ bind(&done); |
4266 } | 4225 } |
4267 | 4226 |
4268 | 4227 |
4269 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4228 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
4270 Label done, heap_number; | 4229 Label done, heap_number; |
4271 Register input_reg = ToRegister(instr->value()); | 4230 Register input_reg = ToRegister(instr->InputAt(0)); |
4272 | 4231 |
4273 // Heap number map check. | 4232 // Heap number map check. |
4274 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4233 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
4275 Heap::kHeapNumberMapRootIndex); | 4234 Heap::kHeapNumberMapRootIndex); |
4276 | 4235 |
4277 if (instr->truncating()) { | 4236 if (instr->truncating()) { |
4278 __ j(equal, &heap_number, Label::kNear); | 4237 __ j(equal, &heap_number, Label::kNear); |
4279 // Check for undefined. Undefined is converted to zero for truncating | 4238 // Check for undefined. Undefined is converted to zero for truncating |
4280 // conversions. | 4239 // conversions. |
4281 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4240 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
4282 DeoptimizeIf(not_equal, instr->environment()); | 4241 DeoptimizeIf(not_equal, instr->environment()); |
4283 __ Set(input_reg, 0); | 4242 __ Set(input_reg, 0); |
4284 __ jmp(&done, Label::kNear); | 4243 __ jmp(&done, Label::kNear); |
4285 | 4244 |
4286 __ bind(&heap_number); | 4245 __ bind(&heap_number); |
4287 | 4246 |
4288 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4247 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4289 __ cvttsd2siq(input_reg, xmm0); | 4248 __ cvttsd2siq(input_reg, xmm0); |
4290 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); | 4249 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); |
4291 __ cmpq(input_reg, kScratchRegister); | 4250 __ cmpq(input_reg, kScratchRegister); |
4292 DeoptimizeIf(equal, instr->environment()); | 4251 DeoptimizeIf(equal, instr->environment()); |
4293 } else { | 4252 } else { |
4294 // Deoptimize if we don't have a heap number. | 4253 // Deoptimize if we don't have a heap number. |
4295 DeoptimizeIf(not_equal, instr->environment()); | 4254 DeoptimizeIf(not_equal, instr->environment()); |
4296 | 4255 |
4297 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 4256 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
4298 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4257 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4299 __ cvttsd2si(input_reg, xmm0); | 4258 __ cvttsd2si(input_reg, xmm0); |
4300 __ cvtlsi2sd(xmm_temp, input_reg); | 4259 __ cvtlsi2sd(xmm_temp, input_reg); |
4301 __ ucomisd(xmm0, xmm_temp); | 4260 __ ucomisd(xmm0, xmm_temp); |
4302 DeoptimizeIf(not_equal, instr->environment()); | 4261 DeoptimizeIf(not_equal, instr->environment()); |
4303 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 4262 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
4304 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4263 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4305 __ testl(input_reg, input_reg); | 4264 __ testl(input_reg, input_reg); |
4306 __ j(not_zero, &done); | 4265 __ j(not_zero, &done); |
4307 __ movmskpd(input_reg, xmm0); | 4266 __ movmskpd(input_reg, xmm0); |
4308 __ andl(input_reg, Immediate(1)); | 4267 __ andl(input_reg, Immediate(1)); |
4309 DeoptimizeIf(not_zero, instr->environment()); | 4268 DeoptimizeIf(not_zero, instr->environment()); |
4310 } | 4269 } |
4311 } | 4270 } |
4312 __ bind(&done); | 4271 __ bind(&done); |
4313 } | 4272 } |
4314 | 4273 |
4315 | 4274 |
4316 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4275 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
4317 class DeferredTaggedToI: public LDeferredCode { | 4276 class DeferredTaggedToI: public LDeferredCode { |
4318 public: | 4277 public: |
4319 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4278 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
4320 : LDeferredCode(codegen), instr_(instr) { } | 4279 : LDeferredCode(codegen), instr_(instr) { } |
4321 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4280 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
4322 virtual LInstruction* instr() { return instr_; } | 4281 virtual LInstruction* instr() { return instr_; } |
4323 private: | 4282 private: |
4324 LTaggedToI* instr_; | 4283 LTaggedToI* instr_; |
4325 }; | 4284 }; |
4326 | 4285 |
4327 LOperand* input = instr->value(); | 4286 LOperand* input = instr->InputAt(0); |
4328 ASSERT(input->IsRegister()); | 4287 ASSERT(input->IsRegister()); |
4329 ASSERT(input->Equals(instr->result())); | 4288 ASSERT(input->Equals(instr->result())); |
4330 | 4289 |
4331 Register input_reg = ToRegister(input); | 4290 Register input_reg = ToRegister(input); |
4332 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4291 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
4333 __ JumpIfNotSmi(input_reg, deferred->entry()); | 4292 __ JumpIfNotSmi(input_reg, deferred->entry()); |
4334 __ SmiToInteger32(input_reg, input_reg); | 4293 __ SmiToInteger32(input_reg, input_reg); |
4335 __ bind(deferred->exit()); | 4294 __ bind(deferred->exit()); |
4336 } | 4295 } |
4337 | 4296 |
4338 | 4297 |
4339 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4298 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
4340 LOperand* input = instr->value(); | 4299 LOperand* input = instr->InputAt(0); |
4341 ASSERT(input->IsRegister()); | 4300 ASSERT(input->IsRegister()); |
4342 LOperand* result = instr->result(); | 4301 LOperand* result = instr->result(); |
4343 ASSERT(result->IsDoubleRegister()); | 4302 ASSERT(result->IsDoubleRegister()); |
4344 | 4303 |
4345 Register input_reg = ToRegister(input); | 4304 Register input_reg = ToRegister(input); |
4346 XMMRegister result_reg = ToDoubleRegister(result); | 4305 XMMRegister result_reg = ToDoubleRegister(result); |
4347 | 4306 |
4348 EmitNumberUntagD(input_reg, result_reg, | 4307 EmitNumberUntagD(input_reg, result_reg, |
4349 instr->hydrogen()->deoptimize_on_undefined(), | 4308 instr->hydrogen()->deoptimize_on_undefined(), |
4350 instr->hydrogen()->deoptimize_on_minus_zero(), | 4309 instr->hydrogen()->deoptimize_on_minus_zero(), |
4351 instr->environment()); | 4310 instr->environment()); |
4352 } | 4311 } |
4353 | 4312 |
4354 | 4313 |
4355 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4314 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
4356 LOperand* input = instr->value(); | 4315 LOperand* input = instr->InputAt(0); |
4357 ASSERT(input->IsDoubleRegister()); | 4316 ASSERT(input->IsDoubleRegister()); |
4358 LOperand* result = instr->result(); | 4317 LOperand* result = instr->result(); |
4359 ASSERT(result->IsRegister()); | 4318 ASSERT(result->IsRegister()); |
4360 | 4319 |
4361 XMMRegister input_reg = ToDoubleRegister(input); | 4320 XMMRegister input_reg = ToDoubleRegister(input); |
4362 Register result_reg = ToRegister(result); | 4321 Register result_reg = ToRegister(result); |
4363 | 4322 |
4364 if (instr->truncating()) { | 4323 if (instr->truncating()) { |
4365 // Performs a truncating conversion of a floating point number as used by | 4324 // Performs a truncating conversion of a floating point number as used by |
4366 // the JS bitwise operations. | 4325 // the JS bitwise operations. |
(...skipping 19 matching lines...) Expand all Loading... |
4386 // deoptimize. | 4345 // deoptimize. |
4387 __ andl(result_reg, Immediate(1)); | 4346 __ andl(result_reg, Immediate(1)); |
4388 DeoptimizeIf(not_zero, instr->environment()); | 4347 DeoptimizeIf(not_zero, instr->environment()); |
4389 __ bind(&done); | 4348 __ bind(&done); |
4390 } | 4349 } |
4391 } | 4350 } |
4392 } | 4351 } |
4393 | 4352 |
4394 | 4353 |
4395 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4354 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
4396 LOperand* input = instr->value(); | 4355 LOperand* input = instr->InputAt(0); |
4397 Condition cc = masm()->CheckSmi(ToRegister(input)); | 4356 Condition cc = masm()->CheckSmi(ToRegister(input)); |
4398 DeoptimizeIf(NegateCondition(cc), instr->environment()); | 4357 DeoptimizeIf(NegateCondition(cc), instr->environment()); |
4399 } | 4358 } |
4400 | 4359 |
4401 | 4360 |
4402 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4361 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
4403 LOperand* input = instr->value(); | 4362 LOperand* input = instr->InputAt(0); |
4404 Condition cc = masm()->CheckSmi(ToRegister(input)); | 4363 Condition cc = masm()->CheckSmi(ToRegister(input)); |
4405 DeoptimizeIf(cc, instr->environment()); | 4364 DeoptimizeIf(cc, instr->environment()); |
4406 } | 4365 } |
4407 | 4366 |
4408 | 4367 |
4409 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4368 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
4410 Register input = ToRegister(instr->value()); | 4369 Register input = ToRegister(instr->InputAt(0)); |
4411 | 4370 |
4412 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 4371 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
4413 | 4372 |
4414 if (instr->hydrogen()->is_interval_check()) { | 4373 if (instr->hydrogen()->is_interval_check()) { |
4415 InstanceType first; | 4374 InstanceType first; |
4416 InstanceType last; | 4375 InstanceType last; |
4417 instr->hydrogen()->GetCheckInterval(&first, &last); | 4376 instr->hydrogen()->GetCheckInterval(&first, &last); |
4418 | 4377 |
4419 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 4378 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
4420 Immediate(static_cast<int8_t>(first))); | 4379 Immediate(static_cast<int8_t>(first))); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4472 CompareMapMode mode, | 4431 CompareMapMode mode, |
4473 LEnvironment* env) { | 4432 LEnvironment* env) { |
4474 Label success; | 4433 Label success; |
4475 __ CompareMap(reg, map, &success, mode); | 4434 __ CompareMap(reg, map, &success, mode); |
4476 DeoptimizeIf(not_equal, env); | 4435 DeoptimizeIf(not_equal, env); |
4477 __ bind(&success); | 4436 __ bind(&success); |
4478 } | 4437 } |
4479 | 4438 |
4480 | 4439 |
4481 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4440 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
4482 LOperand* input = instr->value(); | 4441 LOperand* input = instr->InputAt(0); |
4483 ASSERT(input->IsRegister()); | 4442 ASSERT(input->IsRegister()); |
4484 Register reg = ToRegister(input); | 4443 Register reg = ToRegister(input); |
4485 | 4444 |
4486 Label success; | 4445 Label success; |
4487 SmallMapList* map_set = instr->hydrogen()->map_set(); | 4446 SmallMapList* map_set = instr->hydrogen()->map_set(); |
4488 for (int i = 0; i < map_set->length() - 1; i++) { | 4447 for (int i = 0; i < map_set->length() - 1; i++) { |
4489 Handle<Map> map = map_set->at(i); | 4448 Handle<Map> map = map_set->at(i); |
4490 __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP); | 4449 __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP); |
4491 __ j(equal, &success); | 4450 __ j(equal, &success); |
4492 } | 4451 } |
4493 Handle<Map> map = map_set->last(); | 4452 Handle<Map> map = map_set->last(); |
4494 DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr->environment()); | 4453 DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr->environment()); |
4495 __ bind(&success); | 4454 __ bind(&success); |
4496 } | 4455 } |
4497 | 4456 |
4498 | 4457 |
4499 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4458 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
4500 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4459 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
4501 Register result_reg = ToRegister(instr->result()); | 4460 Register result_reg = ToRegister(instr->result()); |
4502 Register temp_reg = ToRegister(instr->temp()); | 4461 Register temp_reg = ToRegister(instr->TempAt(0)); |
4503 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); | 4462 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg); |
4504 } | 4463 } |
4505 | 4464 |
4506 | 4465 |
4507 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 4466 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
4508 ASSERT(instr->unclamped()->Equals(instr->result())); | 4467 ASSERT(instr->unclamped()->Equals(instr->result())); |
4509 Register value_reg = ToRegister(instr->result()); | 4468 Register value_reg = ToRegister(instr->result()); |
4510 __ ClampUint8(value_reg); | 4469 __ ClampUint8(value_reg); |
4511 } | 4470 } |
4512 | 4471 |
4513 | 4472 |
4514 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 4473 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
4515 ASSERT(instr->unclamped()->Equals(instr->result())); | 4474 ASSERT(instr->unclamped()->Equals(instr->result())); |
4516 Register input_reg = ToRegister(instr->unclamped()); | 4475 Register input_reg = ToRegister(instr->unclamped()); |
4517 Register temp_reg = ToRegister(instr->temp()); | 4476 Register temp_reg = ToRegister(instr->TempAt(0)); |
4518 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp2()); | 4477 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->TempAt(1)); |
4519 Label is_smi, done, heap_number; | 4478 Label is_smi, done, heap_number; |
4520 | 4479 |
4521 __ JumpIfSmi(input_reg, &is_smi); | 4480 __ JumpIfSmi(input_reg, &is_smi); |
4522 | 4481 |
4523 // Check for heap number | 4482 // Check for heap number |
4524 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 4483 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
4525 factory()->heap_number_map()); | 4484 factory()->heap_number_map()); |
4526 __ j(equal, &heap_number, Label::kNear); | 4485 __ j(equal, &heap_number, Label::kNear); |
4527 | 4486 |
4528 // Check for undefined. Undefined is converted to zero for clamping | 4487 // Check for undefined. Undefined is converted to zero for clamping |
(...skipping 12 matching lines...) Expand all Loading... |
4541 // smi | 4500 // smi |
4542 __ bind(&is_smi); | 4501 __ bind(&is_smi); |
4543 __ SmiToInteger32(input_reg, input_reg); | 4502 __ SmiToInteger32(input_reg, input_reg); |
4544 __ ClampUint8(input_reg); | 4503 __ ClampUint8(input_reg); |
4545 | 4504 |
4546 __ bind(&done); | 4505 __ bind(&done); |
4547 } | 4506 } |
4548 | 4507 |
4549 | 4508 |
4550 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 4509 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
4551 Register reg = ToRegister(instr->temp()); | 4510 Register reg = ToRegister(instr->TempAt(0)); |
4552 | 4511 |
4553 Handle<JSObject> holder = instr->holder(); | 4512 Handle<JSObject> holder = instr->holder(); |
4554 Handle<JSObject> current_prototype = instr->prototype(); | 4513 Handle<JSObject> current_prototype = instr->prototype(); |
4555 | 4514 |
4556 // Load prototype object. | 4515 // Load prototype object. |
4557 __ LoadHeapObject(reg, current_prototype); | 4516 __ LoadHeapObject(reg, current_prototype); |
4558 | 4517 |
4559 // Check prototype maps up to the holder. | 4518 // Check prototype maps up to the holder. |
4560 while (!current_prototype.is_identical_to(holder)) { | 4519 while (!current_prototype.is_identical_to(holder)) { |
4561 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), | 4520 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), |
(...skipping 18 matching lines...) Expand all Loading... |
4580 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | 4539 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } |
4581 virtual LInstruction* instr() { return instr_; } | 4540 virtual LInstruction* instr() { return instr_; } |
4582 private: | 4541 private: |
4583 LAllocateObject* instr_; | 4542 LAllocateObject* instr_; |
4584 }; | 4543 }; |
4585 | 4544 |
4586 DeferredAllocateObject* deferred = | 4545 DeferredAllocateObject* deferred = |
4587 new(zone()) DeferredAllocateObject(this, instr); | 4546 new(zone()) DeferredAllocateObject(this, instr); |
4588 | 4547 |
4589 Register result = ToRegister(instr->result()); | 4548 Register result = ToRegister(instr->result()); |
4590 Register scratch = ToRegister(instr->temp()); | 4549 Register scratch = ToRegister(instr->TempAt(0)); |
4591 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | 4550 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
4592 Handle<Map> initial_map(constructor->initial_map()); | 4551 Handle<Map> initial_map(constructor->initial_map()); |
4593 int instance_size = initial_map->instance_size(); | 4552 int instance_size = initial_map->instance_size(); |
4594 ASSERT(initial_map->pre_allocated_property_fields() + | 4553 ASSERT(initial_map->pre_allocated_property_fields() + |
4595 initial_map->unused_property_fields() - | 4554 initial_map->unused_property_fields() - |
4596 initial_map->inobject_properties() == 0); | 4555 initial_map->inobject_properties() == 0); |
4597 | 4556 |
4598 // Allocate memory for the object. The initial map might change when | 4557 // Allocate memory for the object. The initial map might change when |
4599 // the constructor's prototype changes, but instance size and property | 4558 // the constructor's prototype changes, but instance size and property |
4600 // counts remain unchanged (if slack tracking finished). | 4559 // counts remain unchanged (if slack tracking finished). |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4882 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 4841 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
4883 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); | 4842 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
4884 } else { | 4843 } else { |
4885 FastCloneShallowObjectStub stub(properties_count); | 4844 FastCloneShallowObjectStub stub(properties_count); |
4886 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4845 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4887 } | 4846 } |
4888 } | 4847 } |
4889 | 4848 |
4890 | 4849 |
4891 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 4850 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
4892 ASSERT(ToRegister(instr->value()).is(rax)); | 4851 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
4893 __ push(rax); | 4852 __ push(rax); |
4894 CallRuntime(Runtime::kToFastProperties, 1, instr); | 4853 CallRuntime(Runtime::kToFastProperties, 1, instr); |
4895 } | 4854 } |
4896 | 4855 |
4897 | 4856 |
4898 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 4857 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
4899 Label materialized; | 4858 Label materialized; |
4900 // Registers will be used as follows: | 4859 // Registers will be used as follows: |
4901 // rcx = literals array. | 4860 // rcx = literals array. |
4902 // rbx = regexp literal. | 4861 // rbx = regexp literal. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4959 __ Push(shared_info); | 4918 __ Push(shared_info); |
4960 __ PushRoot(pretenure ? | 4919 __ PushRoot(pretenure ? |
4961 Heap::kTrueValueRootIndex : | 4920 Heap::kTrueValueRootIndex : |
4962 Heap::kFalseValueRootIndex); | 4921 Heap::kFalseValueRootIndex); |
4963 CallRuntime(Runtime::kNewClosure, 3, instr); | 4922 CallRuntime(Runtime::kNewClosure, 3, instr); |
4964 } | 4923 } |
4965 } | 4924 } |
4966 | 4925 |
4967 | 4926 |
4968 void LCodeGen::DoTypeof(LTypeof* instr) { | 4927 void LCodeGen::DoTypeof(LTypeof* instr) { |
4969 LOperand* input = instr->value(); | 4928 LOperand* input = instr->InputAt(0); |
4970 EmitPushTaggedOperand(input); | 4929 EmitPushTaggedOperand(input); |
4971 CallRuntime(Runtime::kTypeof, 1, instr); | 4930 CallRuntime(Runtime::kTypeof, 1, instr); |
4972 } | 4931 } |
4973 | 4932 |
4974 | 4933 |
4975 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 4934 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
4976 ASSERT(!operand->IsDoubleRegister()); | 4935 ASSERT(!operand->IsDoubleRegister()); |
4977 if (operand->IsConstantOperand()) { | 4936 if (operand->IsConstantOperand()) { |
4978 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); | 4937 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); |
4979 if (object->IsSmi()) { | 4938 if (object->IsSmi()) { |
4980 __ Push(Handle<Smi>::cast(object)); | 4939 __ Push(Handle<Smi>::cast(object)); |
4981 } else { | 4940 } else { |
4982 __ PushHeapObject(Handle<HeapObject>::cast(object)); | 4941 __ PushHeapObject(Handle<HeapObject>::cast(object)); |
4983 } | 4942 } |
4984 } else if (operand->IsRegister()) { | 4943 } else if (operand->IsRegister()) { |
4985 __ push(ToRegister(operand)); | 4944 __ push(ToRegister(operand)); |
4986 } else { | 4945 } else { |
4987 __ push(ToOperand(operand)); | 4946 __ push(ToOperand(operand)); |
4988 } | 4947 } |
4989 } | 4948 } |
4990 | 4949 |
4991 | 4950 |
4992 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4951 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
4993 Register input = ToRegister(instr->value()); | 4952 Register input = ToRegister(instr->InputAt(0)); |
4994 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4953 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4995 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4954 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4996 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4955 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
4997 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4956 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
4998 | 4957 |
4999 Condition final_branch_condition = | 4958 Condition final_branch_condition = |
5000 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); | 4959 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); |
5001 if (final_branch_condition != no_condition) { | 4960 if (final_branch_condition != no_condition) { |
5002 EmitBranch(true_block, false_block, final_branch_condition); | 4961 EmitBranch(true_block, false_block, final_branch_condition); |
5003 } | 4962 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5069 | 5028 |
5070 } else { | 5029 } else { |
5071 __ jmp(false_label); | 5030 __ jmp(false_label); |
5072 } | 5031 } |
5073 | 5032 |
5074 return final_branch_condition; | 5033 return final_branch_condition; |
5075 } | 5034 } |
5076 | 5035 |
5077 | 5036 |
5078 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5037 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
5079 Register temp = ToRegister(instr->temp()); | 5038 Register temp = ToRegister(instr->TempAt(0)); |
5080 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5039 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
5081 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5040 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
5082 | 5041 |
5083 EmitIsConstructCall(temp); | 5042 EmitIsConstructCall(temp); |
5084 EmitBranch(true_block, false_block, equal); | 5043 EmitBranch(true_block, false_block, equal); |
5085 } | 5044 } |
5086 | 5045 |
5087 | 5046 |
5088 void LCodeGen::EmitIsConstructCall(Register temp) { | 5047 void LCodeGen::EmitIsConstructCall(Register temp) { |
5089 // Get the frame pointer for the calling frame. | 5048 // Get the frame pointer for the calling frame. |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5322 FixedArray::kHeaderSize - kPointerSize)); | 5281 FixedArray::kHeaderSize - kPointerSize)); |
5323 __ bind(&done); | 5282 __ bind(&done); |
5324 } | 5283 } |
5325 | 5284 |
5326 | 5285 |
5327 #undef __ | 5286 #undef __ |
5328 | 5287 |
5329 } } // namespace v8::internal | 5288 } } // namespace v8::internal |
5330 | 5289 |
5331 #endif // V8_TARGET_ARCH_X64 | 5290 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |