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 4688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4699 | 4699 |
4700 | 4700 |
4701 void CodeGenerator::GenerateRandomHeapNumber( | 4701 void CodeGenerator::GenerateRandomHeapNumber( |
4702 ZoneList<Expression*>* args) { | 4702 ZoneList<Expression*>* args) { |
4703 VirtualFrame::SpilledScope spilled_scope(frame_); | 4703 VirtualFrame::SpilledScope spilled_scope(frame_); |
4704 ASSERT(args->length() == 0); | 4704 ASSERT(args->length() == 0); |
4705 | 4705 |
4706 Label slow_allocate_heapnumber; | 4706 Label slow_allocate_heapnumber; |
4707 Label heapnumber_allocated; | 4707 Label heapnumber_allocated; |
4708 | 4708 |
4709 __ AllocateHeapNumber(r4, r1, r2, &slow_allocate_heapnumber); | 4709 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); |
| 4710 __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber); |
4710 __ jmp(&heapnumber_allocated); | 4711 __ jmp(&heapnumber_allocated); |
4711 | 4712 |
4712 __ bind(&slow_allocate_heapnumber); | 4713 __ bind(&slow_allocate_heapnumber); |
4713 // To allocate a heap number, and ensure that it is not a smi, we | 4714 // To allocate a heap number, and ensure that it is not a smi, we |
4714 // call the runtime function FUnaryMinus on 0, returning the double | 4715 // call the runtime function FUnaryMinus on 0, returning the double |
4715 // -0.0. A new, distinct heap number is returned each time. | 4716 // -0.0. A new, distinct heap number is returned each time. |
4716 __ mov(r0, Operand(Smi::FromInt(0))); | 4717 __ mov(r0, Operand(Smi::FromInt(0))); |
4717 __ push(r0); | 4718 __ push(r0); |
4718 __ CallRuntime(Runtime::kNumberUnaryMinus, 1); | 4719 __ CallRuntime(Runtime::kNumberUnaryMinus, 1); |
4719 __ mov(r4, Operand(r0)); | 4720 __ mov(r4, Operand(r0)); |
(...skipping 2636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7356 void GenericBinaryOpStub::HandleBinaryOpSlowCases( | 7357 void GenericBinaryOpStub::HandleBinaryOpSlowCases( |
7357 MacroAssembler* masm, | 7358 MacroAssembler* masm, |
7358 Label* not_smi, | 7359 Label* not_smi, |
7359 Register lhs, | 7360 Register lhs, |
7360 Register rhs, | 7361 Register rhs, |
7361 const Builtins::JavaScript& builtin) { | 7362 const Builtins::JavaScript& builtin) { |
7362 Label slow, slow_reverse, do_the_call; | 7363 Label slow, slow_reverse, do_the_call; |
7363 bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_; | 7364 bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_; |
7364 | 7365 |
7365 ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0))); | 7366 ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0))); |
| 7367 Register heap_number_map = r6; |
7366 | 7368 |
7367 if (ShouldGenerateSmiCode()) { | 7369 if (ShouldGenerateSmiCode()) { |
| 7370 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 7371 |
7368 // Smi-smi case (overflow). | 7372 // Smi-smi case (overflow). |
7369 // Since both are Smis there is no heap number to overwrite, so allocate. | 7373 // Since both are Smis there is no heap number to overwrite, so allocate. |
7370 // The new heap number is in r5. r6 and r7 are scratch. | 7374 // The new heap number is in r5. r3 and r7 are scratch. |
7371 __ AllocateHeapNumber(r5, r6, r7, lhs.is(r0) ? &slow_reverse : &slow); | 7375 __ AllocateHeapNumber( |
| 7376 r5, r3, r7, heap_number_map, lhs.is(r0) ? &slow_reverse : &slow); |
7372 | 7377 |
7373 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV, | 7378 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV, |
7374 // using registers d7 and d6 for the double values. | 7379 // using registers d7 and d6 for the double values. |
7375 if (use_fp_registers) { | 7380 if (use_fp_registers) { |
7376 CpuFeatures::Scope scope(VFP3); | 7381 CpuFeatures::Scope scope(VFP3); |
7377 __ mov(r7, Operand(rhs, ASR, kSmiTagSize)); | 7382 __ mov(r7, Operand(rhs, ASR, kSmiTagSize)); |
7378 __ vmov(s15, r7); | 7383 __ vmov(s15, r7); |
7379 __ vcvt_f64_s32(d7, s15); | 7384 __ vcvt_f64_s32(d7, s15); |
7380 __ mov(r7, Operand(lhs, ASR, kSmiTagSize)); | 7385 __ mov(r7, Operand(lhs, ASR, kSmiTagSize)); |
7381 __ vmov(s13, r7); | 7386 __ vmov(s13, r7); |
7382 __ vcvt_f64_s32(d6, s13); | 7387 __ vcvt_f64_s32(d6, s13); |
7383 } else { | 7388 } else { |
7384 // Write Smi from rhs to r3 and r2 in double format. r6 is scratch. | 7389 // Write Smi from rhs to r3 and r2 in double format. r3 is scratch. |
7385 __ mov(r7, Operand(rhs)); | 7390 __ mov(r7, Operand(rhs)); |
7386 ConvertToDoubleStub stub1(r3, r2, r7, r6); | 7391 ConvertToDoubleStub stub1(r3, r2, r7, r9); |
7387 __ push(lr); | 7392 __ push(lr); |
7388 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); | 7393 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); |
7389 // Write Smi from lhs to r1 and r0 in double format. r6 is scratch. | 7394 // Write Smi from lhs to r1 and r0 in double format. r9 is scratch. |
7390 __ mov(r7, Operand(lhs)); | 7395 __ mov(r7, Operand(lhs)); |
7391 ConvertToDoubleStub stub2(r1, r0, r7, r6); | 7396 ConvertToDoubleStub stub2(r1, r0, r7, r9); |
7392 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); | 7397 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); |
7393 __ pop(lr); | 7398 __ pop(lr); |
7394 } | 7399 } |
7395 __ jmp(&do_the_call); // Tail call. No return. | 7400 __ jmp(&do_the_call); // Tail call. No return. |
7396 } | 7401 } |
7397 | 7402 |
7398 // We branch here if at least one of r0 and r1 is not a Smi. | 7403 // We branch here if at least one of r0 and r1 is not a Smi. |
7399 __ bind(not_smi); | 7404 __ bind(not_smi); |
| 7405 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
7400 | 7406 |
7401 // After this point we have the left hand side in r1 and the right hand side | 7407 // After this point we have the left hand side in r1 and the right hand side |
7402 // in r0. | 7408 // in r0. |
7403 if (lhs.is(r0)) { | 7409 if (lhs.is(r0)) { |
7404 __ Swap(r0, r1, ip); | 7410 __ Swap(r0, r1, ip); |
7405 } | 7411 } |
7406 | 7412 |
7407 if (ShouldGenerateFPCode()) { | 7413 if (ShouldGenerateFPCode()) { |
7408 Label r0_is_smi, r1_is_smi, finished_loading_r0, finished_loading_r1; | 7414 Label r0_is_smi, r1_is_smi, finished_loading_r0, finished_loading_r1; |
7409 | 7415 |
7410 if (runtime_operands_type_ == BinaryOpIC::DEFAULT) { | 7416 if (runtime_operands_type_ == BinaryOpIC::DEFAULT) { |
7411 switch (op_) { | 7417 switch (op_) { |
7412 case Token::ADD: | 7418 case Token::ADD: |
7413 case Token::SUB: | 7419 case Token::SUB: |
7414 case Token::MUL: | 7420 case Token::MUL: |
7415 case Token::DIV: | 7421 case Token::DIV: |
7416 GenerateTypeTransition(masm); | 7422 GenerateTypeTransition(masm); |
7417 break; | 7423 break; |
7418 | 7424 |
7419 default: | 7425 default: |
7420 break; | 7426 break; |
7421 } | 7427 } |
| 7428 // Restore heap number map register. |
| 7429 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
7422 } | 7430 } |
7423 | 7431 |
7424 if (mode_ == NO_OVERWRITE) { | 7432 if (mode_ == NO_OVERWRITE) { |
7425 // In the case where there is no chance of an overwritable float we may as | 7433 // In the case where there is no chance of an overwritable float we may as |
7426 // well do the allocation immediately while r0 and r1 are untouched. | 7434 // well do the allocation immediately while r0 and r1 are untouched. |
7427 __ AllocateHeapNumber(r5, r6, r7, &slow); | 7435 __ AllocateHeapNumber(r5, r3, r7, heap_number_map, &slow); |
7428 } | 7436 } |
7429 | 7437 |
7430 // Move r0 to a double in r2-r3. | 7438 // Move r0 to a double in r2-r3. |
7431 __ tst(r0, Operand(kSmiTagMask)); | 7439 __ tst(r0, Operand(kSmiTagMask)); |
7432 __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. | 7440 __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. |
7433 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); | 7441 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 7442 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 7443 __ cmp(r4, heap_number_map); |
7434 __ b(ne, &slow); | 7444 __ b(ne, &slow); |
7435 if (mode_ == OVERWRITE_RIGHT) { | 7445 if (mode_ == OVERWRITE_RIGHT) { |
7436 __ mov(r5, Operand(r0)); // Overwrite this heap number. | 7446 __ mov(r5, Operand(r0)); // Overwrite this heap number. |
7437 } | 7447 } |
7438 if (use_fp_registers) { | 7448 if (use_fp_registers) { |
7439 CpuFeatures::Scope scope(VFP3); | 7449 CpuFeatures::Scope scope(VFP3); |
7440 // Load the double from tagged HeapNumber r0 to d7. | 7450 // Load the double from tagged HeapNumber r0 to d7. |
7441 __ sub(r7, r0, Operand(kHeapObjectTag)); | 7451 __ sub(r7, r0, Operand(kHeapObjectTag)); |
7442 __ vldr(d7, r7, HeapNumber::kValueOffset); | 7452 __ vldr(d7, r7, HeapNumber::kValueOffset); |
7443 } else { | 7453 } else { |
7444 // Calling convention says that second double is in r2 and r3. | 7454 // Calling convention says that second double is in r2 and r3. |
7445 __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset)); | 7455 __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset)); |
7446 } | 7456 } |
7447 __ jmp(&finished_loading_r0); | 7457 __ jmp(&finished_loading_r0); |
7448 __ bind(&r0_is_smi); | 7458 __ bind(&r0_is_smi); |
7449 if (mode_ == OVERWRITE_RIGHT) { | 7459 if (mode_ == OVERWRITE_RIGHT) { |
7450 // We can't overwrite a Smi so get address of new heap number into r5. | 7460 // We can't overwrite a Smi so get address of new heap number into r5. |
7451 __ AllocateHeapNumber(r5, r6, r7, &slow); | 7461 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); |
7452 } | 7462 } |
7453 | 7463 |
7454 if (use_fp_registers) { | 7464 if (use_fp_registers) { |
7455 CpuFeatures::Scope scope(VFP3); | 7465 CpuFeatures::Scope scope(VFP3); |
7456 // Convert smi in r0 to double in d7. | 7466 // Convert smi in r0 to double in d7. |
7457 __ mov(r7, Operand(r0, ASR, kSmiTagSize)); | 7467 __ mov(r7, Operand(r0, ASR, kSmiTagSize)); |
7458 __ vmov(s15, r7); | 7468 __ vmov(s15, r7); |
7459 __ vcvt_f64_s32(d7, s15); | 7469 __ vcvt_f64_s32(d7, s15); |
7460 } else { | 7470 } else { |
7461 // Write Smi from r0 to r3 and r2 in double format. | 7471 // Write Smi from r0 to r3 and r2 in double format. |
7462 __ mov(r7, Operand(r0)); | 7472 __ mov(r7, Operand(r0)); |
7463 ConvertToDoubleStub stub3(r3, r2, r7, r6); | 7473 ConvertToDoubleStub stub3(r3, r2, r7, r4); |
7464 __ push(lr); | 7474 __ push(lr); |
7465 __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET); | 7475 __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET); |
7466 __ pop(lr); | 7476 __ pop(lr); |
7467 } | 7477 } |
7468 | 7478 |
7469 // HEAP_NUMBERS stub is slower than GENERIC on a pair of smis. | 7479 // HEAP_NUMBERS stub is slower than GENERIC on a pair of smis. |
7470 // r0 is known to be a smi. If r1 is also a smi then switch to GENERIC. | 7480 // r0 is known to be a smi. If r1 is also a smi then switch to GENERIC. |
7471 Label r1_is_not_smi; | 7481 Label r1_is_not_smi; |
7472 if (runtime_operands_type_ == BinaryOpIC::HEAP_NUMBERS) { | 7482 if (runtime_operands_type_ == BinaryOpIC::HEAP_NUMBERS) { |
7473 __ tst(r1, Operand(kSmiTagMask)); | 7483 __ tst(r1, Operand(kSmiTagMask)); |
7474 __ b(ne, &r1_is_not_smi); | 7484 __ b(ne, &r1_is_not_smi); |
7475 GenerateTypeTransition(masm); | 7485 GenerateTypeTransition(masm); |
| 7486 // Restore heap number map register. |
| 7487 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
7476 __ jmp(&r1_is_smi); | 7488 __ jmp(&r1_is_smi); |
7477 } | 7489 } |
7478 | 7490 |
7479 __ bind(&finished_loading_r0); | 7491 __ bind(&finished_loading_r0); |
7480 | 7492 |
7481 // Move r1 to a double in r0-r1. | 7493 // Move r1 to a double in r0-r1. |
7482 __ tst(r1, Operand(kSmiTagMask)); | 7494 __ tst(r1, Operand(kSmiTagMask)); |
7483 __ b(eq, &r1_is_smi); // It's a Smi so don't check it's a heap number. | 7495 __ b(eq, &r1_is_smi); // It's a Smi so don't check it's a heap number. |
7484 __ bind(&r1_is_not_smi); | 7496 __ bind(&r1_is_not_smi); |
7485 __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE); | 7497 __ ldr(r4, FieldMemOperand(r1, HeapNumber::kMapOffset)); |
| 7498 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 7499 __ cmp(r4, heap_number_map); |
7486 __ b(ne, &slow); | 7500 __ b(ne, &slow); |
7487 if (mode_ == OVERWRITE_LEFT) { | 7501 if (mode_ == OVERWRITE_LEFT) { |
7488 __ mov(r5, Operand(r1)); // Overwrite this heap number. | 7502 __ mov(r5, Operand(r1)); // Overwrite this heap number. |
7489 } | 7503 } |
7490 if (use_fp_registers) { | 7504 if (use_fp_registers) { |
7491 CpuFeatures::Scope scope(VFP3); | 7505 CpuFeatures::Scope scope(VFP3); |
7492 // Load the double from tagged HeapNumber r1 to d6. | 7506 // Load the double from tagged HeapNumber r1 to d6. |
7493 __ sub(r7, r1, Operand(kHeapObjectTag)); | 7507 __ sub(r7, r1, Operand(kHeapObjectTag)); |
7494 __ vldr(d6, r7, HeapNumber::kValueOffset); | 7508 __ vldr(d6, r7, HeapNumber::kValueOffset); |
7495 } else { | 7509 } else { |
7496 // Calling convention says that first double is in r0 and r1. | 7510 // Calling convention says that first double is in r0 and r1. |
7497 __ Ldrd(r0, r1, FieldMemOperand(r1, HeapNumber::kValueOffset)); | 7511 __ Ldrd(r0, r1, FieldMemOperand(r1, HeapNumber::kValueOffset)); |
7498 } | 7512 } |
7499 __ jmp(&finished_loading_r1); | 7513 __ jmp(&finished_loading_r1); |
7500 __ bind(&r1_is_smi); | 7514 __ bind(&r1_is_smi); |
7501 if (mode_ == OVERWRITE_LEFT) { | 7515 if (mode_ == OVERWRITE_LEFT) { |
7502 // We can't overwrite a Smi so get address of new heap number into r5. | 7516 // We can't overwrite a Smi so get address of new heap number into r5. |
7503 __ AllocateHeapNumber(r5, r6, r7, &slow); | 7517 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); |
7504 } | 7518 } |
7505 | 7519 |
7506 if (use_fp_registers) { | 7520 if (use_fp_registers) { |
7507 CpuFeatures::Scope scope(VFP3); | 7521 CpuFeatures::Scope scope(VFP3); |
7508 // Convert smi in r1 to double in d6. | 7522 // Convert smi in r1 to double in d6. |
7509 __ mov(r7, Operand(r1, ASR, kSmiTagSize)); | 7523 __ mov(r7, Operand(r1, ASR, kSmiTagSize)); |
7510 __ vmov(s13, r7); | 7524 __ vmov(s13, r7); |
7511 __ vcvt_f64_s32(d6, s13); | 7525 __ vcvt_f64_s32(d6, s13); |
7512 } else { | 7526 } else { |
7513 // Write Smi from r1 to r1 and r0 in double format. | 7527 // Write Smi from r1 to r1 and r0 in double format. |
7514 __ mov(r7, Operand(r1)); | 7528 __ mov(r7, Operand(r1)); |
7515 ConvertToDoubleStub stub4(r1, r0, r7, r6); | 7529 ConvertToDoubleStub stub4(r1, r0, r7, r9); |
7516 __ push(lr); | 7530 __ push(lr); |
7517 __ Call(stub4.GetCode(), RelocInfo::CODE_TARGET); | 7531 __ Call(stub4.GetCode(), RelocInfo::CODE_TARGET); |
7518 __ pop(lr); | 7532 __ pop(lr); |
7519 } | 7533 } |
7520 | 7534 |
7521 __ bind(&finished_loading_r1); | 7535 __ bind(&finished_loading_r1); |
7522 | 7536 |
7523 __ bind(&do_the_call); | 7537 __ bind(&do_the_call); |
7524 // If we are inlining the operation using VFP3 instructions for | 7538 // If we are inlining the operation using VFP3 instructions for |
7525 // add, subtract, multiply, or divide, the arguments are in d6 and d7. | 7539 // add, subtract, multiply, or divide, the arguments are in d6 and d7. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7566 #else | 7580 #else |
7567 // Double returned in registers 0 and 1. | 7581 // Double returned in registers 0 and 1. |
7568 __ Strd(r0, r1, FieldMemOperand(r5, HeapNumber::kValueOffset)); | 7582 __ Strd(r0, r1, FieldMemOperand(r5, HeapNumber::kValueOffset)); |
7569 #endif | 7583 #endif |
7570 __ mov(r0, Operand(r5)); | 7584 __ mov(r0, Operand(r5)); |
7571 // And we are done. | 7585 // And we are done. |
7572 __ pop(pc); | 7586 __ pop(pc); |
7573 } | 7587 } |
7574 } | 7588 } |
7575 | 7589 |
7576 | |
7577 if (lhs.is(r0)) { | 7590 if (lhs.is(r0)) { |
7578 __ b(&slow); | 7591 __ b(&slow); |
7579 __ bind(&slow_reverse); | 7592 __ bind(&slow_reverse); |
7580 __ Swap(r0, r1, ip); | 7593 __ Swap(r0, r1, ip); |
7581 } | 7594 } |
7582 | 7595 |
| 7596 heap_number_map = no_reg; // Don't use this any more from here on. |
| 7597 |
7583 // We jump to here if something goes wrong (one param is not a number of any | 7598 // We jump to here if something goes wrong (one param is not a number of any |
7584 // sort or new-space allocation fails). | 7599 // sort or new-space allocation fails). |
7585 __ bind(&slow); | 7600 __ bind(&slow); |
7586 | 7601 |
7587 // Push arguments to the stack | 7602 // Push arguments to the stack |
7588 __ Push(r1, r0); | 7603 __ Push(r1, r0); |
7589 | 7604 |
7590 if (Token::ADD == op_) { | 7605 if (Token::ADD == op_) { |
7591 // Test for string arguments before calling runtime. | 7606 // Test for string arguments before calling runtime. |
7592 // r1 : first argument | 7607 // r1 : first argument |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7738 // result is a Smi. If so, great, otherwise we try to find a heap number to | 7753 // result is a Smi. If so, great, otherwise we try to find a heap number to |
7739 // write the answer into (either by allocating or by overwriting). | 7754 // write the answer into (either by allocating or by overwriting). |
7740 // On entry the operands are in lhs and rhs. On exit the answer is in r0. | 7755 // On entry the operands are in lhs and rhs. On exit the answer is in r0. |
7741 void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm, | 7756 void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm, |
7742 Register lhs, | 7757 Register lhs, |
7743 Register rhs) { | 7758 Register rhs) { |
7744 Label slow, result_not_a_smi; | 7759 Label slow, result_not_a_smi; |
7745 Label rhs_is_smi, lhs_is_smi; | 7760 Label rhs_is_smi, lhs_is_smi; |
7746 Label done_checking_rhs, done_checking_lhs; | 7761 Label done_checking_rhs, done_checking_lhs; |
7747 | 7762 |
| 7763 Register heap_number_map = r6; |
| 7764 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 7765 |
7748 __ tst(lhs, Operand(kSmiTagMask)); | 7766 __ tst(lhs, Operand(kSmiTagMask)); |
7749 __ b(eq, &lhs_is_smi); // It's a Smi so don't check it's a heap number. | 7767 __ b(eq, &lhs_is_smi); // It's a Smi so don't check it's a heap number. |
7750 __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE); | 7768 __ ldr(r4, FieldMemOperand(lhs, HeapNumber::kMapOffset)); |
| 7769 __ cmp(r4, heap_number_map); |
7751 __ b(ne, &slow); | 7770 __ b(ne, &slow); |
7752 GetInt32(masm, lhs, r3, r5, r4, &slow); | 7771 GetInt32(masm, lhs, r3, r5, r4, &slow); |
7753 __ jmp(&done_checking_lhs); | 7772 __ jmp(&done_checking_lhs); |
7754 __ bind(&lhs_is_smi); | 7773 __ bind(&lhs_is_smi); |
7755 __ mov(r3, Operand(lhs, ASR, 1)); | 7774 __ mov(r3, Operand(lhs, ASR, 1)); |
7756 __ bind(&done_checking_lhs); | 7775 __ bind(&done_checking_lhs); |
7757 | 7776 |
7758 __ tst(rhs, Operand(kSmiTagMask)); | 7777 __ tst(rhs, Operand(kSmiTagMask)); |
7759 __ b(eq, &rhs_is_smi); // It's a Smi so don't check it's a heap number. | 7778 __ b(eq, &rhs_is_smi); // It's a Smi so don't check it's a heap number. |
7760 __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE); | 7779 __ ldr(r4, FieldMemOperand(rhs, HeapNumber::kMapOffset)); |
| 7780 __ cmp(r4, heap_number_map); |
7761 __ b(ne, &slow); | 7781 __ b(ne, &slow); |
7762 GetInt32(masm, rhs, r2, r5, r4, &slow); | 7782 GetInt32(masm, rhs, r2, r5, r4, &slow); |
7763 __ jmp(&done_checking_rhs); | 7783 __ jmp(&done_checking_rhs); |
7764 __ bind(&rhs_is_smi); | 7784 __ bind(&rhs_is_smi); |
7765 __ mov(r2, Operand(rhs, ASR, 1)); | 7785 __ mov(r2, Operand(rhs, ASR, 1)); |
7766 __ bind(&done_checking_rhs); | 7786 __ bind(&done_checking_rhs); |
7767 | 7787 |
7768 ASSERT(((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0)))); | 7788 ASSERT(((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0)))); |
7769 | 7789 |
7770 // r0 and r1: Original operands (Smi or heap numbers). | 7790 // r0 and r1: Original operands (Smi or heap numbers). |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7810 __ mov(r5, Operand(rhs)); | 7830 __ mov(r5, Operand(rhs)); |
7811 break; | 7831 break; |
7812 } | 7832 } |
7813 case OVERWRITE_LEFT: { | 7833 case OVERWRITE_LEFT: { |
7814 __ tst(lhs, Operand(kSmiTagMask)); | 7834 __ tst(lhs, Operand(kSmiTagMask)); |
7815 __ b(eq, &have_to_allocate); | 7835 __ b(eq, &have_to_allocate); |
7816 __ mov(r5, Operand(lhs)); | 7836 __ mov(r5, Operand(lhs)); |
7817 break; | 7837 break; |
7818 } | 7838 } |
7819 case NO_OVERWRITE: { | 7839 case NO_OVERWRITE: { |
7820 // Get a new heap number in r5. r6 and r7 are scratch. | 7840 // Get a new heap number in r5. r4 and r7 are scratch. |
7821 __ AllocateHeapNumber(r5, r6, r7, &slow); | 7841 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); |
7822 } | 7842 } |
7823 default: break; | 7843 default: break; |
7824 } | 7844 } |
7825 __ bind(&got_a_heap_number); | 7845 __ bind(&got_a_heap_number); |
7826 // r2: Answer as signed int32. | 7846 // r2: Answer as signed int32. |
7827 // r5: Heap number to write answer into. | 7847 // r5: Heap number to write answer into. |
7828 | 7848 |
7829 // Nothing can go wrong now, so move the heap number to r0, which is the | 7849 // Nothing can go wrong now, so move the heap number to r0, which is the |
7830 // result. | 7850 // result. |
7831 __ mov(r0, Operand(r5)); | 7851 __ mov(r0, Operand(r5)); |
7832 | 7852 |
7833 // Tail call that writes the int32 in r2 to the heap number in r0, using | 7853 // Tail call that writes the int32 in r2 to the heap number in r0, using |
7834 // r3 as scratch. r0 is preserved and returned. | 7854 // r3 as scratch. r0 is preserved and returned. |
7835 WriteInt32ToHeapNumberStub stub(r2, r0, r3); | 7855 WriteInt32ToHeapNumberStub stub(r2, r0, r3); |
7836 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 7856 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
7837 | 7857 |
7838 if (mode_ != NO_OVERWRITE) { | 7858 if (mode_ != NO_OVERWRITE) { |
7839 __ bind(&have_to_allocate); | 7859 __ bind(&have_to_allocate); |
7840 // Get a new heap number in r5. r6 and r7 are scratch. | 7860 // Get a new heap number in r5. r4 and r7 are scratch. |
7841 __ AllocateHeapNumber(r5, r6, r7, &slow); | 7861 __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow); |
7842 __ jmp(&got_a_heap_number); | 7862 __ jmp(&got_a_heap_number); |
7843 } | 7863 } |
7844 | 7864 |
7845 // If all else failed then we go to the runtime system. | 7865 // If all else failed then we go to the runtime system. |
7846 __ bind(&slow); | 7866 __ bind(&slow); |
7847 __ Push(lhs, rhs); // Restore stack. | 7867 __ Push(lhs, rhs); // Restore stack. |
7848 switch (op_) { | 7868 switch (op_) { |
7849 case Token::BIT_OR: | 7869 case Token::BIT_OR: |
7850 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS); | 7870 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS); |
7851 break; | 7871 break; |
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8402 __ push(r0); | 8422 __ push(r0); |
8403 __ TailCallRuntime(Runtime::kStackGuard, 1, 1); | 8423 __ TailCallRuntime(Runtime::kStackGuard, 1, 1); |
8404 | 8424 |
8405 __ StubReturn(1); | 8425 __ StubReturn(1); |
8406 } | 8426 } |
8407 | 8427 |
8408 | 8428 |
8409 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | 8429 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
8410 Label slow, done; | 8430 Label slow, done; |
8411 | 8431 |
| 8432 Register heap_number_map = r6; |
| 8433 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 8434 |
8412 if (op_ == Token::SUB) { | 8435 if (op_ == Token::SUB) { |
8413 // Check whether the value is a smi. | 8436 // Check whether the value is a smi. |
8414 Label try_float; | 8437 Label try_float; |
8415 __ tst(r0, Operand(kSmiTagMask)); | 8438 __ tst(r0, Operand(kSmiTagMask)); |
8416 __ b(ne, &try_float); | 8439 __ b(ne, &try_float); |
8417 | 8440 |
8418 // Go slow case if the value of the expression is zero | 8441 // Go slow case if the value of the expression is zero |
8419 // to make sure that we switch between 0 and -0. | 8442 // to make sure that we switch between 0 and -0. |
8420 __ cmp(r0, Operand(0)); | 8443 __ cmp(r0, Operand(0)); |
8421 __ b(eq, &slow); | 8444 __ b(eq, &slow); |
8422 | 8445 |
8423 // The value of the expression is a smi that is not zero. Try | 8446 // The value of the expression is a smi that is not zero. Try |
8424 // optimistic subtraction '0 - value'. | 8447 // optimistic subtraction '0 - value'. |
8425 __ rsb(r1, r0, Operand(0), SetCC); | 8448 __ rsb(r1, r0, Operand(0), SetCC); |
8426 __ b(vs, &slow); | 8449 __ b(vs, &slow); |
8427 | 8450 |
8428 __ mov(r0, Operand(r1)); // Set r0 to result. | 8451 __ mov(r0, Operand(r1)); // Set r0 to result. |
8429 __ b(&done); | 8452 __ b(&done); |
8430 | 8453 |
8431 __ bind(&try_float); | 8454 __ bind(&try_float); |
8432 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); | 8455 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 8456 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 8457 __ cmp(r1, heap_number_map); |
8433 __ b(ne, &slow); | 8458 __ b(ne, &slow); |
8434 // r0 is a heap number. Get a new heap number in r1. | 8459 // r0 is a heap number. Get a new heap number in r1. |
8435 if (overwrite_) { | 8460 if (overwrite_) { |
8436 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 8461 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
8437 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | 8462 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
8438 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 8463 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
8439 } else { | 8464 } else { |
8440 __ AllocateHeapNumber(r1, r2, r3, &slow); | 8465 __ AllocateHeapNumber(r1, r2, r3, r6, &slow); |
8441 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 8466 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); |
8442 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 8467 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); |
8443 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); | 8468 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); |
8444 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | 8469 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. |
8445 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); | 8470 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); |
8446 __ mov(r0, Operand(r1)); | 8471 __ mov(r0, Operand(r1)); |
8447 } | 8472 } |
8448 } else if (op_ == Token::BIT_NOT) { | 8473 } else if (op_ == Token::BIT_NOT) { |
8449 // Check if the operand is a heap number. | 8474 // Check if the operand is a heap number. |
8450 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); | 8475 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 8476 __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 8477 __ cmp(r1, heap_number_map); |
8451 __ b(ne, &slow); | 8478 __ b(ne, &slow); |
8452 | 8479 |
8453 // Convert the heap number is r0 to an untagged integer in r1. | 8480 // Convert the heap number is r0 to an untagged integer in r1. |
8454 GetInt32(masm, r0, r1, r2, r3, &slow); | 8481 GetInt32(masm, r0, r1, r2, r3, &slow); |
8455 | 8482 |
8456 // Do the bitwise operation (move negated) and check if the result | 8483 // Do the bitwise operation (move negated) and check if the result |
8457 // fits in a smi. | 8484 // fits in a smi. |
8458 Label try_float; | 8485 Label try_float; |
8459 __ mvn(r1, Operand(r1)); | 8486 __ mvn(r1, Operand(r1)); |
8460 __ add(r2, r1, Operand(0x40000000), SetCC); | 8487 __ add(r2, r1, Operand(0x40000000), SetCC); |
8461 __ b(mi, &try_float); | 8488 __ b(mi, &try_float); |
8462 __ mov(r0, Operand(r1, LSL, kSmiTagSize)); | 8489 __ mov(r0, Operand(r1, LSL, kSmiTagSize)); |
8463 __ b(&done); | 8490 __ b(&done); |
8464 | 8491 |
8465 __ bind(&try_float); | 8492 __ bind(&try_float); |
8466 if (!overwrite_) { | 8493 if (!overwrite_) { |
8467 // Allocate a fresh heap number, but don't overwrite r0 until | 8494 // Allocate a fresh heap number, but don't overwrite r0 until |
8468 // we're sure we can do it without going through the slow case | 8495 // we're sure we can do it without going through the slow case |
8469 // that needs the value in r0. | 8496 // that needs the value in r0. |
8470 __ AllocateHeapNumber(r2, r3, r4, &slow); | 8497 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); |
8471 __ mov(r0, Operand(r2)); | 8498 __ mov(r0, Operand(r2)); |
8472 } | 8499 } |
8473 | 8500 |
8474 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not | 8501 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not |
8475 // have to set up a frame. | 8502 // have to set up a frame. |
8476 WriteInt32ToHeapNumberStub stub(r1, r0, r2); | 8503 WriteInt32ToHeapNumberStub stub(r1, r0, r2); |
8477 __ push(lr); | 8504 __ push(lr); |
8478 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); | 8505 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); |
8479 __ pop(lr); | 8506 __ pop(lr); |
8480 } else { | 8507 } else { |
(...skipping 2209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10690 __ bind(&string_add_runtime); | 10717 __ bind(&string_add_runtime); |
10691 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10718 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10692 } | 10719 } |
10693 | 10720 |
10694 | 10721 |
10695 #undef __ | 10722 #undef __ |
10696 | 10723 |
10697 } } // namespace v8::internal | 10724 } } // namespace v8::internal |
10698 | 10725 |
10699 #endif // V8_TARGET_ARCH_ARM | 10726 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |