Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1051 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1051 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
| 1052 // tagged as a small integer. | 1052 // tagged as a small integer. |
| 1053 frame_->EmitPush(r0); | 1053 frame_->EmitPush(r0); |
| 1054 Result arg_count_register = allocator_->Allocate(r0); | 1054 Result arg_count_register = allocator_->Allocate(r0); |
| 1055 ASSERT(arg_count_register.is_valid()); | 1055 ASSERT(arg_count_register.is_valid()); |
| 1056 __ mov(arg_count_register.reg(), Operand(arg_count)); | 1056 __ mov(arg_count_register.reg(), Operand(arg_count)); |
| 1057 Result result = frame_->InvokeBuiltin(native, | 1057 Result result = frame_->InvokeBuiltin(native, |
| 1058 CALL_JS, | 1058 CALL_JS, |
| 1059 &arg_count_register, | 1059 &arg_count_register, |
| 1060 arg_count + 1); | 1060 arg_count + 1); |
| 1061 __ cmp(result.reg(), Operand(0)); | 1061 __ cmp(result.reg(), Operand(0, RelocInfo::NONE)); |
| 1062 result.Unuse(); | 1062 result.Unuse(); |
| 1063 exit.Jump(); | 1063 exit.Jump(); |
| 1064 | 1064 |
| 1065 // test smi equality by pointer comparison. | 1065 // test smi equality by pointer comparison. |
| 1066 smi.Bind(); | 1066 smi.Bind(); |
| 1067 __ cmp(r1, Operand(r0)); | 1067 __ cmp(r1, Operand(r0)); |
| 1068 | 1068 |
| 1069 exit.Bind(); | 1069 exit.Bind(); |
| 1070 cc_reg_ = cc; | 1070 cc_reg_ = cc; |
| 1071 } | 1071 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1228 // Push initial value, if any. | 1228 // Push initial value, if any. |
| 1229 // Note: For variables we must not push an initial value (such as | 1229 // Note: For variables we must not push an initial value (such as |
| 1230 // 'undefined') because we may have a (legal) redeclaration and we | 1230 // 'undefined') because we may have a (legal) redeclaration and we |
| 1231 // must not destroy the current value. | 1231 // must not destroy the current value. |
| 1232 if (node->mode() == Variable::CONST) { | 1232 if (node->mode() == Variable::CONST) { |
| 1233 __ mov(r0, Operand(Factory::the_hole_value())); | 1233 __ mov(r0, Operand(Factory::the_hole_value())); |
| 1234 frame_->EmitPush(r0); | 1234 frame_->EmitPush(r0); |
| 1235 } else if (node->fun() != NULL) { | 1235 } else if (node->fun() != NULL) { |
| 1236 LoadAndSpill(node->fun()); | 1236 LoadAndSpill(node->fun()); |
| 1237 } else { | 1237 } else { |
| 1238 __ mov(r0, Operand(0)); // no initial value! | 1238 __ mov(r0, Operand(0, RelocInfo::NONE)); // no initial value! |
| 1239 frame_->EmitPush(r0); | 1239 frame_->EmitPush(r0); |
| 1240 } | 1240 } |
| 1241 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); | 1241 frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 1242 // Ignore the return value (declarations are statements). | 1242 // Ignore the return value (declarations are statements). |
| 1243 ASSERT(frame_->height() == original_height); | 1243 ASSERT(frame_->height() == original_height); |
| 1244 return; | 1244 return; |
| 1245 } | 1245 } |
| 1246 | 1246 |
| 1247 ASSERT(!var->is_global()); | 1247 ASSERT(!var->is_global()); |
| 1248 | 1248 |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1870 // Check if enumerable is already a JSObject | 1870 // Check if enumerable is already a JSObject |
| 1871 __ tst(r0, Operand(kSmiTagMask)); | 1871 __ tst(r0, Operand(kSmiTagMask)); |
| 1872 primitive.Branch(eq); | 1872 primitive.Branch(eq); |
| 1873 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 1873 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
| 1874 jsobject.Branch(hs); | 1874 jsobject.Branch(hs); |
| 1875 | 1875 |
| 1876 primitive.Bind(); | 1876 primitive.Bind(); |
| 1877 frame_->EmitPush(r0); | 1877 frame_->EmitPush(r0); |
| 1878 Result arg_count = allocator_->Allocate(r0); | 1878 Result arg_count = allocator_->Allocate(r0); |
| 1879 ASSERT(arg_count.is_valid()); | 1879 ASSERT(arg_count.is_valid()); |
| 1880 __ mov(arg_count.reg(), Operand(0)); | 1880 __ mov(arg_count.reg(), Operand(0, RelocInfo::NONE)); |
| 1881 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1); | 1881 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1); |
| 1882 | 1882 |
| 1883 jsobject.Bind(); | 1883 jsobject.Bind(); |
| 1884 // Get the set of properties (as a FixedArray or Map). | 1884 // Get the set of properties (as a FixedArray or Map). |
| 1885 frame_->EmitPush(r0); // duplicate the object being enumerated | 1885 frame_->EmitPush(r0); // duplicate the object being enumerated |
| 1886 frame_->EmitPush(r0); | 1886 frame_->EmitPush(r0); |
| 1887 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1887 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); |
| 1888 | 1888 |
| 1889 // If we got a Map, we can do a fast modification check. | 1889 // If we got a Map, we can do a fast modification check. |
| 1890 // Otherwise, we got a FixedArray, and we have to do a slow check. | 1890 // Otherwise, we got a FixedArray, and we have to do a slow check. |
| (...skipping 1673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3564 case Token::BIT_NOT: { | 3564 case Token::BIT_NOT: { |
| 3565 // smi check | 3565 // smi check |
| 3566 JumpTarget smi_label; | 3566 JumpTarget smi_label; |
| 3567 JumpTarget continue_label; | 3567 JumpTarget continue_label; |
| 3568 __ tst(r0, Operand(kSmiTagMask)); | 3568 __ tst(r0, Operand(kSmiTagMask)); |
| 3569 smi_label.Branch(eq); | 3569 smi_label.Branch(eq); |
| 3570 | 3570 |
| 3571 frame_->EmitPush(r0); | 3571 frame_->EmitPush(r0); |
| 3572 Result arg_count = allocator_->Allocate(r0); | 3572 Result arg_count = allocator_->Allocate(r0); |
| 3573 ASSERT(arg_count.is_valid()); | 3573 ASSERT(arg_count.is_valid()); |
| 3574 __ mov(arg_count.reg(), Operand(0)); // not counting receiver | 3574 // not counting receiver |
|
William Hesse
2009/06/15 08:59:29
// Argument count does not include the receiver.
C
| |
| 3575 __ mov(arg_count.reg(), Operand(0, RelocInfo::NONE)); | |
| 3575 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1); | 3576 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1); |
| 3576 | 3577 |
| 3577 continue_label.Jump(); | 3578 continue_label.Jump(); |
| 3578 smi_label.Bind(); | 3579 smi_label.Bind(); |
| 3579 __ mvn(r0, Operand(r0)); | 3580 __ mvn(r0, Operand(r0)); |
| 3580 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag | 3581 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag |
| 3581 continue_label.Bind(); | 3582 continue_label.Bind(); |
| 3582 break; | 3583 break; |
| 3583 } | 3584 } |
| 3584 | 3585 |
| 3585 case Token::VOID: | 3586 case Token::VOID: |
| 3586 // since the stack top is cached in r0, popping and then | 3587 // since the stack top is cached in r0, popping and then |
| 3587 // pushing a value can be done by just writing to r0. | 3588 // pushing a value can be done by just writing to r0. |
| 3588 __ mov(r0, Operand(Factory::undefined_value())); | 3589 __ mov(r0, Operand(Factory::undefined_value())); |
| 3589 break; | 3590 break; |
| 3590 | 3591 |
| 3591 case Token::ADD: { | 3592 case Token::ADD: { |
| 3592 // Smi check. | 3593 // Smi check. |
| 3593 JumpTarget continue_label; | 3594 JumpTarget continue_label; |
| 3594 __ tst(r0, Operand(kSmiTagMask)); | 3595 __ tst(r0, Operand(kSmiTagMask)); |
| 3595 continue_label.Branch(eq); | 3596 continue_label.Branch(eq); |
| 3596 frame_->EmitPush(r0); | 3597 frame_->EmitPush(r0); |
| 3597 Result arg_count = allocator_->Allocate(r0); | 3598 Result arg_count = allocator_->Allocate(r0); |
| 3598 ASSERT(arg_count.is_valid()); | 3599 ASSERT(arg_count.is_valid()); |
| 3599 __ mov(arg_count.reg(), Operand(0)); // not counting receiver | 3600 // not counting receiver |
| 3601 __ mov(arg_count.reg(), Operand(0, RelocInfo::NONE)); | |
| 3600 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); | 3602 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); |
| 3601 continue_label.Bind(); | 3603 continue_label.Bind(); |
| 3602 break; | 3604 break; |
| 3603 } | 3605 } |
| 3604 default: | 3606 default: |
| 3605 UNREACHABLE(); | 3607 UNREACHABLE(); |
| 3606 } | 3608 } |
| 3607 frame_->EmitPush(r0); // r0 has result | 3609 frame_->EmitPush(r0); // r0 has result |
| 3608 } | 3610 } |
| 3609 ASSERT((has_cc() && frame_->height() == original_height) || | 3611 ASSERT((has_cc() && frame_->height() == original_height) || |
| 3610 (!has_cc() && frame_->height() == original_height + 1)); | 3612 (!has_cc() && frame_->height() == original_height + 1)); |
| 3611 } | 3613 } |
| 3612 | 3614 |
| 3613 | 3615 |
| 3614 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 3616 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
| 3615 #ifdef DEBUG | 3617 #ifdef DEBUG |
| 3616 int original_height = frame_->height(); | 3618 int original_height = frame_->height(); |
| 3617 #endif | 3619 #endif |
| 3618 VirtualFrame::SpilledScope spilled_scope; | 3620 VirtualFrame::SpilledScope spilled_scope; |
| 3619 Comment cmnt(masm_, "[ CountOperation"); | 3621 Comment cmnt(masm_, "[ CountOperation"); |
| 3620 | 3622 |
| 3621 bool is_postfix = node->is_postfix(); | 3623 bool is_postfix = node->is_postfix(); |
| 3622 bool is_increment = node->op() == Token::INC; | 3624 bool is_increment = node->op() == Token::INC; |
| 3623 | 3625 |
| 3624 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 3626 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); |
| 3625 bool is_const = (var != NULL && var->mode() == Variable::CONST); | 3627 bool is_const = (var != NULL && var->mode() == Variable::CONST); |
| 3626 | 3628 |
| 3627 // Postfix: Make room for the result. | 3629 // Postfix: Make room for the result. |
| 3628 if (is_postfix) { | 3630 if (is_postfix) { |
| 3629 __ mov(r0, Operand(0)); | 3631 __ mov(r0, Operand(0, RelocInfo::NONE)); |
| 3630 frame_->EmitPush(r0); | 3632 frame_->EmitPush(r0); |
| 3631 } | 3633 } |
| 3632 | 3634 |
| 3633 { Reference target(this, node->expression()); | 3635 { Reference target(this, node->expression()); |
| 3634 if (target.is_illegal()) { | 3636 if (target.is_illegal()) { |
| 3635 // Spoof the virtual frame to have the expected height (one higher | 3637 // Spoof the virtual frame to have the expected height (one higher |
| 3636 // than on entry). | 3638 // than on entry). |
| 3637 if (!is_postfix) { | 3639 if (!is_postfix) { |
| 3638 __ mov(r0, Operand(Smi::FromInt(0))); | 3640 __ mov(r0, Operand(Smi::FromInt(0))); |
| 3639 frame_->EmitPush(r0); | 3641 frame_->EmitPush(r0); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3676 __ add(r0, r0, Operand(r1)); | 3678 __ add(r0, r0, Operand(r1)); |
| 3677 } | 3679 } |
| 3678 | 3680 |
| 3679 // Slow case: Convert to number. | 3681 // Slow case: Convert to number. |
| 3680 slow.Bind(); | 3682 slow.Bind(); |
| 3681 { | 3683 { |
| 3682 // Convert the operand to a number. | 3684 // Convert the operand to a number. |
| 3683 frame_->EmitPush(r0); | 3685 frame_->EmitPush(r0); |
| 3684 Result arg_count = allocator_->Allocate(r0); | 3686 Result arg_count = allocator_->Allocate(r0); |
| 3685 ASSERT(arg_count.is_valid()); | 3687 ASSERT(arg_count.is_valid()); |
| 3686 __ mov(arg_count.reg(), Operand(0)); | 3688 __ mov(arg_count.reg(), Operand(0, RelocInfo::NONE)); |
| 3687 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); | 3689 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1); |
| 3688 } | 3690 } |
| 3689 if (is_postfix) { | 3691 if (is_postfix) { |
| 3690 // Postfix: store to result (on the stack). | 3692 // Postfix: store to result (on the stack). |
| 3691 __ str(r0, frame_->ElementAt(target.size())); | 3693 __ str(r0, frame_->ElementAt(target.size())); |
| 3692 } | 3694 } |
| 3693 | 3695 |
| 3694 // Compute the new value. | 3696 // Compute the new value. |
| 3695 __ mov(r1, Operand(Smi::FromInt(1))); | 3697 __ mov(r1, Operand(Smi::FromInt(1))); |
| 3696 frame_->EmitPush(r0); | 3698 frame_->EmitPush(r0); |
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4324 // instruction. On pre-ARM5 hardware this routine gives the wrong answer for 0 | 4326 // instruction. On pre-ARM5 hardware this routine gives the wrong answer for 0 |
| 4325 // (31 instead of 32). | 4327 // (31 instead of 32). |
| 4326 static void CountLeadingZeros( | 4328 static void CountLeadingZeros( |
| 4327 MacroAssembler* masm, | 4329 MacroAssembler* masm, |
| 4328 Register source, | 4330 Register source, |
| 4329 Register scratch, | 4331 Register scratch, |
| 4330 Register zeros) { | 4332 Register zeros) { |
| 4331 #ifdef __ARM_ARCH_5__ | 4333 #ifdef __ARM_ARCH_5__ |
| 4332 __ clz(zeros, source); // This instruction is only supported after ARM5. | 4334 __ clz(zeros, source); // This instruction is only supported after ARM5. |
| 4333 #else | 4335 #else |
| 4334 __ mov(zeros, Operand(0)); | 4336 __ mov(zeros, Operand(0, RelocInfo::NONE)); |
| 4335 __ mov(scratch, source); | 4337 __ mov(scratch, source); |
| 4336 // Top 16. | 4338 // Top 16. |
| 4337 __ tst(scratch, Operand(0xffff0000)); | 4339 __ tst(scratch, Operand(0xffff0000)); |
| 4338 __ add(zeros, zeros, Operand(16), LeaveCC, eq); | 4340 __ add(zeros, zeros, Operand(16), LeaveCC, eq); |
| 4339 __ mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq); | 4341 __ mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq); |
| 4340 // Top 8. | 4342 // Top 8. |
| 4341 __ tst(scratch, Operand(0xff000000)); | 4343 __ tst(scratch, Operand(0xff000000)); |
| 4342 __ add(zeros, zeros, Operand(8), LeaveCC, eq); | 4344 __ add(zeros, zeros, Operand(8), LeaveCC, eq); |
| 4343 __ mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq); | 4345 __ mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq); |
| 4344 // Top 4. | 4346 // Top 4. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4411 #endif | 4413 #endif |
| 4412 Label not_special; | 4414 Label not_special; |
| 4413 // Convert from Smi to integer. | 4415 // Convert from Smi to integer. |
| 4414 __ mov(source_, Operand(source_, ASR, kSmiTagSize)); | 4416 __ mov(source_, Operand(source_, ASR, kSmiTagSize)); |
| 4415 // Move sign bit from source to destination. This works because the sign bit | 4417 // Move sign bit from source to destination. This works because the sign bit |
| 4416 // in the exponent word of the double has the same position and polarity as | 4418 // in the exponent word of the double has the same position and polarity as |
| 4417 // the 2's complement sign bit in a Smi. | 4419 // the 2's complement sign bit in a Smi. |
| 4418 ASSERT(HeapNumber::kSignMask == 0x80000000u); | 4420 ASSERT(HeapNumber::kSignMask == 0x80000000u); |
| 4419 __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC); | 4421 __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC); |
| 4420 // Subtract from 0 if source was negative. | 4422 // Subtract from 0 if source was negative. |
| 4421 __ rsb(source_, source_, Operand(0), LeaveCC, ne); | 4423 __ rsb(source_, source_, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
| 4422 __ cmp(source_, Operand(1)); | 4424 __ cmp(source_, Operand(1)); |
| 4423 __ b(gt, ¬_special); | 4425 __ b(gt, ¬_special); |
| 4424 | 4426 |
| 4425 // We have -1, 0 or 1, which we treat specially. | 4427 // We have -1, 0 or 1, which we treat specially. |
| 4426 __ cmp(source_, Operand(0)); | 4428 __ cmp(source_, Operand(0, RelocInfo::NONE)); |
| 4427 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). | 4429 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). |
| 4428 static const uint32_t exponent_word_for_1 = | 4430 static const uint32_t exponent_word_for_1 = |
| 4429 HeapNumber::kExponentBias << HeapNumber::kExponentShift; | 4431 HeapNumber::kExponentBias << HeapNumber::kExponentShift; |
| 4430 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, ne); | 4432 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, ne); |
| 4431 // 1, 0 and -1 all have 0 for the second word. | 4433 // 1, 0 and -1 all have 0 for the second word. |
| 4432 __ mov(mantissa, Operand(0)); | 4434 __ mov(mantissa, Operand(0, RelocInfo::NONE)); |
| 4433 __ Ret(); | 4435 __ Ret(); |
| 4434 | 4436 |
| 4435 __ bind(¬_special); | 4437 __ bind(¬_special); |
| 4436 // Count leading zeros. Uses result2 for a scratch register on pre-ARM5. | 4438 // Count leading zeros. Uses result2 for a scratch register on pre-ARM5. |
| 4437 // Gets the wrong answer for 0, but we already checked for that case above. | 4439 // Gets the wrong answer for 0, but we already checked for that case above. |
| 4438 CountLeadingZeros(masm, source_, mantissa, zeros_); | 4440 CountLeadingZeros(masm, source_, mantissa, zeros_); |
| 4439 // Compute exponent and or it into the exponent register. | 4441 // Compute exponent and or it into the exponent register. |
| 4440 // We use result2 as a scratch register here. | 4442 // We use result2 as a scratch register here. |
| 4441 __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias)); | 4443 __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias)); |
| 4442 __ orr(exponent, | 4444 __ orr(exponent, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4505 __ cmp(the_int_, Operand(0x80000000)); | 4507 __ cmp(the_int_, Operand(0x80000000)); |
| 4506 __ b(eq, &max_negative_int); | 4508 __ b(eq, &max_negative_int); |
| 4507 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. | 4509 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. |
| 4508 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). | 4510 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). |
| 4509 uint32_t non_smi_exponent = | 4511 uint32_t non_smi_exponent = |
| 4510 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; | 4512 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; |
| 4511 __ mov(scratch_, Operand(non_smi_exponent)); | 4513 __ mov(scratch_, Operand(non_smi_exponent)); |
| 4512 // Set the sign bit in scratch_ if the value was negative. | 4514 // Set the sign bit in scratch_ if the value was negative. |
| 4513 __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs); | 4515 __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs); |
| 4514 // Subtract from 0 if the value was negative. | 4516 // Subtract from 0 if the value was negative. |
| 4515 __ rsb(the_int_, the_int_, Operand(0), LeaveCC, cs); | 4517 __ rsb(the_int_, the_int_, Operand(0, RelocInfo::NONE), LeaveCC, cs); |
| 4516 // We should be masking the implict first digit of the mantissa away here, | 4518 // We should be masking the implict first digit of the mantissa away here, |
| 4517 // but it just ends up combining harmlessly with the last digit of the | 4519 // but it just ends up combining harmlessly with the last digit of the |
| 4518 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get | 4520 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get |
| 4519 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. | 4521 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. |
| 4520 ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); | 4522 ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); |
| 4521 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; | 4523 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; |
| 4522 __ orr(scratch_, scratch_, Operand(the_int_, LSR, shift_distance)); | 4524 __ orr(scratch_, scratch_, Operand(the_int_, LSR, shift_distance)); |
| 4523 __ str(scratch_, FieldMemOperand(the_heap_number_, | 4525 __ str(scratch_, FieldMemOperand(the_heap_number_, |
| 4524 HeapNumber::kExponentOffset)); | 4526 HeapNumber::kExponentOffset)); |
| 4525 __ mov(scratch_, Operand(the_int_, LSL, 32 - shift_distance)); | 4527 __ mov(scratch_, Operand(the_int_, LSL, 32 - shift_distance)); |
| 4526 __ str(scratch_, FieldMemOperand(the_heap_number_, | 4528 __ str(scratch_, FieldMemOperand(the_heap_number_, |
| 4527 HeapNumber::kMantissaOffset)); | 4529 HeapNumber::kMantissaOffset)); |
| 4528 __ Ret(); | 4530 __ Ret(); |
| 4529 | 4531 |
| 4530 __ bind(&max_negative_int); | 4532 __ bind(&max_negative_int); |
| 4531 // The max negative int32 is stored as a positive number in the mantissa of | 4533 // The max negative int32 is stored as a positive number in the mantissa of |
| 4532 // a double because it uses a sign bit instead of using two's complement. | 4534 // a double because it uses a sign bit instead of using two's complement. |
| 4533 // The actual mantissa bits stored are all 0 because the implicit most | 4535 // The actual mantissa bits stored are all 0 because the implicit most |
| 4534 // significant 1 bit is not stored. | 4536 // significant 1 bit is not stored. |
| 4535 non_smi_exponent += 1 << HeapNumber::kExponentShift; | 4537 non_smi_exponent += 1 << HeapNumber::kExponentShift; |
| 4536 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); | 4538 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); |
| 4537 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); | 4539 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); |
| 4538 __ mov(ip, Operand(0)); | 4540 __ mov(ip, Operand(0, RelocInfo::NONE)); |
| 4539 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); | 4541 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); |
| 4540 __ Ret(); | 4542 __ Ret(); |
| 4541 } | 4543 } |
| 4542 | 4544 |
| 4543 | 4545 |
| 4544 // Allocates a heap number or jumps to the label if the young space is full and | 4546 // Allocates a heap number or jumps to the label if the young space is full and |
| 4545 // a scavenge is needed. | 4547 // a scavenge is needed. |
| 4546 static void AllocateHeapNumber( | 4548 static void AllocateHeapNumber( |
| 4547 MacroAssembler* masm, | 4549 MacroAssembler* masm, |
| 4548 Label* need_gc, // Jump here if young space is full. | 4550 Label* need_gc, // Jump here if young space is full. |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4734 // leave the sign bit 0 so we subtract 2 bits from the shift distance. | 4736 // leave the sign bit 0 so we subtract 2 bits from the shift distance. |
| 4735 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; | 4737 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; |
| 4736 __ mov(scratch2, Operand(scratch2, LSL, shift_distance)); | 4738 __ mov(scratch2, Operand(scratch2, LSL, shift_distance)); |
| 4737 // Put sign in zero flag. | 4739 // Put sign in zero flag. |
| 4738 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 4740 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
| 4739 // Get the second half of the double. | 4741 // Get the second half of the double. |
| 4740 __ ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset)); | 4742 __ ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset)); |
| 4741 // Shift down 22 bits to get the last 10 bits. | 4743 // Shift down 22 bits to get the last 10 bits. |
| 4742 __ orr(dest, scratch2, Operand(scratch, LSR, 32 - shift_distance)); | 4744 __ orr(dest, scratch2, Operand(scratch, LSR, 32 - shift_distance)); |
| 4743 // Fix sign if sign bit was set. | 4745 // Fix sign if sign bit was set. |
| 4744 __ rsb(dest, dest, Operand(0), LeaveCC, ne); | 4746 __ rsb(dest, dest, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
| 4745 } | 4747 } |
| 4746 | 4748 |
| 4747 | 4749 |
| 4748 // For bitwise ops where the inputs are not both Smis we here try to determine | 4750 // For bitwise ops where the inputs are not both Smis we here try to determine |
| 4749 // whether both inputs are either Smis or at least heap numbers that can be | 4751 // whether both inputs are either Smis or at least heap numbers that can be |
| 4750 // represented by a 32 bit signed value. We truncate towards zero as required | 4752 // represented by a 32 bit signed value. We truncate towards zero as required |
| 4751 // by the ES spec. If this is the case we do the bitwise op and see if the | 4753 // by the ES spec. If this is the case we do the bitwise op and see if the |
| 4752 // result is a Smi. If so, great, otherwise we try to find a heap number to | 4754 // result is a Smi. If so, great, otherwise we try to find a heap number to |
| 4753 // write the answer into (either by allocating or by overwriting). | 4755 // write the answer into (either by allocating or by overwriting). |
| 4754 // On entry the operands are in r0 and r1. On exit the answer is in r0. | 4756 // On entry the operands are in r0 and r1. On exit the answer is in r0. |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5045 Label slow; | 5047 Label slow; |
| 5046 Label done; | 5048 Label done; |
| 5047 Label not_smi; | 5049 Label not_smi; |
| 5048 | 5050 |
| 5049 // Enter runtime system if the value is not a smi. | 5051 // Enter runtime system if the value is not a smi. |
| 5050 __ tst(r0, Operand(kSmiTagMask)); | 5052 __ tst(r0, Operand(kSmiTagMask)); |
| 5051 __ b(ne, ¬_smi); | 5053 __ b(ne, ¬_smi); |
| 5052 | 5054 |
| 5053 // Enter runtime system if the value of the expression is zero | 5055 // Enter runtime system if the value of the expression is zero |
| 5054 // to make sure that we switch between 0 and -0. | 5056 // to make sure that we switch between 0 and -0. |
| 5055 __ cmp(r0, Operand(0)); | 5057 __ cmp(r0, Operand(0, RelocInfo::NONE)); |
| 5056 __ b(eq, &slow); | 5058 __ b(eq, &slow); |
| 5057 | 5059 |
| 5058 // The value of the expression is a smi that is not zero. Try | 5060 // The value of the expression is a smi that is not zero. Try |
| 5059 // optimistic subtraction '0 - value'. | 5061 // optimistic subtraction '0 - value'. |
| 5060 __ rsb(r1, r0, Operand(0), SetCC); | 5062 __ rsb(r1, r0, Operand(0, RelocInfo::NONE), SetCC); |
| 5061 __ b(vs, &slow); | 5063 __ b(vs, &slow); |
| 5062 | 5064 |
| 5063 __ mov(r0, Operand(r1)); // Set r0 to result. | 5065 __ mov(r0, Operand(r1)); // Set r0 to result. |
| 5064 __ StubReturn(1); | 5066 __ StubReturn(1); |
| 5065 | 5067 |
| 5066 // Enter runtime system. | 5068 // Enter runtime system. |
| 5067 __ bind(&slow); | 5069 __ bind(&slow); |
| 5068 __ push(r0); | 5070 __ push(r0); |
| 5069 __ mov(r0, Operand(0)); // Set number of arguments. | 5071 __ mov(r0, Operand(0, RelocInfo::NONE)); // Set number of arguments. |
| 5070 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); | 5072 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS); |
| 5071 | 5073 |
| 5072 __ bind(&done); | 5074 __ bind(&done); |
| 5073 __ StubReturn(1); | 5075 __ StubReturn(1); |
| 5074 | 5076 |
| 5075 __ bind(¬_smi); | 5077 __ bind(¬_smi); |
| 5076 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); | 5078 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); |
| 5077 __ b(ne, &slow); | 5079 __ b(ne, &slow); |
| 5078 // r0 is a heap number. Get a new heap number in r1. | 5080 // r0 is a heap number. Get a new heap number in r1. |
| 5079 if (overwrite_) { | 5081 if (overwrite_) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 5106 // Restore the next handler and frame pointer, discard handler state. | 5108 // Restore the next handler and frame pointer, discard handler state. |
| 5107 ASSERT(StackHandlerConstants::kNextOffset == 0); | 5109 ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 5108 __ pop(r2); | 5110 __ pop(r2); |
| 5109 __ str(r2, MemOperand(r3)); | 5111 __ str(r2, MemOperand(r3)); |
| 5110 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 5112 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
| 5111 __ ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. | 5113 __ ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state. |
| 5112 | 5114 |
| 5113 // Before returning we restore the context from the frame pointer if | 5115 // Before returning we restore the context from the frame pointer if |
| 5114 // not NULL. The frame pointer is NULL in the exception handler of a | 5116 // not NULL. The frame pointer is NULL in the exception handler of a |
| 5115 // JS entry frame. | 5117 // JS entry frame. |
| 5116 __ cmp(fp, Operand(0)); | 5118 __ cmp(fp, Operand(0, RelocInfo::NONE)); |
| 5117 // Set cp to NULL if fp is NULL. | 5119 // Set cp to NULL if fp is NULL. |
| 5118 __ mov(cp, Operand(0), LeaveCC, eq); | 5120 __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 5119 // Restore cp otherwise. | 5121 // Restore cp otherwise. |
| 5120 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | 5122 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
| 5121 #ifdef DEBUG | 5123 #ifdef DEBUG |
| 5122 if (FLAG_debug_code) { | 5124 if (FLAG_debug_code) { |
| 5123 __ mov(lr, Operand(pc)); | 5125 __ mov(lr, Operand(pc)); |
| 5124 } | 5126 } |
| 5125 #endif | 5127 #endif |
| 5126 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | 5128 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 5127 __ pop(pc); | 5129 __ pop(pc); |
| 5128 } | 5130 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 5150 __ jmp(&loop); | 5152 __ jmp(&loop); |
| 5151 __ bind(&done); | 5153 __ bind(&done); |
| 5152 | 5154 |
| 5153 // Set the top handler address to next handler past the current ENTRY handler. | 5155 // Set the top handler address to next handler past the current ENTRY handler. |
| 5154 ASSERT(StackHandlerConstants::kNextOffset == 0); | 5156 ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 5155 __ pop(r0); | 5157 __ pop(r0); |
| 5156 __ str(r0, MemOperand(r3)); | 5158 __ str(r0, MemOperand(r3)); |
| 5157 | 5159 |
| 5158 // Set external caught exception to false. | 5160 // Set external caught exception to false. |
| 5159 ExternalReference external_caught(Top::k_external_caught_exception_address); | 5161 ExternalReference external_caught(Top::k_external_caught_exception_address); |
| 5160 __ mov(r0, Operand(false)); | 5162 __ mov(r0, Operand(0, RelocInfo::NONE)); |
| 5161 __ mov(r2, Operand(external_caught)); | 5163 __ mov(r2, Operand(external_caught)); |
| 5162 __ str(r0, MemOperand(r2)); | 5164 __ str(r0, MemOperand(r2)); |
| 5163 | 5165 |
| 5164 // Set pending exception and r0 to out of memory exception. | 5166 // Set pending exception and r0 to out of memory exception. |
| 5165 Failure* out_of_memory = Failure::OutOfMemoryException(); | 5167 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| 5166 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 5168 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| 5167 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); | 5169 __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address))); |
| 5168 __ str(r0, MemOperand(r2)); | 5170 __ str(r0, MemOperand(r2)); |
| 5169 | 5171 |
| 5170 // Stack layout at this point. See also StackHandlerConstants. | 5172 // Stack layout at this point. See also StackHandlerConstants. |
| 5171 // sp -> state (ENTRY) | 5173 // sp -> state (ENTRY) |
| 5172 // fp | 5174 // fp |
| 5173 // lr | 5175 // lr |
| 5174 | 5176 |
| 5175 // Discard handler state (r2 is not used) and restore frame pointer. | 5177 // Discard handler state (r2 is not used) and restore frame pointer. |
| 5176 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | 5178 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
| 5177 __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. | 5179 __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state. |
| 5178 // Before returning we restore the context from the frame pointer if | 5180 // Before returning we restore the context from the frame pointer if |
| 5179 // not NULL. The frame pointer is NULL in the exception handler of a | 5181 // not NULL. The frame pointer is NULL in the exception handler of a |
| 5180 // JS entry frame. | 5182 // JS entry frame. |
| 5181 __ cmp(fp, Operand(0)); | 5183 __ cmp(fp, Operand(0, RelocInfo::NONE)); |
| 5182 // Set cp to NULL if fp is NULL. | 5184 // Set cp to NULL if fp is NULL. |
| 5183 __ mov(cp, Operand(0), LeaveCC, eq); | 5185 __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 5184 // Restore cp otherwise. | 5186 // Restore cp otherwise. |
| 5185 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); | 5187 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne); |
| 5186 #ifdef DEBUG | 5188 #ifdef DEBUG |
| 5187 if (FLAG_debug_code) { | 5189 if (FLAG_debug_code) { |
| 5188 __ mov(lr, Operand(pc)); | 5190 __ mov(lr, Operand(pc)); |
| 5189 } | 5191 } |
| 5190 #endif | 5192 #endif |
| 5191 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | 5193 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 5192 __ pop(pc); | 5194 __ pop(pc); |
| 5193 } | 5195 } |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5643 __ b(ne, &slow); | 5645 __ b(ne, &slow); |
| 5644 | 5646 |
| 5645 // Fast-case: Invoke the function now. | 5647 // Fast-case: Invoke the function now. |
| 5646 // r1: pushed function | 5648 // r1: pushed function |
| 5647 ParameterCount actual(argc_); | 5649 ParameterCount actual(argc_); |
| 5648 __ InvokeFunction(r1, actual, JUMP_FUNCTION); | 5650 __ InvokeFunction(r1, actual, JUMP_FUNCTION); |
| 5649 | 5651 |
| 5650 // Slow-case: Non-function called. | 5652 // Slow-case: Non-function called. |
| 5651 __ bind(&slow); | 5653 __ bind(&slow); |
| 5652 __ mov(r0, Operand(argc_)); // Setup the number of arguments. | 5654 __ mov(r0, Operand(argc_)); // Setup the number of arguments. |
| 5653 __ mov(r2, Operand(0)); | 5655 __ mov(r2, Operand(0, RelocInfo::NONE)); |
| 5654 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5656 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
| 5655 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 5657 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
| 5656 RelocInfo::CODE_TARGET); | 5658 RelocInfo::CODE_TARGET); |
| 5657 } | 5659 } |
| 5658 | 5660 |
| 5659 | 5661 |
| 5660 #undef __ | 5662 #undef __ |
| 5661 | 5663 |
| 5662 } } // namespace v8::internal | 5664 } } // namespace v8::internal |
| OLD | NEW |