| 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 |