OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 3355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3366 expression->AsLiteral()->IsNull())) { | 3366 expression->AsLiteral()->IsNull())) { |
3367 // Omit evaluating the value of the primitive literal. | 3367 // Omit evaluating the value of the primitive literal. |
3368 // It will be discarded anyway, and can have no side effect. | 3368 // It will be discarded anyway, and can have no side effect. |
3369 frame_->Push(Factory::undefined_value()); | 3369 frame_->Push(Factory::undefined_value()); |
3370 } else { | 3370 } else { |
3371 Load(node->expression()); | 3371 Load(node->expression()); |
3372 frame_->SetElementAt(0, Factory::undefined_value()); | 3372 frame_->SetElementAt(0, Factory::undefined_value()); |
3373 } | 3373 } |
3374 | 3374 |
3375 } else { | 3375 } else { |
3376 bool overwrite = | 3376 bool can_overwrite = |
3377 (node->expression()->AsBinaryOperation() != NULL && | 3377 (node->expression()->AsBinaryOperation() != NULL && |
3378 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | 3378 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 3379 UnaryOverwriteMode overwrite = |
| 3380 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
| 3381 bool no_negative_zero = node->expression()->no_negative_zero(); |
3379 Load(node->expression()); | 3382 Load(node->expression()); |
3380 switch (op) { | 3383 switch (op) { |
3381 case Token::NOT: | 3384 case Token::NOT: |
3382 case Token::DELETE: | 3385 case Token::DELETE: |
3383 case Token::TYPEOF: | 3386 case Token::TYPEOF: |
3384 UNREACHABLE(); // handled above | 3387 UNREACHABLE(); // handled above |
3385 break; | 3388 break; |
3386 | 3389 |
3387 case Token::SUB: { | 3390 case Token::SUB: { |
3388 GenericUnaryOpStub stub(Token::SUB, overwrite); | 3391 GenericUnaryOpStub stub( |
| 3392 Token::SUB, |
| 3393 overwrite, |
| 3394 no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero); |
3389 Result operand = frame_->Pop(); | 3395 Result operand = frame_->Pop(); |
3390 Result answer = frame_->CallStub(&stub, &operand); | 3396 Result answer = frame_->CallStub(&stub, &operand); |
3391 answer.set_type_info(TypeInfo::Number()); | 3397 answer.set_type_info(TypeInfo::Number()); |
3392 frame_->Push(&answer); | 3398 frame_->Push(&answer); |
3393 break; | 3399 break; |
3394 } | 3400 } |
3395 | 3401 |
3396 case Token::BIT_NOT: { | 3402 case Token::BIT_NOT: { |
3397 // Smi check. | 3403 // Smi check. |
3398 JumpTarget smi_label; | 3404 JumpTarget smi_label; |
(...skipping 5100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8499 | 8505 |
8500 | 8506 |
8501 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | 8507 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
8502 Label slow, done; | 8508 Label slow, done; |
8503 | 8509 |
8504 if (op_ == Token::SUB) { | 8510 if (op_ == Token::SUB) { |
8505 // Check whether the value is a smi. | 8511 // Check whether the value is a smi. |
8506 Label try_float; | 8512 Label try_float; |
8507 __ JumpIfNotSmi(rax, &try_float); | 8513 __ JumpIfNotSmi(rax, &try_float); |
8508 | 8514 |
| 8515 if (negative_zero_ == kIgnoreNegativeZero) { |
| 8516 __ SmiCompare(rax, Smi::FromInt(0)); |
| 8517 __ j(equal, &done); |
| 8518 } |
| 8519 |
8509 // Enter runtime system if the value of the smi is zero | 8520 // Enter runtime system if the value of the smi is zero |
8510 // to make sure that we switch between 0 and -0. | 8521 // to make sure that we switch between 0 and -0. |
8511 // Also enter it if the value of the smi is Smi::kMinValue. | 8522 // Also enter it if the value of the smi is Smi::kMinValue. |
8512 __ SmiNeg(rax, rax, &done); | 8523 __ SmiNeg(rax, rax, &done); |
8513 | 8524 |
8514 // Either zero or Smi::kMinValue, neither of which become a smi when | 8525 // Either zero or Smi::kMinValue, neither of which become a smi when |
8515 // negated. | 8526 // negated. |
8516 __ SmiCompare(rax, Smi::FromInt(0)); | 8527 if (negative_zero_ == kStrictNegativeZero) { |
8517 __ j(not_equal, &slow); | 8528 __ SmiCompare(rax, Smi::FromInt(0)); |
8518 __ Move(rax, Factory::minus_zero_value()); | 8529 __ j(not_equal, &slow); |
8519 __ jmp(&done); | 8530 __ Move(rax, Factory::minus_zero_value()); |
| 8531 __ jmp(&done); |
| 8532 } else { |
| 8533 __ jmp(&slow); |
| 8534 } |
8520 | 8535 |
8521 // Try floating point case. | 8536 // Try floating point case. |
8522 __ bind(&try_float); | 8537 __ bind(&try_float); |
8523 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 8538 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
8524 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); | 8539 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); |
8525 __ j(not_equal, &slow); | 8540 __ j(not_equal, &slow); |
8526 // Operand is a float, negate its value by flipping sign bit. | 8541 // Operand is a float, negate its value by flipping sign bit. |
8527 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); | 8542 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); |
8528 __ movq(kScratchRegister, Immediate(0x01)); | 8543 __ movq(kScratchRegister, Immediate(0x01)); |
8529 __ shl(kScratchRegister, Immediate(63)); | 8544 __ shl(kScratchRegister, Immediate(63)); |
8530 __ xor_(rdx, kScratchRegister); // Flip sign. | 8545 __ xor_(rdx, kScratchRegister); // Flip sign. |
8531 // rdx is value to store. | 8546 // rdx is value to store. |
8532 if (overwrite_) { | 8547 if (overwrite_ == UNARY_OVERWRITE) { |
8533 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); | 8548 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); |
8534 } else { | 8549 } else { |
8535 __ AllocateHeapNumber(rcx, rbx, &slow); | 8550 __ AllocateHeapNumber(rcx, rbx, &slow); |
8536 // rcx: allocated 'empty' number | 8551 // rcx: allocated 'empty' number |
8537 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); | 8552 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); |
8538 __ movq(rax, rcx); | 8553 __ movq(rax, rcx); |
8539 } | 8554 } |
8540 } else if (op_ == Token::BIT_NOT) { | 8555 } else if (op_ == Token::BIT_NOT) { |
8541 // Check if the operand is a heap number. | 8556 // Check if the operand is a heap number. |
8542 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 8557 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
(...skipping 3526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12069 } | 12084 } |
12070 | 12085 |
12071 #endif | 12086 #endif |
12072 | 12087 |
12073 | 12088 |
12074 #undef __ | 12089 #undef __ |
12075 | 12090 |
12076 } } // namespace v8::internal | 12091 } } // namespace v8::internal |
12077 | 12092 |
12078 #endif // V8_TARGET_ARCH_X64 | 12093 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |