Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 2819012: X64: Load HeapNumberMap once in BinaryOpStub, and reuse it. (Closed)
Patch Set: Addressed review comments Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 // Returns operands as floating point numbers on fp stack. 307 // Returns operands as floating point numbers on fp stack.
308 static void LoadFloatOperands(MacroAssembler* masm, 308 static void LoadFloatOperands(MacroAssembler* masm,
309 Register lhs, 309 Register lhs,
310 Register rhs); 310 Register rhs);
311 311
312 // Test if operands are smi or number objects (fp). Requirements: 312 // Test if operands are smi or number objects (fp). Requirements:
313 // operand_1 in rax, operand_2 in rdx; falls through on float or smi 313 // operand_1 in rax, operand_2 in rdx; falls through on float or smi
314 // operands, jumps to the non_float label otherwise. 314 // operands, jumps to the non_float label otherwise.
315 static void CheckNumberOperands(MacroAssembler* masm, 315 static void CheckNumberOperands(MacroAssembler* masm,
316 Label* non_float); 316 Label* non_float);
317 // As CheckNumberOperands above, but expects the HeapNumber map in
318 // a register.
319 static void CheckNumberOperands(MacroAssembler* masm,
320 Label* non_float,
321 Register heap_number_map);
317 322
318 // Takes the operands in rdx and rax and loads them as integers in rax 323 // Takes the operands in rdx and rax and loads them as integers in rax
319 // and rcx. 324 // and rcx.
320 static void LoadAsIntegers(MacroAssembler* masm, 325 static void LoadAsIntegers(MacroAssembler* masm,
321 Label* operand_conversion_failure); 326 Label* operand_conversion_failure,
327 Register heap_number_map);
322 }; 328 };
323 329
324 330
325 // ----------------------------------------------------------------------------- 331 // -----------------------------------------------------------------------------
326 // CodeGenerator implementation. 332 // CodeGenerator implementation.
327 333
328 CodeGenerator::CodeGenerator(MacroAssembler* masm) 334 CodeGenerator::CodeGenerator(MacroAssembler* masm)
329 : deferred_(8), 335 : deferred_(8),
330 masm_(masm), 336 masm_(masm),
331 info_(NULL), 337 info_(NULL),
(...skipping 9649 matching lines...) Expand 10 before | Expand all | Expand 10 after
9981 __ fild_s(Operand(rsp, 0)); 9987 __ fild_s(Operand(rsp, 0));
9982 __ pop(number); 9988 __ pop(number);
9983 9989
9984 __ bind(&done); 9990 __ bind(&done);
9985 } 9991 }
9986 9992
9987 9993
9988 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 9994 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
9989 Register src, 9995 Register src,
9990 XMMRegister dst) { 9996 XMMRegister dst) {
9997 ASSERT(!src.is(kScratchRegister));
9991 Label load_smi, done; 9998 Label load_smi, done;
9992 9999
9993 __ JumpIfSmi(src, &load_smi); 10000 __ JumpIfSmi(src, &load_smi);
9994 __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset)); 10001 __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset));
9995 __ jmp(&done); 10002 __ jmp(&done);
9996 10003
9997 __ bind(&load_smi); 10004 __ bind(&load_smi);
9998 __ SmiToInteger32(src, src); 10005 __ SmiToInteger32(kScratchRegister, src);
9999 __ cvtlsi2sd(dst, src); 10006 __ cvtlsi2sd(dst, kScratchRegister);
10000 10007
10001 __ bind(&done); 10008 __ bind(&done);
10002 } 10009 }
10003 10010
10004 10011
10005 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 10012 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
10006 Register src, 10013 Register src,
10007 XMMRegister dst, 10014 XMMRegister dst,
10008 Label* not_number) { 10015 Label* not_number) {
10009 Label load_smi, done; 10016 Label load_smi, done;
10010 ASSERT(!src.is(kScratchRegister)); 10017 ASSERT(!src.is(kScratchRegister));
10011 __ JumpIfSmi(src, &load_smi); 10018 __ JumpIfSmi(src, &load_smi);
10012 __ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex); 10019 __ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
10013 __ cmpq(FieldOperand(src, HeapObject::kMapOffset), kScratchRegister); 10020 __ cmpq(FieldOperand(src, HeapObject::kMapOffset), kScratchRegister);
10014 __ j(not_equal, not_number); 10021 __ j(not_equal, not_number);
10015 __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset)); 10022 __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset));
10016 __ jmp(&done); 10023 __ jmp(&done);
10017 10024
10018 __ bind(&load_smi); 10025 __ bind(&load_smi);
10019 __ SmiToInteger32(kScratchRegister, src); 10026 __ SmiToInteger32(kScratchRegister, src);
10020 __ cvtlsi2sd(dst, kScratchRegister); 10027 __ cvtlsi2sd(dst, kScratchRegister);
10021 10028
10022 __ bind(&done); 10029 __ bind(&done);
10023 } 10030 }
10024 10031
10025 10032
10026 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 10033 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
10027 XMMRegister dst1, 10034 XMMRegister dst1,
10028 XMMRegister dst2) { 10035 XMMRegister dst2) {
10029 __ movq(kScratchRegister, rdx); 10036 LoadFloatOperand(masm, rdx, dst1);
10030 LoadFloatOperand(masm, kScratchRegister, dst1); 10037 LoadFloatOperand(masm, rax, dst2);
10031 __ movq(kScratchRegister, rax);
10032 LoadFloatOperand(masm, kScratchRegister, dst2);
10033 } 10038 }
10034 10039
10035 10040
10036 void FloatingPointHelper::LoadFloatOperandsFromSmis(MacroAssembler* masm, 10041 void FloatingPointHelper::LoadFloatOperandsFromSmis(MacroAssembler* masm,
10037 XMMRegister dst1, 10042 XMMRegister dst1,
10038 XMMRegister dst2) { 10043 XMMRegister dst2) {
10039 __ SmiToInteger32(kScratchRegister, rdx); 10044 __ SmiToInteger32(kScratchRegister, rdx);
10040 __ cvtlsi2sd(dst1, kScratchRegister); 10045 __ cvtlsi2sd(dst1, kScratchRegister);
10041 __ SmiToInteger32(kScratchRegister, rax); 10046 __ SmiToInteger32(kScratchRegister, rax);
10042 __ cvtlsi2sd(dst2, kScratchRegister); 10047 __ cvtlsi2sd(dst2, kScratchRegister);
10043 } 10048 }
10044 10049
10045 10050
10046 // Input: rdx, rax are the left and right objects of a bit op. 10051 // Input: rdx, rax are the left and right objects of a bit op.
10047 // Output: rax, rcx are left and right integers for a bit op. 10052 // Output: rax, rcx are left and right integers for a bit op.
10048 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, 10053 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
10049 Label* conversion_failure) { 10054 Label* conversion_failure,
10055 Register heap_number_map) {
10050 // Check float operands. 10056 // Check float operands.
10051 Label arg1_is_object, check_undefined_arg1; 10057 Label arg1_is_object, check_undefined_arg1;
10052 Label arg2_is_object, check_undefined_arg2; 10058 Label arg2_is_object, check_undefined_arg2;
10053 Label load_arg2, done; 10059 Label load_arg2, done;
10054 10060
10055 __ JumpIfNotSmi(rdx, &arg1_is_object); 10061 __ JumpIfNotSmi(rdx, &arg1_is_object);
10056 __ SmiToInteger32(rdx, rdx); 10062 __ SmiToInteger32(rdx, rdx);
10057 __ jmp(&load_arg2); 10063 __ jmp(&load_arg2);
10058 10064
10059 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 10065 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
10060 __ bind(&check_undefined_arg1); 10066 __ bind(&check_undefined_arg1);
10061 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); 10067 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex);
10062 __ j(not_equal, conversion_failure); 10068 __ j(not_equal, conversion_failure);
10063 __ movl(rdx, Immediate(0)); 10069 __ movl(rdx, Immediate(0));
10064 __ jmp(&load_arg2); 10070 __ jmp(&load_arg2);
10065 10071
10066 __ bind(&arg1_is_object); 10072 __ bind(&arg1_is_object);
10067 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); 10073 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map);
10068 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
10069 __ j(not_equal, &check_undefined_arg1); 10074 __ j(not_equal, &check_undefined_arg1);
10070 // Get the untagged integer version of the edx heap number in rcx. 10075 // Get the untagged integer version of the edx heap number in rcx.
10071 IntegerConvert(masm, rdx, rdx); 10076 IntegerConvert(masm, rdx, rdx);
10072 10077
10073 // Here rdx has the untagged integer, rax has a Smi or a heap number. 10078 // Here rdx has the untagged integer, rax has a Smi or a heap number.
10074 __ bind(&load_arg2); 10079 __ bind(&load_arg2);
10075 // Test if arg2 is a Smi. 10080 // Test if arg2 is a Smi.
10076 __ JumpIfNotSmi(rax, &arg2_is_object); 10081 __ JumpIfNotSmi(rax, &arg2_is_object);
10077 __ SmiToInteger32(rax, rax); 10082 __ SmiToInteger32(rax, rax);
10078 __ movl(rcx, rax); 10083 __ movl(rcx, rax);
10079 __ jmp(&done); 10084 __ jmp(&done);
10080 10085
10081 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 10086 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
10082 __ bind(&check_undefined_arg2); 10087 __ bind(&check_undefined_arg2);
10083 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 10088 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
10084 __ j(not_equal, conversion_failure); 10089 __ j(not_equal, conversion_failure);
10085 __ movl(rcx, Immediate(0)); 10090 __ movl(rcx, Immediate(0));
10086 __ jmp(&done); 10091 __ jmp(&done);
10087 10092
10088 __ bind(&arg2_is_object); 10093 __ bind(&arg2_is_object);
10089 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 10094 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map);
10090 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
10091 __ j(not_equal, &check_undefined_arg2); 10095 __ j(not_equal, &check_undefined_arg2);
10092 // Get the untagged integer version of the eax heap number in ecx. 10096 // Get the untagged integer version of the eax heap number in ecx.
10093 IntegerConvert(masm, rcx, rax); 10097 IntegerConvert(masm, rcx, rax);
10094 __ bind(&done); 10098 __ bind(&done);
10095 __ movl(rax, rdx); 10099 __ movl(rax, rdx);
10096 } 10100 }
10097 10101
10098 10102
10099 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 10103 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
10100 Register lhs, 10104 Register lhs,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
10137 __ bind(&test_other); 10141 __ bind(&test_other);
10138 __ JumpIfSmi(rax, &done); // argument in rax is OK 10142 __ JumpIfSmi(rax, &done); // argument in rax is OK
10139 __ Cmp(FieldOperand(rax, HeapObject::kMapOffset), Factory::heap_number_map()); 10143 __ Cmp(FieldOperand(rax, HeapObject::kMapOffset), Factory::heap_number_map());
10140 __ j(not_equal, non_float); // The argument in rax is not a number. 10144 __ j(not_equal, non_float); // The argument in rax is not a number.
10141 10145
10142 // Fall-through: Both operands are numbers. 10146 // Fall-through: Both operands are numbers.
10143 __ bind(&done); 10147 __ bind(&done);
10144 } 10148 }
10145 10149
10146 10150
10151 void FloatingPointHelper::CheckNumberOperands(MacroAssembler* masm,
10152 Label* non_float,
10153 Register heap_number_map) {
10154 Label test_other, done;
10155 // Test if both operands are numbers (heap_numbers or smis).
10156 // If not, jump to label non_float.
10157 __ JumpIfSmi(rdx, &test_other); // argument in rdx is OK
10158 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map);
10159 __ j(not_equal, non_float); // The argument in rdx is not a number.
10160
10161 __ bind(&test_other);
10162 __ JumpIfSmi(rax, &done); // argument in rax is OK
10163 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map);
10164 __ j(not_equal, non_float); // The argument in rax is not a number.
10165
10166 // Fall-through: Both operands are numbers.
10167 __ bind(&done);
10168 }
10169
10170
10147 const char* GenericBinaryOpStub::GetName() { 10171 const char* GenericBinaryOpStub::GetName() {
10148 if (name_ != NULL) return name_; 10172 if (name_ != NULL) return name_;
10149 const int len = 100; 10173 const int len = 100;
10150 name_ = Bootstrapper::AllocateAutoDeletedArray(len); 10174 name_ = Bootstrapper::AllocateAutoDeletedArray(len);
10151 if (name_ == NULL) return "OOM"; 10175 if (name_ == NULL) return "OOM";
10152 const char* op_name = Token::Name(op_); 10176 const char* op_name = Token::Name(op_);
10153 const char* overwrite_name; 10177 const char* overwrite_name;
10154 switch (mode_) { 10178 switch (mode_) {
10155 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 10179 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
10156 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 10180 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
10496 10520
10497 if (ShouldGenerateSmiCode()) { 10521 if (ShouldGenerateSmiCode()) {
10498 GenerateSmiCode(masm, &call_runtime); 10522 GenerateSmiCode(masm, &call_runtime);
10499 } else if (op_ != Token::MOD) { 10523 } else if (op_ != Token::MOD) {
10500 if (!HasArgsInRegisters()) { 10524 if (!HasArgsInRegisters()) {
10501 GenerateLoadArguments(masm); 10525 GenerateLoadArguments(masm);
10502 } 10526 }
10503 } 10527 }
10504 // Floating point case. 10528 // Floating point case.
10505 if (ShouldGenerateFPCode()) { 10529 if (ShouldGenerateFPCode()) {
10530 // Load the HeapNumber map here and use it throughout the FP code.
10531 Register heap_number_map = r9;
10506 switch (op_) { 10532 switch (op_) {
10507 case Token::ADD: 10533 case Token::ADD:
10508 case Token::SUB: 10534 case Token::SUB:
10509 case Token::MUL: 10535 case Token::MUL:
10510 case Token::DIV: { 10536 case Token::DIV: {
10511 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && 10537 if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
10512 HasSmiCodeInStub()) { 10538 HasSmiCodeInStub()) {
10513 // Execution reaches this point when the first non-smi argument occurs 10539 // Execution reaches this point when the first non-smi argument occurs
10514 // (and only if smi code is generated). This is the right moment to 10540 // (and only if smi code is generated). This is the right moment to
10515 // patch to HEAP_NUMBERS state. The transition is attempted only for 10541 // patch to HEAP_NUMBERS state. The transition is attempted only for
10516 // the four basic operations. The stub stays in the DEFAULT state 10542 // the four basic operations. The stub stays in the DEFAULT state
10517 // forever for all other operations (also if smi code is skipped). 10543 // forever for all other operations (also if smi code is skipped).
10518 GenerateTypeTransition(masm); 10544 GenerateTypeTransition(masm);
10519 } 10545 }
10546 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
10520 10547
10521 Label not_floats; 10548 Label not_floats;
10522 // rax: y 10549 // rax: y
10523 // rdx: x 10550 // rdx: x
10524 if (static_operands_type_.IsNumber() && FLAG_debug_code) { 10551 if (static_operands_type_.IsNumber() && FLAG_debug_code) {
10525 // Assert at runtime that inputs are only numbers. 10552 // Assert at runtime that inputs are only numbers.
10526 __ AbortIfNotNumber(rdx); 10553 __ AbortIfNotNumber(rdx);
10527 __ AbortIfNotNumber(rax); 10554 __ AbortIfNotNumber(rax);
10528 } else { 10555 } else {
10529 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); 10556 if (FLAG_debug_code) {
10530 } 10557 __ AbortIfNotRootValue(heap_number_map,
10558 Heap::kHeapNumberMapRootIndex,
10559 "HeapNumberMap register clobbered.");
10560 }
10561 FloatingPointHelper::CheckNumberOperands(masm,
10562 &call_runtime,
10563 heap_number_map);
10564 }
10531 // Fast-case: Both operands are numbers. 10565 // Fast-case: Both operands are numbers.
10532 // xmm4 and xmm5 are volatile XMM registers. 10566 // xmm4 and xmm5 are volatile XMM registers.
10533 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5); 10567 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
10534 10568
10535 switch (op_) { 10569 switch (op_) {
10536 case Token::ADD: __ addsd(xmm4, xmm5); break; 10570 case Token::ADD: __ addsd(xmm4, xmm5); break;
10537 case Token::SUB: __ subsd(xmm4, xmm5); break; 10571 case Token::SUB: __ subsd(xmm4, xmm5); break;
10538 case Token::MUL: __ mulsd(xmm4, xmm5); break; 10572 case Token::MUL: __ mulsd(xmm4, xmm5); break;
10539 case Token::DIV: __ divsd(xmm4, xmm5); break; 10573 case Token::DIV: __ divsd(xmm4, xmm5); break;
10540 default: UNREACHABLE(); 10574 default: UNREACHABLE();
10541 } 10575 }
10542 // Allocate a heap number, if needed. 10576 // Allocate a heap number, if needed.
10543 Label skip_allocation; 10577 Label skip_allocation;
10544 OverwriteMode mode = mode_; 10578 OverwriteMode mode = mode_;
10545 if (HasArgsReversed()) { 10579 if (HasArgsReversed()) {
10546 if (mode == OVERWRITE_RIGHT) { 10580 if (mode == OVERWRITE_RIGHT) {
10547 mode = OVERWRITE_LEFT; 10581 mode = OVERWRITE_LEFT;
10548 } else if (mode == OVERWRITE_LEFT) { 10582 } else if (mode == OVERWRITE_LEFT) {
10549 mode = OVERWRITE_RIGHT; 10583 mode = OVERWRITE_RIGHT;
10550 } 10584 }
10551 } 10585 }
10552 switch (mode) { 10586 switch (mode) {
10587 // TODO(lrn): Allocate this when we first see that the
10588 // left register is a smi (and load it into xmm4).
10553 case OVERWRITE_LEFT: 10589 case OVERWRITE_LEFT:
10554 __ JumpIfNotSmi(rdx, &skip_allocation); 10590 __ JumpIfNotSmi(rdx, &skip_allocation);
10555 __ AllocateHeapNumber(rbx, rcx, &call_runtime); 10591 // Allocate heap number in new space.
10592 __ AllocateInNewSpace(HeapNumber::kSize,
10593 rbx,
10594 rcx,
10595 no_reg,
10596 &call_runtime,
10597 TAG_OBJECT);
10598 if (FLAG_debug_code) {
10599 __ AbortIfNotRootValue(heap_number_map,
10600 Heap::kHeapNumberMapRootIndex,
10601 "HeapNumberMap register clobbered.");
10602 }
10603 __ movq(FieldOperand(rbx, HeapObject::kMapOffset),
10604 heap_number_map);
10556 __ movq(rdx, rbx); 10605 __ movq(rdx, rbx);
10557 __ bind(&skip_allocation); 10606 __ bind(&skip_allocation);
10558 __ movq(rax, rdx); 10607 __ movq(rax, rdx);
10559 break; 10608 break;
10560 case OVERWRITE_RIGHT: 10609 case OVERWRITE_RIGHT:
10561 // If the argument in rax is already an object, we skip the 10610 // If the argument in rax is already an object, we skip the
10562 // allocation of a heap number. 10611 // allocation of a heap number.
10612 // TODO(lrn): Allocate the heap number when we first see that the
10613 // right register is a smi (and load it into xmm5).
10563 __ JumpIfNotSmi(rax, &skip_allocation); 10614 __ JumpIfNotSmi(rax, &skip_allocation);
10564 // Fall through! 10615 // Fall through!
10565 case NO_OVERWRITE: 10616 case NO_OVERWRITE:
10566 // Allocate a heap number for the result. Keep rax and rdx intact 10617 // Allocate a heap number for the result. Keep rax and rdx intact
10567 // for the possible runtime call. 10618 // for the possible runtime call.
10568 __ AllocateHeapNumber(rbx, rcx, &call_runtime); 10619 __ AllocateInNewSpace(HeapNumber::kSize,
10620 rbx,
10621 rcx,
10622 no_reg,
10623 &call_runtime,
10624 TAG_OBJECT);
10625 if (FLAG_debug_code) {
10626 __ AbortIfNotRootValue(heap_number_map,
10627 Heap::kHeapNumberMapRootIndex,
10628 "HeapNumberMap register clobbered.");
10629 }
10630 __ movq(FieldOperand(rbx, HeapObject::kMapOffset),
10631 heap_number_map);
10569 __ movq(rax, rbx); 10632 __ movq(rax, rbx);
10570 __ bind(&skip_allocation); 10633 __ bind(&skip_allocation);
10571 break; 10634 break;
10572 default: UNREACHABLE(); 10635 default: UNREACHABLE();
10573 } 10636 }
10574 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4); 10637 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4);
10575 GenerateReturn(masm); 10638 GenerateReturn(masm);
10576 __ bind(&not_floats); 10639 __ bind(&not_floats);
10577 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && 10640 if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
10578 !HasSmiCodeInStub()) { 10641 !HasSmiCodeInStub()) {
(...skipping 10 matching lines...) Expand all
10589 case Token::MOD: { 10652 case Token::MOD: {
10590 // For MOD we go directly to runtime in the non-smi case. 10653 // For MOD we go directly to runtime in the non-smi case.
10591 break; 10654 break;
10592 } 10655 }
10593 case Token::BIT_OR: 10656 case Token::BIT_OR:
10594 case Token::BIT_AND: 10657 case Token::BIT_AND:
10595 case Token::BIT_XOR: 10658 case Token::BIT_XOR:
10596 case Token::SAR: 10659 case Token::SAR:
10597 case Token::SHL: 10660 case Token::SHL:
10598 case Token::SHR: { 10661 case Token::SHR: {
10599 Label skip_allocation, non_smi_result; 10662 Label skip_allocation, non_smi_shr_result;
10600 FloatingPointHelper::LoadAsIntegers(masm, &call_runtime); 10663 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
10664 FloatingPointHelper::LoadAsIntegers(masm,
10665 &call_runtime,
10666 heap_number_map);
10601 switch (op_) { 10667 switch (op_) {
10602 case Token::BIT_OR: __ orl(rax, rcx); break; 10668 case Token::BIT_OR: __ orl(rax, rcx); break;
10603 case Token::BIT_AND: __ andl(rax, rcx); break; 10669 case Token::BIT_AND: __ andl(rax, rcx); break;
10604 case Token::BIT_XOR: __ xorl(rax, rcx); break; 10670 case Token::BIT_XOR: __ xorl(rax, rcx); break;
10605 case Token::SAR: __ sarl_cl(rax); break; 10671 case Token::SAR: __ sarl_cl(rax); break;
10606 case Token::SHL: __ shll_cl(rax); break; 10672 case Token::SHL: __ shll_cl(rax); break;
10607 case Token::SHR: __ shrl_cl(rax); break; 10673 case Token::SHR: __ shrl_cl(rax); break;
10608 default: UNREACHABLE(); 10674 default: UNREACHABLE();
10609 } 10675 }
10610 if (op_ == Token::SHR) { 10676 if (op_ == Token::SHR) {
10611 // Check if result is negative. This can only happen for a shift 10677 // Check if result is negative. This can only happen for a shift
10612 // by zero, which also doesn't update the sign flag. 10678 // by zero.
10613 __ testl(rax, rax); 10679 __ testl(rax, rax);
10614 __ j(negative, &non_smi_result); 10680 __ j(negative, &non_smi_shr_result);
10615 } 10681 }
10616 __ JumpIfNotValidSmiValue(rax, &non_smi_result); 10682 STATIC_ASSERT(kSmiValueSize == 32);
10617 // Tag smi result, if possible, and return. 10683 // Tag smi result and return.
10618 __ Integer32ToSmi(rax, rax); 10684 __ Integer32ToSmi(rax, rax);
10619 GenerateReturn(masm); 10685 GenerateReturn(masm);
10620 10686
10621 // All ops except SHR return a signed int32 that we load in 10687 // All bit-ops except SHR return a signed int32 that can be
10622 // a HeapNumber. 10688 // returned immediately as a smi.
10623 if (op_ != Token::SHR && non_smi_result.is_linked()) { 10689 if (op_ == Token::SHR) {
10624 __ bind(&non_smi_result); 10690 ASSERT(non_smi_shr_result.is_linked());
10691 __ bind(&non_smi_shr_result);
10625 // Allocate a heap number if needed. 10692 // Allocate a heap number if needed.
10626 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result 10693 __ movl(rbx, rax); // rbx holds result value (uint32 value as int64).
10627 switch (mode_) { 10694 switch (mode_) {
10628 case OVERWRITE_LEFT: 10695 case OVERWRITE_LEFT:
10629 case OVERWRITE_RIGHT: 10696 case OVERWRITE_RIGHT:
10630 // If the operand was an object, we skip the 10697 // If the operand was an object, we skip the
10631 // allocation of a heap number. 10698 // allocation of a heap number.
10632 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ? 10699 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ?
10633 1 * kPointerSize : 2 * kPointerSize)); 10700 1 * kPointerSize : 2 * kPointerSize));
10634 __ JumpIfNotSmi(rax, &skip_allocation); 10701 __ JumpIfNotSmi(rax, &skip_allocation);
10635 // Fall through! 10702 // Fall through!
10636 case NO_OVERWRITE: 10703 case NO_OVERWRITE:
10637 __ AllocateHeapNumber(rax, rcx, &call_runtime); 10704 // Allocate heap number in new space.
10705 __ AllocateInNewSpace(HeapNumber::kSize,
10706 rax,
10707 rcx,
10708 no_reg,
10709 &call_runtime,
10710 TAG_OBJECT);
10711 // Set the map.
10712 if (FLAG_debug_code) {
10713 __ AbortIfNotRootValue(heap_number_map,
10714 Heap::kHeapNumberMapRootIndex,
10715 "HeapNumberMap register clobbered.");
10716 }
10717 __ movq(FieldOperand(rax, HeapObject::kMapOffset),
10718 heap_number_map);
10638 __ bind(&skip_allocation); 10719 __ bind(&skip_allocation);
10639 break; 10720 break;
10640 default: UNREACHABLE(); 10721 default: UNREACHABLE();
10641 } 10722 }
10642 // Store the result in the HeapNumber and return. 10723 // Store the result in the HeapNumber and return.
10643 __ movq(Operand(rsp, 1 * kPointerSize), rbx); 10724 __ cvtqsi2sd(xmm0, rbx);
10644 __ fild_s(Operand(rsp, 1 * kPointerSize)); 10725 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
10645 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
10646 GenerateReturn(masm); 10726 GenerateReturn(masm);
10647 } 10727 }
10648 10728
10649 // SHR should return uint32 - go to runtime for non-smi/negative result.
10650 if (op_ == Token::SHR) {
10651 __ bind(&non_smi_result);
10652 }
10653 break; 10729 break;
10654 } 10730 }
10655 default: UNREACHABLE(); break; 10731 default: UNREACHABLE(); break;
10656 } 10732 }
10657 } 10733 }
10658 10734
10659 // If all else fails, use the runtime system to get the correct 10735 // If all else fails, use the runtime system to get the correct
10660 // result. If arguments was passed in registers now place them on the 10736 // result. If arguments was passed in registers now place them on the
10661 // stack in the correct order below the return address. 10737 // stack in the correct order below the return address.
10662 __ bind(&call_runtime); 10738 __ bind(&call_runtime);
(...skipping 12 matching lines...) Expand all
10675 rhs = rdx; 10751 rhs = rdx;
10676 } else { 10752 } else {
10677 lhs = rdx; 10753 lhs = rdx;
10678 rhs = rax; 10754 rhs = rax;
10679 } 10755 }
10680 10756
10681 // Test for string arguments before calling runtime. 10757 // Test for string arguments before calling runtime.
10682 Label not_strings, both_strings, not_string1, string1, string1_smi2; 10758 Label not_strings, both_strings, not_string1, string1, string1_smi2;
10683 10759
10684 // If this stub has already generated FP-specific code then the arguments 10760 // If this stub has already generated FP-specific code then the arguments
10685 // are already in rdx, rax 10761 // are already in rdx, rax.
10686 if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) { 10762 if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) {
10687 GenerateLoadArguments(masm); 10763 GenerateLoadArguments(masm);
10688 } 10764 }
10689 10765
10690 Condition is_smi; 10766 Condition is_smi;
10691 is_smi = masm->CheckSmi(lhs); 10767 is_smi = masm->CheckSmi(lhs);
10692 __ j(is_smi, &not_string1); 10768 __ j(is_smi, &not_string1);
10693 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, r8); 10769 __ CmpObjectType(lhs, FIRST_NONSTRING_TYPE, r8);
10694 __ j(above_equal, &not_string1); 10770 __ j(above_equal, &not_string1);
10695 10771
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after
11956 } 12032 }
11957 12033
11958 #endif 12034 #endif
11959 12035
11960 12036
11961 #undef __ 12037 #undef __
11962 12038
11963 } } // namespace v8::internal 12039 } } // namespace v8::internal
11964 12040
11965 #endif // V8_TARGET_ARCH_X64 12041 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « no previous file | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698