| 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 2046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10589 case Token::MUL: | 10604 case Token::MUL: |
| 10590 case Token::DIV: { | 10605 case Token::DIV: { |
| 10591 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && | 10606 if (runtime_operands_type_ == BinaryOpIC::DEFAULT && |
| 10592 HasSmiCodeInStub()) { | 10607 HasSmiCodeInStub()) { |
| 10593 // Execution reaches this point when the first non-smi argument occurs | 10608 // Execution reaches this point when the first non-smi argument occurs |
| 10594 // (and only if smi code is generated). This is the right moment to | 10609 // (and only if smi code is generated). This is the right moment to |
| 10595 // patch to HEAP_NUMBERS state. The transition is attempted only for | 10610 // patch to HEAP_NUMBERS state. The transition is attempted only for |
| 10596 // the four basic operations. The stub stays in the DEFAULT state | 10611 // the four basic operations. The stub stays in the DEFAULT state |
| 10597 // forever for all other operations (also if smi code is skipped). | 10612 // forever for all other operations (also if smi code is skipped). |
| 10598 GenerateTypeTransition(masm); | 10613 GenerateTypeTransition(masm); |
| 10614 break; |
| 10599 } | 10615 } |
| 10600 | 10616 |
| 10601 Label not_floats; | 10617 Label not_floats; |
| 10602 // rax: y | 10618 // rax: y |
| 10603 // rdx: x | 10619 // rdx: x |
| 10604 if (static_operands_type_.IsNumber()) { | 10620 if (static_operands_type_.IsNumber()) { |
| 10605 if (FLAG_debug_code) { | 10621 if (FLAG_debug_code) { |
| 10606 // Assert at runtime that inputs are only numbers. | 10622 // Assert at runtime that inputs are only numbers. |
| 10607 __ AbortIfNotNumber(rdx); | 10623 __ AbortIfNotNumber(rdx); |
| 10608 __ AbortIfNotNumber(rax); | 10624 __ AbortIfNotNumber(rax); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10906 __ push(rdx); | 10922 __ push(rdx); |
| 10907 __ push(rax); | 10923 __ push(rax); |
| 10908 } | 10924 } |
| 10909 __ push(rcx); | 10925 __ push(rcx); |
| 10910 } | 10926 } |
| 10911 | 10927 |
| 10912 | 10928 |
| 10913 void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | 10929 void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
| 10914 Label get_result; | 10930 Label get_result; |
| 10915 | 10931 |
| 10916 // Keep a copy of operands on the stack and make sure they are also in | 10932 // Ensure the operands are on the stack. |
| 10917 // rdx, rax. | |
| 10918 if (HasArgsInRegisters()) { | 10933 if (HasArgsInRegisters()) { |
| 10919 GenerateRegisterArgsPush(masm); | 10934 GenerateRegisterArgsPush(masm); |
| 10920 } else { | |
| 10921 GenerateLoadArguments(masm); | |
| 10922 } | 10935 } |
| 10923 | 10936 |
| 10924 // Internal frame is necessary to handle exceptions properly. | |
| 10925 __ EnterInternalFrame(); | |
| 10926 | |
| 10927 // Push arguments on stack if the stub expects them there. | |
| 10928 if (!HasArgsInRegisters()) { | |
| 10929 __ push(rdx); | |
| 10930 __ push(rax); | |
| 10931 } | |
| 10932 // Call the stub proper to get the result in rax. | |
| 10933 __ call(&get_result); | |
| 10934 __ LeaveInternalFrame(); | |
| 10935 | |
| 10936 // Left and right arguments are already on stack. | 10937 // Left and right arguments are already on stack. |
| 10937 __ pop(rcx); | 10938 __ pop(rcx); // Save the return address. |
| 10938 // Push the operation result. The tail call to BinaryOp_Patch will | |
| 10939 // return it to the original caller.. | |
| 10940 __ push(rax); | |
| 10941 | 10939 |
| 10942 // Push this stub's key. | 10940 // Push this stub's key. |
| 10943 __ Push(Smi::FromInt(MinorKey())); | 10941 __ Push(Smi::FromInt(MinorKey())); |
| 10944 | 10942 |
| 10945 // Although the operation and the type info are encoded into the key, | 10943 // Although the operation and the type info are encoded into the key, |
| 10946 // the encoding is opaque, so push them too. | 10944 // the encoding is opaque, so push them too. |
| 10947 __ Push(Smi::FromInt(op_)); | 10945 __ Push(Smi::FromInt(op_)); |
| 10948 | 10946 |
| 10949 __ Push(Smi::FromInt(runtime_operands_type_)); | 10947 __ Push(Smi::FromInt(runtime_operands_type_)); |
| 10950 | 10948 |
| 10951 __ push(rcx); | 10949 __ push(rcx); // The return address. |
| 10952 | 10950 |
| 10953 // Perform patching to an appropriate fast case and return the result. | 10951 // Perform patching to an appropriate fast case and return the result. |
| 10954 __ TailCallExternalReference( | 10952 __ TailCallExternalReference( |
| 10955 ExternalReference(IC_Utility(IC::kBinaryOp_Patch)), | 10953 ExternalReference(IC_Utility(IC::kBinaryOp_Patch)), |
| 10956 6, | 10954 5, |
| 10957 1); | 10955 1); |
| 10958 | |
| 10959 // The entry point for the result calculation is assumed to be immediately | |
| 10960 // after this sequence. | |
| 10961 __ bind(&get_result); | |
| 10962 } | 10956 } |
| 10963 | 10957 |
| 10964 | 10958 |
| 10965 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { | 10959 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { |
| 10966 GenericBinaryOpStub stub(key, type_info); | 10960 GenericBinaryOpStub stub(key, type_info); |
| 10967 return stub.GetCode(); | 10961 return stub.GetCode(); |
| 10968 } | 10962 } |
| 10969 | 10963 |
| 10970 | 10964 |
| 10971 int CompareStub::MinorKey() { | 10965 int CompareStub::MinorKey() { |
| (...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12069 } | 12063 } |
| 12070 | 12064 |
| 12071 #endif | 12065 #endif |
| 12072 | 12066 |
| 12073 | 12067 |
| 12074 #undef __ | 12068 #undef __ |
| 12075 | 12069 |
| 12076 } } // namespace v8::internal | 12070 } } // namespace v8::internal |
| 12077 | 12071 |
| 12078 #endif // V8_TARGET_ARCH_X64 | 12072 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |