| 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 2416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2427 | 2427 |
| 2428 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 2428 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
| 2429 "TypeRecordingBinaryOpStub_%s_%s_%s", | 2429 "TypeRecordingBinaryOpStub_%s_%s_%s", |
| 2430 op_name, | 2430 op_name, |
| 2431 overwrite_name, | 2431 overwrite_name, |
| 2432 TRBinaryOpIC::GetName(operands_type_)); | 2432 TRBinaryOpIC::GetName(operands_type_)); |
| 2433 return name_; | 2433 return name_; |
| 2434 } | 2434 } |
| 2435 | 2435 |
| 2436 | 2436 |
| 2437 void TypeRecordingBinaryOpStub::GenerateOptimisticSmiOperation( | 2437 void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation( |
| 2438 MacroAssembler* masm) { | 2438 MacroAssembler* masm) { |
| 2439 Register left = r1; | 2439 Register left = r1; |
| 2440 Register right = r0; | 2440 Register right = r0; |
| 2441 Register scratch1 = r7; |
| 2442 Register scratch2 = r9; |
| 2441 | 2443 |
| 2442 ASSERT(right.is(r0)); | 2444 ASSERT(right.is(r0)); |
| 2445 STATIC_ASSERT(kSmiTag == 0); |
| 2443 | 2446 |
| 2447 Label not_smi_result; |
| 2444 switch (op_) { | 2448 switch (op_) { |
| 2445 case Token::ADD: | 2449 case Token::ADD: |
| 2446 __ add(right, left, Operand(right), SetCC); // Add optimistically. | 2450 __ add(right, left, Operand(right), SetCC); // Add optimistically. |
| 2447 __ Ret(vc); | 2451 __ Ret(vc); |
| 2448 __ sub(right, right, Operand(left)); // Revert optimistic add. | 2452 __ sub(right, right, Operand(left)); // Revert optimistic add. |
| 2449 break; | 2453 break; |
| 2450 case Token::SUB: | 2454 case Token::SUB: |
| 2451 __ sub(right, left, Operand(right), SetCC); // Subtract optimistically. | 2455 __ sub(right, left, Operand(right), SetCC); // Subtract optimistically. |
| 2452 __ Ret(vc); | 2456 __ Ret(vc); |
| 2453 __ sub(right, left, Operand(right)); // Revert optimistic subtract. | 2457 __ sub(right, left, Operand(right)); // Revert optimistic subtract. |
| 2454 break; | 2458 break; |
| 2459 case Token::MUL: |
| 2460 // Remove tag from one of the operands. This way the multiplication result |
| 2461 // will be a smi if it fits the smi range. |
| 2462 __ SmiUntag(ip, right); |
| 2463 // Do multiplication |
| 2464 // scratch1 = lower 32 bits of ip * left. |
| 2465 // scratch2 = higher 32 bits of ip * left. |
| 2466 __ smull(scratch1, scratch2, left, ip); |
| 2467 // Check for overflowing the smi range - no overflow if higher 33 bits of |
| 2468 // the result are identical. |
| 2469 __ mov(ip, Operand(scratch1, ASR, 31)); |
| 2470 __ cmp(ip, Operand(scratch2)); |
| 2471 __ b(ne, ¬_smi_result); |
| 2472 // Go slow on zero result to handle -0. |
| 2473 __ tst(scratch1, Operand(scratch1)); |
| 2474 __ mov(right, Operand(scratch1), LeaveCC, ne); |
| 2475 __ Ret(ne); |
| 2476 // We need -0 if we were multiplying a negative number with 0 to get 0. |
| 2477 // We know one of them was zero. |
| 2478 __ add(scratch2, right, Operand(left), SetCC); |
| 2479 __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl); |
| 2480 __ Ret(pl); // Return smi 0 if the non-zero one was positive. |
| 2481 // We fall through here if we multiplied a negative number with 0, because |
| 2482 // that would mean we should produce -0. |
| 2483 break; |
| 2455 default: | 2484 default: |
| 2456 UNREACHABLE(); | 2485 UNREACHABLE(); |
| 2457 } | 2486 } |
| 2487 __ bind(¬_smi_result); |
| 2458 } | 2488 } |
| 2459 | 2489 |
| 2460 | 2490 |
| 2461 void TypeRecordingBinaryOpStub::GenerateVFPOperation( | 2491 void TypeRecordingBinaryOpStub::GenerateVFPOperation( |
| 2462 MacroAssembler* masm) { | 2492 MacroAssembler* masm) { |
| 2463 switch (op_) { | 2493 switch (op_) { |
| 2464 case Token::ADD: | 2494 case Token::ADD: |
| 2465 __ vadd(d5, d6, d7); | 2495 __ vadd(d5, d6, d7); |
| 2466 break; | 2496 break; |
| 2467 case Token::SUB: | 2497 case Token::SUB: |
| 2468 __ vsub(d5, d6, d7); | 2498 __ vsub(d5, d6, d7); |
| 2469 break; | 2499 break; |
| 2500 case Token::MUL: |
| 2501 __ vmul(d5, d6, d7); |
| 2502 break; |
| 2470 default: | 2503 default: |
| 2471 UNREACHABLE(); | 2504 UNREACHABLE(); |
| 2472 } | 2505 } |
| 2473 } | 2506 } |
| 2474 | 2507 |
| 2475 | 2508 |
| 2476 // Generate the smi code. If the operation on smis are successful this return is | 2509 // Generate the smi code. If the operation on smis are successful this return is |
| 2477 // generated. If the result is not a smi and heap number allocation is not | 2510 // generated. If the result is not a smi and heap number allocation is not |
| 2478 // requested the code falls through. If number allocation is requested but a | 2511 // requested the code falls through. If number allocation is requested but a |
| 2479 // heap number cannot be allocated the code jumps to the lable gc_required. | 2512 // heap number cannot be allocated the code jumps to the lable gc_required. |
| 2480 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, | 2513 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, |
| 2481 Label* gc_required, | 2514 Label* gc_required, |
| 2482 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { | 2515 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { |
| 2483 Label not_smis; | 2516 Label not_smis; |
| 2484 | 2517 |
| 2485 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2518 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
| 2486 | 2519 |
| 2487 Register left = r1; | 2520 Register left = r1; |
| 2488 Register right = r0; | 2521 Register right = r0; |
| 2489 Register scratch1 = r7; | 2522 Register scratch1 = r7; |
| 2490 Register scratch2 = r9; | 2523 Register scratch2 = r9; |
| 2491 | 2524 |
| 2492 // Perform combined smi check on both operands. | 2525 // Perform combined smi check on both operands. |
| 2493 __ orr(scratch1, left, Operand(right)); | 2526 __ orr(scratch1, left, Operand(right)); |
| 2494 STATIC_ASSERT(kSmiTag == 0); | 2527 STATIC_ASSERT(kSmiTag == 0); |
| 2495 __ tst(scratch1, Operand(kSmiTagMask)); | 2528 __ tst(scratch1, Operand(kSmiTagMask)); |
| 2496 __ b(ne, ¬_smis); | 2529 __ b(ne, ¬_smis); |
| 2497 | 2530 |
| 2498 GenerateOptimisticSmiOperation(masm); | 2531 GenerateSmiSmiOperation(masm); |
| 2499 | 2532 |
| 2500 // If heap number results are possible generate the result in an allocated | 2533 // If heap number results are possible generate the result in an allocated |
| 2501 // heap number. | 2534 // heap number. |
| 2502 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { | 2535 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { |
| 2503 FloatingPointHelper::Destination destination = | 2536 FloatingPointHelper::Destination destination = |
| 2504 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? | 2537 CpuFeatures::IsSupported(VFP3) && Token::MOD != op_ ? |
| 2505 FloatingPointHelper::kVFPRegisters : | 2538 FloatingPointHelper::kVFPRegisters : |
| 2506 FloatingPointHelper::kCoreRegisters; | 2539 FloatingPointHelper::kCoreRegisters; |
| 2507 | 2540 |
| 2508 Register heap_number_map = r6; | 2541 Register heap_number_map = r6; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2556 __ pop(pc); | 2589 __ pop(pc); |
| 2557 } | 2590 } |
| 2558 } | 2591 } |
| 2559 __ bind(¬_smis); | 2592 __ bind(¬_smis); |
| 2560 } | 2593 } |
| 2561 | 2594 |
| 2562 | 2595 |
| 2563 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 2596 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
| 2564 Label not_smis, call_runtime; | 2597 Label not_smis, call_runtime; |
| 2565 | 2598 |
| 2566 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2599 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
| 2567 | 2600 |
| 2568 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || | 2601 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || |
| 2569 result_type_ == TRBinaryOpIC::SMI) { | 2602 result_type_ == TRBinaryOpIC::SMI) { |
| 2570 // Only allow smi results. | 2603 // Only allow smi results. |
| 2571 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); | 2604 GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS); |
| 2572 } else { | 2605 } else { |
| 2573 // Allow heap number result and don't make a transition if a heap number | 2606 // Allow heap number result and don't make a transition if a heap number |
| 2574 // cannot be allocated. | 2607 // cannot be allocated. |
| 2575 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2608 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
| 2576 } | 2609 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2588 ASSERT(operands_type_ == TRBinaryOpIC::STRING); | 2621 ASSERT(operands_type_ == TRBinaryOpIC::STRING); |
| 2589 ASSERT(op_ == Token::ADD); | 2622 ASSERT(op_ == Token::ADD); |
| 2590 // Try to add arguments as strings, otherwise, transition to the generic | 2623 // Try to add arguments as strings, otherwise, transition to the generic |
| 2591 // TRBinaryOpIC type. | 2624 // TRBinaryOpIC type. |
| 2592 GenerateAddStrings(masm); | 2625 GenerateAddStrings(masm); |
| 2593 GenerateTypeTransition(masm); | 2626 GenerateTypeTransition(masm); |
| 2594 } | 2627 } |
| 2595 | 2628 |
| 2596 | 2629 |
| 2597 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 2630 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
| 2598 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2631 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::SUB); |
| 2599 | 2632 |
| 2600 ASSERT(operands_type_ == TRBinaryOpIC::INT32); | 2633 ASSERT(operands_type_ == TRBinaryOpIC::INT32); |
| 2601 | 2634 |
| 2602 GenerateTypeTransition(masm); | 2635 GenerateTypeTransition(masm); |
| 2603 } | 2636 } |
| 2604 | 2637 |
| 2605 | 2638 |
| 2606 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { | 2639 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { |
| 2607 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2640 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
| 2608 | 2641 |
| 2609 Register scratch1 = r7; | 2642 Register scratch1 = r7; |
| 2610 Register scratch2 = r9; | 2643 Register scratch2 = r9; |
| 2611 | 2644 |
| 2612 Label not_number, call_runtime; | 2645 Label not_number, call_runtime; |
| 2613 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); | 2646 ASSERT(operands_type_ == TRBinaryOpIC::HEAP_NUMBER); |
| 2614 | 2647 |
| 2615 Register heap_number_map = r6; | 2648 Register heap_number_map = r6; |
| 2616 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2649 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 2617 | 2650 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2677 | 2710 |
| 2678 __ bind(¬_number); | 2711 __ bind(¬_number); |
| 2679 GenerateTypeTransition(masm); | 2712 GenerateTypeTransition(masm); |
| 2680 | 2713 |
| 2681 __ bind(&call_runtime); | 2714 __ bind(&call_runtime); |
| 2682 GenerateCallRuntime(masm); | 2715 GenerateCallRuntime(masm); |
| 2683 } | 2716 } |
| 2684 | 2717 |
| 2685 | 2718 |
| 2686 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { | 2719 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
| 2687 ASSERT(op_ == Token::ADD || op_ == Token::SUB); | 2720 ASSERT(op_ == Token::ADD || op_ == Token::SUB || op_ == Token::MUL); |
| 2688 | 2721 |
| 2689 Label call_runtime; | 2722 Label call_runtime; |
| 2690 | 2723 |
| 2691 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); | 2724 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); |
| 2692 | 2725 |
| 2693 // If all else fails, use the runtime system to get the correct | 2726 // If all else fails, use the runtime system to get the correct |
| 2694 // result. | 2727 // result. |
| 2695 __ bind(&call_runtime); | 2728 __ bind(&call_runtime); |
| 2696 | 2729 |
| 2697 // Try to add strings before calling runtime. | 2730 // Try to add strings before calling runtime. |
| (...skipping 2962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5660 __ pop(r1); | 5693 __ pop(r1); |
| 5661 __ Jump(r2); | 5694 __ Jump(r2); |
| 5662 } | 5695 } |
| 5663 | 5696 |
| 5664 | 5697 |
| 5665 #undef __ | 5698 #undef __ |
| 5666 | 5699 |
| 5667 } } // namespace v8::internal | 5700 } } // namespace v8::internal |
| 5668 | 5701 |
| 5669 #endif // V8_TARGET_ARCH_ARM | 5702 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |