Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2426 | 2426 |
| 2427 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 2427 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
| 2428 "TypeRecordingBinaryOpStub_%s_%s_%s", | 2428 "TypeRecordingBinaryOpStub_%s_%s_%s", |
| 2429 op_name, | 2429 op_name, |
| 2430 overwrite_name, | 2430 overwrite_name, |
| 2431 TRBinaryOpIC::GetName(operands_type_)); | 2431 TRBinaryOpIC::GetName(operands_type_)); |
| 2432 return name_; | 2432 return name_; |
| 2433 } | 2433 } |
| 2434 | 2434 |
| 2435 | 2435 |
| 2436 void TypeRecordingBinaryOpStub::GenerateOptimisticSmiOperation( | |
| 2437 MacroAssembler* masm) { | |
| 2438 Register left = r1; | |
| 2439 Register right = r0; | |
| 2440 | |
| 2441 ASSERT(right.is(r0)); | |
| 2442 | |
| 2443 switch (op_) { | |
| 2444 case Token::ADD: | |
| 2445 __ add(right, left, Operand(right), SetCC); // Add optimistically. | |
| 2446 __ Ret(vc); | |
| 2447 __ sub(right, right, Operand(left)); // Revert optimistic add. | |
| 2448 break; | |
| 2449 case Token::SUB: | |
| 2450 __ sub(right, left, Operand(right), SetCC); // Subtract optimistically. | |
| 2451 __ Ret(vc); | |
| 2452 __ sub(right, left, Operand(right)); // Revert optimistic subtract. | |
|
Alexandre
2011/01/25 16:51:15
Shouldn't it be an add(right, right, Operand(left)
Alexandre
2011/01/25 16:54:45
Sorry I messed up with these right and left.
On 20
| |
| 2453 break; | |
| 2454 default: | |
| 2455 UNREACHABLE(); | |
| 2456 } | |
| 2457 } | |
| 2458 | |
| 2459 | |
| 2460 void TypeRecordingBinaryOpStub::GenerateVFPOperation( | |
| 2461 MacroAssembler* masm) { | |
| 2462 switch (op_) { | |
| 2463 case Token::ADD: | |
| 2464 __ vadd(d5, d6, d7); | |
| 2465 break; | |
| 2466 case Token::SUB: | |
| 2467 __ vsub(d5, d6, d7); | |
| 2468 break; | |
| 2469 default: | |
| 2470 UNREACHABLE(); | |
| 2471 } | |
| 2472 | |
| 2473 } | |
| 2474 | |
| 2475 | |
| 2436 // Generate the smi code. If the operation on smis are successful this return is | 2476 // Generate the smi code. If the operation on smis are successful this return is |
| 2437 // generated. If the result is not a smi and heap number allocation is not | 2477 // generated. If the result is not a smi and heap number allocation is not |
| 2438 // requested the code falls through. If number allocation is requested but a | 2478 // requested the code falls through. If number allocation is requested but a |
| 2439 // heap number cannot be allocated the code jumps to the lable gc_required. | 2479 // heap number cannot be allocated the code jumps to the lable gc_required. |
| 2440 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, | 2480 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
| 2441 Label* gc_required, | 2481 Label* gc_required, |
| 2442 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { | 2482 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { |
| 2443 Label not_smis; | 2483 Label not_smis; |
| 2444 | 2484 |
| 2445 ASSERT(op_ == Token::ADD); | 2485 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
| 2446 | 2486 |
| 2447 Register left = r1; | 2487 Register left = r1; |
| 2448 Register right = r0; | 2488 Register right = r0; |
| 2449 Register scratch1 = r7; | 2489 Register scratch1 = r7; |
| 2450 Register scratch2 = r9; | 2490 Register scratch2 = r9; |
| 2451 | 2491 |
| 2452 // Perform combined smi check on both operands. | 2492 // Perform combined smi check on both operands. |
| 2453 __ orr(scratch1, left, Operand(right)); | 2493 __ orr(scratch1, left, Operand(right)); |
| 2454 STATIC_ASSERT(kSmiTag == 0); | 2494 STATIC_ASSERT(kSmiTag == 0); |
| 2455 __ tst(scratch1, Operand(kSmiTagMask)); | 2495 __ tst(scratch1, Operand(kSmiTagMask)); |
| 2456 __ b(ne, ¬_smis); | 2496 __ b(ne, ¬_smis); |
| 2457 | 2497 |
| 2458 __ add(right, right, Operand(left), SetCC); // Add optimistically. | 2498 GenerateOptimisticSmiOperation(masm); |
| 2459 | |
| 2460 // Return smi result if no overflow (r0 is the result). | |
| 2461 ASSERT(right.is(r0)); | |
| 2462 __ Ret(vc); | |
| 2463 | |
| 2464 // Result is not a smi. Revert the optimistic add. | |
| 2465 __ sub(right, right, Operand(left)); | |
| 2466 | 2499 |
| 2467 // If heap number results are possible generate the result in an allocated | 2500 // If heap number results are possible generate the result in an allocated |
| 2468 // heap number. | 2501 // heap number. |
| 2469 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { | 2502 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { |
| 2470 FloatingPointHelper::Destination destination = | 2503 FloatingPointHelper::Destination destination = |
| 2471 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? | 2504 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? |
| 2472 FloatingPointHelper::kVFPRegisters : | 2505 FloatingPointHelper::kVFPRegisters : |
| 2473 FloatingPointHelper::kCoreRegisters; | 2506 FloatingPointHelper::kCoreRegisters; |
| 2474 | 2507 |
| 2475 Register heap_number_map = r6; | 2508 Register heap_number_map = r6; |
| 2476 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2509 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 2477 | 2510 |
| 2478 // Allocate new heap number for result. | 2511 // Allocate new heap number for result. |
| 2479 Register heap_number = r5; | 2512 Register heap_number = r5; |
| 2480 __ AllocateHeapNumber( | 2513 __ AllocateHeapNumber( |
| 2481 heap_number, scratch1, scratch2, heap_number_map, gc_required); | 2514 heap_number, scratch1, scratch2, heap_number_map, gc_required); |
| 2482 | 2515 |
| 2483 // Load the smis. | 2516 // Load the smis. |
| 2484 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); | 2517 FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2); |
| 2485 | 2518 |
| 2486 // Calculate the result. | 2519 // Calculate the result. |
| 2487 if (destination == FloatingPointHelper::kVFPRegisters) { | 2520 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 2488 // Using VFP registers: | 2521 // Using VFP registers: |
| 2489 // d6: Left value | 2522 // d6: Left value |
| 2490 // d7: Right value | 2523 // d7: Right value |
| 2491 CpuFeatures::Scope scope(VFP3); | 2524 CpuFeatures::Scope scope(VFP3); |
| 2492 __ vadd(d5, d6, d7); | 2525 GenerateVFPOperation(masm); |
| 2493 | 2526 |
| 2494 __ sub(r0, heap_number, Operand(kHeapObjectTag)); | 2527 __ sub(r0, heap_number, Operand(kHeapObjectTag)); |
| 2495 __ vstr(d5, r0, HeapNumber::kValueOffset); | 2528 __ vstr(d5, r0, HeapNumber::kValueOffset); |
| 2496 __ add(r0, r0, Operand(kHeapObjectTag)); | 2529 __ add(r0, r0, Operand(kHeapObjectTag)); |
| 2497 __ Ret(); | 2530 __ Ret(); |
| 2498 } else { | 2531 } else { |
| 2499 // Using core registers: | 2532 // Using core registers: |
| 2500 // r0: Left value (least significant part of mantissa). | 2533 // r0: Left value (least significant part of mantissa). |
| 2501 // r1: Left value (sign, exponent, top of mantissa). | 2534 // r1: Left value (sign, exponent, top of mantissa). |
| 2502 // r2: Right value (least significant part of mantissa). | 2535 // r2: Right value (least significant part of mantissa). |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2523 __ pop(pc); | 2556 __ pop(pc); |
| 2524 } | 2557 } |
| 2525 } | 2558 } |
| 2526 __ bind(¬_smis); | 2559 __ bind(¬_smis); |
| 2527 } | 2560 } |
| 2528 | 2561 |
| 2529 | 2562 |
| 2530 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 2563 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
| 2531 Label not_smis, call_runtime; | 2564 Label not_smis, call_runtime; |
| 2532 | 2565 |
| 2533 ASSERT(op_ == Token::ADD); | 2566 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
| 2534 | 2567 |
| 2535 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || | 2568 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || |
| 2536 result_type_ == TRBinaryOpIC::SMI) { | 2569 result_type_ == TRBinaryOpIC::SMI) { |
| 2537 // Only allow smi results. | 2570 // Only allow smi results. |
| 2538 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); | 2571 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); |
| 2539 } else { | 2572 } else { |
| 2540 // Allow heap number result and don't make a transition if a heap number | 2573 // Allow heap number result and don't make a transition if a heap number |
| 2541 // cannot be allocated. | 2574 // cannot be allocated. |
| 2542 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2575 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
| 2543 } | 2576 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2555 ASSERT(operands_type_ == TRBinaryOpIC::STRING); | 2588 ASSERT(operands_type_ == TRBinaryOpIC::STRING); |
| 2556 ASSERT(op_ == Token::ADD); | 2589 ASSERT(op_ == Token::ADD); |
| 2557 // Try to add arguments as strings, otherwise, transition to the generic | 2590 // Try to add arguments as strings, otherwise, transition to the generic |
| 2558 // TRBinaryOpIC type. | 2591 // TRBinaryOpIC type. |
| 2559 GenerateAddStrings(masm); | 2592 GenerateAddStrings(masm); |
| 2560 GenerateTypeTransition(masm); | 2593 GenerateTypeTransition(masm); |
| 2561 } | 2594 } |
| 2562 | 2595 |
| 2563 | 2596 |
| 2564 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 2597 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
| 2565 ASSERT(op_ == Token::ADD); | 2598 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
| 2566 | 2599 |
| 2567 ASSERT(operands_type_ == TRBinaryOpIC::INT32); | 2600 ASSERT(operands_type_ == TRBinaryOpIC::INT32); |
| 2568 | 2601 |
| 2569 GenerateTypeTransition(masm); | 2602 GenerateTypeTransition(masm); |
| 2570 } | 2603 } |
| 2571 | 2604 |
| 2572 | 2605 |
| 2573 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { | 2606 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
| 2574 ASSERT(op_ == Token::ADD); | 2607 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
| 2575 | 2608 |
| 2576 Register scratch1 = r7; | 2609 Register scratch1 = r7; |
| 2577 Register scratch2 = r9; | 2610 Register scratch2 = r9; |
| 2578 | 2611 |
| 2579 Label not_number, call_runtime; | 2612 Label not_number, call_runtime; |
| 2580 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); | 2613 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); |
| 2581 | 2614 |
| 2582 Register heap_number_map = r6; | 2615 Register heap_number_map = r6; |
| 2583 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2616 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 2584 | 2617 |
| 2585 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending on | 2618 // Load left and right operands into d6 and d7 or r0/r1 and r2/r3 depending on |
| 2586 // whether VFP3 is available. | 2619 // whether VFP3 is available. |
| 2587 FloatingPointHelper::Destination destination = | 2620 FloatingPointHelper::Destination destination = |
| 2588 CpuFeatures::IsSupported(VFP3) ? | 2621 CpuFeatures::IsSupported(VFP3) ? |
| 2589 FloatingPointHelper::kVFPRegisters : | 2622 FloatingPointHelper::kVFPRegisters : |
| 2590 FloatingPointHelper::kCoreRegisters; | 2623 FloatingPointHelper::kCoreRegisters; |
| 2591 FloatingPointHelper::LoadOperands(masm, | 2624 FloatingPointHelper::LoadOperands(masm, |
| 2592 destination, | 2625 destination, |
| 2593 heap_number_map, | 2626 heap_number_map, |
| 2594 scratch1, | 2627 scratch1, |
| 2595 scratch2, | 2628 scratch2, |
| 2596 ¬_number); | 2629 ¬_number); |
| 2597 if (destination == FloatingPointHelper::kVFPRegisters) { | 2630 if (destination == FloatingPointHelper::kVFPRegisters) { |
| 2598 // Use floating point instructions for the binary operation. | 2631 // Use floating point instructions for the binary operation. |
| 2599 CpuFeatures::Scope scope(VFP3); | 2632 CpuFeatures::Scope scope(VFP3); |
| 2600 __ vadd(d5, d6, d7); | 2633 GenerateVFPOperation(masm); |
| 2601 | 2634 |
| 2602 // Get a heap number object for the result - might be left or right if one | 2635 // Get a heap number object for the result - might be left or right if one |
| 2603 // of these are overwritable. | 2636 // of these are overwritable. |
| 2604 GenerateHeapResultAllocation( | 2637 GenerateHeapResultAllocation( |
| 2605 masm, r4, heap_number_map, scratch1, scratch2, &call_runtime); | 2638 masm, r4, heap_number_map, scratch1, scratch2, &call_runtime); |
| 2606 | 2639 |
| 2607 // Fill the result into the allocated heap number and return. | 2640 // Fill the result into the allocated heap number and return. |
| 2608 __ sub(r0, r4, Operand(kHeapObjectTag)); | 2641 __ sub(r0, r4, Operand(kHeapObjectTag)); |
| 2609 __ vstr(d5, r0, HeapNumber::kValueOffset); | 2642 __ vstr(d5, r0, HeapNumber::kValueOffset); |
| 2610 __ add(r0, r0, Operand(kHeapObjectTag)); | 2643 __ add(r0, r0, Operand(kHeapObjectTag)); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2644 | 2677 |
| 2645 __ bind(¬_number); | 2678 __ bind(¬_number); |
| 2646 GenerateTypeTransition(masm); | 2679 GenerateTypeTransition(masm); |
| 2647 | 2680 |
| 2648 __ bind(&call_runtime); | 2681 __ bind(&call_runtime); |
| 2649 GenerateCallRuntime(masm); | 2682 GenerateCallRuntime(masm); |
| 2650 } | 2683 } |
| 2651 | 2684 |
| 2652 | 2685 |
| 2653 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { | 2686 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
| 2654 ASSERT(op_ == Token::ADD); | 2687 ASSERT(op_ == Token::ADD || op_ == Token::SUB); |
| 2655 | 2688 |
| 2656 Label call_runtime; | 2689 Label call_runtime; |
| 2657 | 2690 |
| 2658 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2691 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
| 2659 | 2692 |
| 2660 // If all else fails, use the runtime system to get the correct | 2693 // If all else fails, use the runtime system to get the correct |
| 2661 // result. | 2694 // result. |
| 2662 __ bind(&call_runtime); | 2695 __ bind(&call_runtime); |
| 2663 | 2696 |
| 2664 // Try to add strings before calling runtime. | 2697 // Try to add strings before calling runtime. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 2688 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | 2721 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
| 2689 GenerateRegisterArgsPush(masm); | 2722 GenerateRegisterArgsPush(masm); |
| 2690 __ TailCallStub(&string_add_stub); | 2723 __ TailCallStub(&string_add_stub); |
| 2691 | 2724 |
| 2692 // At least one argument is not a string. | 2725 // At least one argument is not a string. |
| 2693 __ bind(&call_runtime); | 2726 __ bind(&call_runtime); |
| 2694 } | 2727 } |
| 2695 | 2728 |
| 2696 | 2729 |
| 2697 void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { | 2730 void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { |
| 2731 GenerateRegisterArgsPush(masm); | |
| 2698 switch (op_) { | 2732 switch (op_) { |
| 2699 case Token::ADD: | 2733 case Token::ADD: |
| 2700 GenerateRegisterArgsPush(masm); | |
| 2701 __ InvokeBuiltin(Builtins::ADD, JUMP_JS); | 2734 __ InvokeBuiltin(Builtins::ADD, JUMP_JS); |
| 2702 break; | 2735 break; |
| 2736 case Token::SUB: | |
| 2737 __ InvokeBuiltin(Builtins::SUB, JUMP_JS); | |
| 2738 break; | |
| 2703 default: | 2739 default: |
| 2704 UNREACHABLE(); | 2740 UNREACHABLE(); |
| 2705 } | 2741 } |
| 2706 } | 2742 } |
| 2707 | 2743 |
| 2708 | 2744 |
| 2709 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( | 2745 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( |
| 2710 MacroAssembler* masm, | 2746 MacroAssembler* masm, |
| 2711 Register result, | 2747 Register result, |
| 2712 Register heap_number_map, | 2748 Register heap_number_map, |
| (...skipping 2907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5620 __ pop(r1); | 5656 __ pop(r1); |
| 5621 __ Jump(r2); | 5657 __ Jump(r2); |
| 5622 } | 5658 } |
| 5623 | 5659 |
| 5624 | 5660 |
| 5625 #undef __ | 5661 #undef __ |
| 5626 | 5662 |
| 5627 } } // namespace v8::internal | 5663 } } // namespace v8::internal |
| 5628 | 5664 |
| 5629 #endif // V8_TARGET_ARCH_ARM | 5665 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |