| 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 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 if (save_doubles_ == kSaveFPRegs) { | 295 if (save_doubles_ == kSaveFPRegs) { |
| 296 CpuFeatures::Scope scope(SSE2); | 296 CpuFeatures::Scope scope(SSE2); |
| 297 __ subq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); | 297 __ subq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); |
| 298 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { | 298 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { |
| 299 XMMRegister reg = XMMRegister::from_code(i); | 299 XMMRegister reg = XMMRegister::from_code(i); |
| 300 __ movsd(Operand(rsp, i * kDoubleSize), reg); | 300 __ movsd(Operand(rsp, i * kDoubleSize), reg); |
| 301 } | 301 } |
| 302 } | 302 } |
| 303 const int argument_count = 0; | 303 const int argument_count = 0; |
| 304 __ PrepareCallCFunction(argument_count); | 304 __ PrepareCallCFunction(argument_count); |
| 305 ExternalReference store_buffer_overflow = | 305 __ CallCFunction(ExteranalReference::store_buffer_overflow_function(), |
| 306 ExternalReference(Runtime::FunctionForId(Runtime::kStoreBufferOverflow)); | 306 argument_count); |
| 307 __ CallCFunction(store_buffer_overflow, argument_count); | |
| 308 if (save_doubles_ == kSaveFPRegs) { | 307 if (save_doubles_ == kSaveFPRegs) { |
| 309 CpuFeatures::Scope scope(SSE2); | 308 CpuFeatures::Scope scope(SSE2); |
| 310 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { | 309 for (int i = 0; i < XMMRegister::kNumRegisters; i++) { |
| 311 XMMRegister reg = XMMRegister::from_code(i); | 310 XMMRegister reg = XMMRegister::from_code(i); |
| 312 __ movsd(reg, Operand(rsp, i * kDoubleSize)); | 311 __ movsd(reg, Operand(rsp, i * kDoubleSize)); |
| 313 } | 312 } |
| 314 __ addq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); | 313 __ addq(rsp, Immediate(kDoubleSize * XMMRegister::kNumRegisters)); |
| 315 } | 314 } |
| 316 for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { | 315 for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) { |
| 317 __ pop(saved_regs[i]); | 316 __ pop(saved_regs[i]); |
| 318 } | 317 } |
| 319 __ ret(0); | 318 __ ret(0); |
| 320 } | 319 } |
| 321 | 320 |
| 322 | 321 |
| 323 const char* GenericBinaryOpStub::GetName() { | 322 const char* GenericBinaryOpStub::GetName() { |
| 324 if (name_ != NULL) return name_; | 323 if (name_ != NULL) return name_; |
| 325 const int kMaxNameLength = 100; | 324 const int kMaxNameLength = 100; |
| 326 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength); | 325 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
| 326 kMaxNameLength); |
| 327 if (name_ == NULL) return "OOM"; | 327 if (name_ == NULL) return "OOM"; |
| 328 const char* op_name = Token::Name(op_); | 328 const char* op_name = Token::Name(op_); |
| 329 const char* overwrite_name; | 329 const char* overwrite_name; |
| 330 switch (mode_) { | 330 switch (mode_) { |
| 331 case NO_OVERWRITE: overwrite_name = "Alloc"; break; | 331 case NO_OVERWRITE: overwrite_name = "Alloc"; break; |
| 332 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; | 332 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; |
| 333 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; | 333 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; |
| 334 default: overwrite_name = "UnknownOverwrite"; break; | 334 default: overwrite_name = "UnknownOverwrite"; break; |
| 335 } | 335 } |
| 336 | 336 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 } | 390 } |
| 391 } else { | 391 } else { |
| 392 // Order of moves is not important. | 392 // Order of moves is not important. |
| 393 __ movq(left_arg, left); | 393 __ movq(left_arg, left); |
| 394 __ movq(right_arg, right); | 394 __ movq(right_arg, right); |
| 395 } | 395 } |
| 396 } | 396 } |
| 397 | 397 |
| 398 // Update flags to indicate that arguments are in registers. | 398 // Update flags to indicate that arguments are in registers. |
| 399 SetArgsInRegisters(); | 399 SetArgsInRegisters(); |
| 400 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); | 400 __ IncrementCounter(COUNTERS->generic_binary_stub_calls_regs(), 1); |
| 401 } | 401 } |
| 402 | 402 |
| 403 // Call the stub. | 403 // Call the stub. |
| 404 __ CallStub(this); | 404 __ CallStub(this); |
| 405 } | 405 } |
| 406 | 406 |
| 407 | 407 |
| 408 void GenericBinaryOpStub::GenerateCall( | 408 void GenericBinaryOpStub::GenerateCall( |
| 409 MacroAssembler* masm, | 409 MacroAssembler* masm, |
| 410 Register left, | 410 Register left, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 426 // For non-commutative operations, left and right_arg might be | 426 // For non-commutative operations, left and right_arg might be |
| 427 // the same register. Therefore, the order of the moves is | 427 // the same register. Therefore, the order of the moves is |
| 428 // important here in order to not overwrite left before moving | 428 // important here in order to not overwrite left before moving |
| 429 // it to left_arg. | 429 // it to left_arg. |
| 430 __ movq(left_arg, left); | 430 __ movq(left_arg, left); |
| 431 __ Move(right_arg, right); | 431 __ Move(right_arg, right); |
| 432 } | 432 } |
| 433 | 433 |
| 434 // Update flags to indicate that arguments are in registers. | 434 // Update flags to indicate that arguments are in registers. |
| 435 SetArgsInRegisters(); | 435 SetArgsInRegisters(); |
| 436 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); | 436 __ IncrementCounter(COUNTERS->generic_binary_stub_calls_regs(), 1); |
| 437 } | 437 } |
| 438 | 438 |
| 439 // Call the stub. | 439 // Call the stub. |
| 440 __ CallStub(this); | 440 __ CallStub(this); |
| 441 } | 441 } |
| 442 | 442 |
| 443 | 443 |
| 444 void GenericBinaryOpStub::GenerateCall( | 444 void GenericBinaryOpStub::GenerateCall( |
| 445 MacroAssembler* masm, | 445 MacroAssembler* masm, |
| 446 Smi* left, | 446 Smi* left, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 461 } else { | 461 } else { |
| 462 // For non-commutative operations, right and left_arg might be | 462 // For non-commutative operations, right and left_arg might be |
| 463 // the same register. Therefore, the order of the moves is | 463 // the same register. Therefore, the order of the moves is |
| 464 // important here in order to not overwrite right before moving | 464 // important here in order to not overwrite right before moving |
| 465 // it to right_arg. | 465 // it to right_arg. |
| 466 __ movq(right_arg, right); | 466 __ movq(right_arg, right); |
| 467 __ Move(left_arg, left); | 467 __ Move(left_arg, left); |
| 468 } | 468 } |
| 469 // Update flags to indicate that arguments are in registers. | 469 // Update flags to indicate that arguments are in registers. |
| 470 SetArgsInRegisters(); | 470 SetArgsInRegisters(); |
| 471 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); | 471 __ IncrementCounter(COUNTERS->generic_binary_stub_calls_regs(), 1); |
| 472 } | 472 } |
| 473 | 473 |
| 474 // Call the stub. | 474 // Call the stub. |
| 475 __ CallStub(this); | 475 __ CallStub(this); |
| 476 } | 476 } |
| 477 | 477 |
| 478 | 478 |
| 479 class FloatingPointHelper : public AllStatic { | 479 class FloatingPointHelper : public AllStatic { |
| 480 public: | 480 public: |
| 481 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. | 481 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1104 break; | 1104 break; |
| 1105 default: | 1105 default: |
| 1106 UNREACHABLE(); | 1106 UNREACHABLE(); |
| 1107 } | 1107 } |
| 1108 } | 1108 } |
| 1109 | 1109 |
| 1110 | 1110 |
| 1111 const char* TypeRecordingBinaryOpStub::GetName() { | 1111 const char* TypeRecordingBinaryOpStub::GetName() { |
| 1112 if (name_ != NULL) return name_; | 1112 if (name_ != NULL) return name_; |
| 1113 const int kMaxNameLength = 100; | 1113 const int kMaxNameLength = 100; |
| 1114 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength); | 1114 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
| 1115 kMaxNameLength); |
| 1115 if (name_ == NULL) return "OOM"; | 1116 if (name_ == NULL) return "OOM"; |
| 1116 const char* op_name = Token::Name(op_); | 1117 const char* op_name = Token::Name(op_); |
| 1117 const char* overwrite_name; | 1118 const char* overwrite_name; |
| 1118 switch (mode_) { | 1119 switch (mode_) { |
| 1119 case NO_OVERWRITE: overwrite_name = "Alloc"; break; | 1120 case NO_OVERWRITE: overwrite_name = "Alloc"; break; |
| 1120 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; | 1121 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; |
| 1121 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; | 1122 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; |
| 1122 default: overwrite_name = "UnknownOverwrite"; break; | 1123 default: overwrite_name = "UnknownOverwrite"; break; |
| 1123 } | 1124 } |
| 1124 | 1125 |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 __ xorl(rdx, rbx); | 1615 __ xorl(rdx, rbx); |
| 1615 __ movl(rcx, rdx); | 1616 __ movl(rcx, rdx); |
| 1616 __ movl(rax, rdx); | 1617 __ movl(rax, rdx); |
| 1617 __ movl(rdi, rdx); | 1618 __ movl(rdi, rdx); |
| 1618 __ sarl(rdx, Immediate(8)); | 1619 __ sarl(rdx, Immediate(8)); |
| 1619 __ sarl(rcx, Immediate(16)); | 1620 __ sarl(rcx, Immediate(16)); |
| 1620 __ sarl(rax, Immediate(24)); | 1621 __ sarl(rax, Immediate(24)); |
| 1621 __ xorl(rcx, rdx); | 1622 __ xorl(rcx, rdx); |
| 1622 __ xorl(rax, rdi); | 1623 __ xorl(rax, rdi); |
| 1623 __ xorl(rcx, rax); | 1624 __ xorl(rcx, rax); |
| 1624 ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize)); | 1625 ASSERT(IsPowerOf2(TranscendentalCache::SubCache::kCacheSize)); |
| 1625 __ andl(rcx, Immediate(TranscendentalCache::kCacheSize - 1)); | 1626 __ andl(rcx, Immediate(TranscendentalCache::SubCache::kCacheSize - 1)); |
| 1626 | 1627 |
| 1627 // ST[0] == double value. | 1628 // ST[0] == double value. |
| 1628 // rbx = bits of double value. | 1629 // rbx = bits of double value. |
| 1629 // rcx = TranscendentalCache::hash(double value). | 1630 // rcx = TranscendentalCache::hash(double value). |
| 1630 __ movq(rax, ExternalReference::transcendental_cache_array_address()); | 1631 __ movq(rax, ExternalReference::transcendental_cache_array_address()); |
| 1631 // rax points to cache array. | 1632 // rax points to cache array. |
| 1632 __ movq(rax, Operand(rax, type_ * sizeof(TranscendentalCache::caches_[0]))); | 1633 __ movq(rax, Operand(rax, type_ * sizeof( |
| 1634 Isolate::Current()->transcendental_cache()->caches_[0]))); |
| 1633 // rax points to the cache for the type type_. | 1635 // rax points to the cache for the type type_. |
| 1634 // If NULL, the cache hasn't been initialized yet, so go through runtime. | 1636 // If NULL, the cache hasn't been initialized yet, so go through runtime. |
| 1635 __ testq(rax, rax); | 1637 __ testq(rax, rax); |
| 1636 __ j(zero, &runtime_call_clear_stack); // Only clears stack if TAGGED. | 1638 __ j(zero, &runtime_call_clear_stack); // Only clears stack if TAGGED. |
| 1637 #ifdef DEBUG | 1639 #ifdef DEBUG |
| 1638 // Check that the layout of cache elements match expectations. | 1640 // Check that the layout of cache elements match expectations. |
| 1639 { // NOLINT - doesn't like a single brace on a line. | 1641 { // NOLINT - doesn't like a single brace on a line. |
| 1640 TranscendentalCache::Element test_elem[2]; | 1642 TranscendentalCache::SubCache::Element test_elem[2]; |
| 1641 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); | 1643 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); |
| 1642 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); | 1644 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); |
| 1643 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); | 1645 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); |
| 1644 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); | 1646 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); |
| 1645 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); | 1647 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); |
| 1646 // Two uint_32's and a pointer per element. | 1648 // Two uint_32's and a pointer per element. |
| 1647 CHECK_EQ(16, static_cast<int>(elem2_start - elem_start)); | 1649 CHECK_EQ(16, static_cast<int>(elem2_start - elem_start)); |
| 1648 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start)); | 1650 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start)); |
| 1649 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start)); | 1651 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start)); |
| 1650 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start)); | 1652 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start)); |
| (...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2624 // r11: code | 2626 // r11: code |
| 2625 // Load used arguments before starting to push arguments for call to native | 2627 // Load used arguments before starting to push arguments for call to native |
| 2626 // RegExp code to avoid handling changing stack height. | 2628 // RegExp code to avoid handling changing stack height. |
| 2627 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); | 2629 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); |
| 2628 | 2630 |
| 2629 // rdi: subject string | 2631 // rdi: subject string |
| 2630 // rbx: previous index | 2632 // rbx: previous index |
| 2631 // rcx: encoding of subject string (1 if ascii 0 if two_byte); | 2633 // rcx: encoding of subject string (1 if ascii 0 if two_byte); |
| 2632 // r11: code | 2634 // r11: code |
| 2633 // All checks done. Now push arguments for native regexp code. | 2635 // All checks done. Now push arguments for native regexp code. |
| 2634 __ IncrementCounter(&Counters::regexp_entry_native, 1); | 2636 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1); |
| 2635 | 2637 |
| 2636 static const int kRegExpExecuteArguments = 7; | 2638 // Isolates: note we add an additional parameter here (isolate pointer). |
| 2639 static const int kRegExpExecuteArguments = 8; |
| 2637 int argument_slots_on_stack = | 2640 int argument_slots_on_stack = |
| 2638 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); | 2641 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); |
| 2639 __ EnterApiExitFrame(argument_slots_on_stack); | 2642 __ EnterApiExitFrame(argument_slots_on_stack); |
| 2640 | 2643 |
| 2644 // Argument 8: Pass current isolate address. |
| 2645 // __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), |
| 2646 // Immediate(ExternalReference::isolate_address())); |
| 2647 __ movq(kScratchRegister, ExternalReference::isolate_address()); |
| 2648 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), |
| 2649 kScratchRegister); |
| 2650 |
| 2641 // Argument 7: Indicate that this is a direct call from JavaScript. | 2651 // Argument 7: Indicate that this is a direct call from JavaScript. |
| 2642 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), | 2652 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), |
| 2643 Immediate(1)); | 2653 Immediate(1)); |
| 2644 | 2654 |
| 2645 // Argument 6: Start (high end) of backtracking stack memory area. | 2655 // Argument 6: Start (high end) of backtracking stack memory area. |
| 2646 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); | 2656 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); |
| 2647 __ movq(r9, Operand(kScratchRegister, 0)); | 2657 __ movq(r9, Operand(kScratchRegister, 0)); |
| 2648 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); | 2658 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); |
| 2649 __ addq(r9, Operand(kScratchRegister, 0)); | 2659 __ addq(r9, Operand(kScratchRegister, 0)); |
| 2650 // Argument 6 passed in r9 on Linux and on the stack on Windows. | 2660 // Argument 6 passed in r9 on Linux and on the stack on Windows. |
| 2651 #ifdef _WIN64 | 2661 #ifdef _WIN64 |
| 2652 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), r9); | 2662 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r9); |
| 2653 #endif | 2663 #endif |
| 2654 | 2664 |
| 2655 // Argument 5: static offsets vector buffer. | 2665 // Argument 5: static offsets vector buffer. |
| 2656 __ movq(r8, ExternalReference::address_of_static_offsets_vector()); | 2666 __ movq(r8, ExternalReference::address_of_static_offsets_vector()); |
| 2657 // Argument 5 passed in r8 on Linux and on the stack on Windows. | 2667 // Argument 5 passed in r8 on Linux and on the stack on Windows. |
| 2658 #ifdef _WIN64 | 2668 #ifdef _WIN64 |
| 2659 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r8); | 2669 __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kPointerSize), r8); |
| 2660 #endif | 2670 #endif |
| 2661 | 2671 |
| 2662 // First four arguments are passed in registers on both Linux and Windows. | 2672 // First four arguments are passed in registers on both Linux and Windows. |
| 2663 #ifdef _WIN64 | 2673 #ifdef _WIN64 |
| 2664 Register arg4 = r9; | 2674 Register arg4 = r9; |
| 2665 Register arg3 = r8; | 2675 Register arg3 = r8; |
| 2666 Register arg2 = rdx; | 2676 Register arg2 = rdx; |
| 2667 Register arg1 = rcx; | 2677 Register arg1 = rcx; |
| 2668 #else | 2678 #else |
| 2669 Register arg4 = rcx; | 2679 Register arg4 = rcx; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2786 | 2796 |
| 2787 // Return last match info. | 2797 // Return last match info. |
| 2788 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 2798 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); |
| 2789 __ ret(4 * kPointerSize); | 2799 __ ret(4 * kPointerSize); |
| 2790 | 2800 |
| 2791 __ bind(&exception); | 2801 __ bind(&exception); |
| 2792 // Result must now be exception. If there is no pending exception already a | 2802 // Result must now be exception. If there is no pending exception already a |
| 2793 // stack overflow (on the backtrack stack) was detected in RegExp code but | 2803 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 2794 // haven't created the exception yet. Handle that in the runtime system. | 2804 // haven't created the exception yet. Handle that in the runtime system. |
| 2795 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 2805 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 2796 ExternalReference pending_exception_address(Top::k_pending_exception_address); | 2806 ExternalReference pending_exception_address( |
| 2807 Isolate::k_pending_exception_address); |
| 2797 __ movq(rbx, pending_exception_address); | 2808 __ movq(rbx, pending_exception_address); |
| 2798 __ movq(rax, Operand(rbx, 0)); | 2809 __ movq(rax, Operand(rbx, 0)); |
| 2799 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); | 2810 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
| 2800 __ cmpq(rax, rdx); | 2811 __ cmpq(rax, rdx); |
| 2801 __ j(equal, &runtime); | 2812 __ j(equal, &runtime); |
| 2802 __ movq(Operand(rbx, 0), rdx); | 2813 __ movq(Operand(rbx, 0), rdx); |
| 2803 | 2814 |
| 2804 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); | 2815 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
| 2805 NearLabel termination_exception; | 2816 NearLabel termination_exception; |
| 2806 __ j(equal, &termination_exception); | 2817 __ j(equal, &termination_exception); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2923 __ subq(mask, Immediate(1)); // Make mask. | 2934 __ subq(mask, Immediate(1)); // Make mask. |
| 2924 | 2935 |
| 2925 // Calculate the entry in the number string cache. The hash value in the | 2936 // Calculate the entry in the number string cache. The hash value in the |
| 2926 // number string cache for smis is just the smi value, and the hash for | 2937 // number string cache for smis is just the smi value, and the hash for |
| 2927 // doubles is the xor of the upper and lower words. See | 2938 // doubles is the xor of the upper and lower words. See |
| 2928 // Heap::GetNumberStringCache. | 2939 // Heap::GetNumberStringCache. |
| 2929 Label is_smi; | 2940 Label is_smi; |
| 2930 Label load_result_from_cache; | 2941 Label load_result_from_cache; |
| 2931 if (!object_is_smi) { | 2942 if (!object_is_smi) { |
| 2932 __ JumpIfSmi(object, &is_smi); | 2943 __ JumpIfSmi(object, &is_smi); |
| 2933 __ CheckMap(object, Factory::heap_number_map(), not_found, true); | 2944 __ CheckMap(object, FACTORY->heap_number_map(), not_found, true); |
| 2934 | 2945 |
| 2935 STATIC_ASSERT(8 == kDoubleSize); | 2946 STATIC_ASSERT(8 == kDoubleSize); |
| 2936 __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); | 2947 __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
| 2937 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset)); | 2948 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
| 2938 GenerateConvertHashCodeToIndex(masm, scratch, mask); | 2949 GenerateConvertHashCodeToIndex(masm, scratch, mask); |
| 2939 | 2950 |
| 2940 Register index = scratch; | 2951 Register index = scratch; |
| 2941 Register probe = mask; | 2952 Register probe = mask; |
| 2942 __ movq(probe, | 2953 __ movq(probe, |
| 2943 FieldOperand(number_string_cache, | 2954 FieldOperand(number_string_cache, |
| 2944 index, | 2955 index, |
| 2945 times_1, | 2956 times_1, |
| 2946 FixedArray::kHeaderSize)); | 2957 FixedArray::kHeaderSize)); |
| 2947 __ JumpIfSmi(probe, not_found); | 2958 __ JumpIfSmi(probe, not_found); |
| 2948 ASSERT(CpuFeatures::IsSupported(SSE2)); | 2959 ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2)); |
| 2949 CpuFeatures::Scope fscope(SSE2); | 2960 CpuFeatures::Scope fscope(SSE2); |
| 2950 __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); | 2961 __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
| 2951 __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); | 2962 __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); |
| 2952 __ ucomisd(xmm0, xmm1); | 2963 __ ucomisd(xmm0, xmm1); |
| 2953 __ j(parity_even, not_found); // Bail out if NaN is involved. | 2964 __ j(parity_even, not_found); // Bail out if NaN is involved. |
| 2954 __ j(not_equal, not_found); // The cache did not contain this value. | 2965 __ j(not_equal, not_found); // The cache did not contain this value. |
| 2955 __ jmp(&load_result_from_cache); | 2966 __ jmp(&load_result_from_cache); |
| 2956 } | 2967 } |
| 2957 | 2968 |
| 2958 __ bind(&is_smi); | 2969 __ bind(&is_smi); |
| 2959 __ SmiToInteger32(scratch, object); | 2970 __ SmiToInteger32(scratch, object); |
| 2960 GenerateConvertHashCodeToIndex(masm, scratch, mask); | 2971 GenerateConvertHashCodeToIndex(masm, scratch, mask); |
| 2961 | 2972 |
| 2962 Register index = scratch; | 2973 Register index = scratch; |
| 2963 // Check if the entry is the smi we are looking for. | 2974 // Check if the entry is the smi we are looking for. |
| 2964 __ cmpq(object, | 2975 __ cmpq(object, |
| 2965 FieldOperand(number_string_cache, | 2976 FieldOperand(number_string_cache, |
| 2966 index, | 2977 index, |
| 2967 times_1, | 2978 times_1, |
| 2968 FixedArray::kHeaderSize)); | 2979 FixedArray::kHeaderSize)); |
| 2969 __ j(not_equal, not_found); | 2980 __ j(not_equal, not_found); |
| 2970 | 2981 |
| 2971 // Get the result from the cache. | 2982 // Get the result from the cache. |
| 2972 __ bind(&load_result_from_cache); | 2983 __ bind(&load_result_from_cache); |
| 2973 __ movq(result, | 2984 __ movq(result, |
| 2974 FieldOperand(number_string_cache, | 2985 FieldOperand(number_string_cache, |
| 2975 index, | 2986 index, |
| 2976 times_1, | 2987 times_1, |
| 2977 FixedArray::kHeaderSize + kPointerSize)); | 2988 FixedArray::kHeaderSize + kPointerSize)); |
| 2978 __ IncrementCounter(&Counters::number_to_string_native, 1); | 2989 __ IncrementCounter(COUNTERS->number_to_string_native(), 1); |
| 2979 } | 2990 } |
| 2980 | 2991 |
| 2981 | 2992 |
| 2982 void NumberToStringStub::GenerateConvertHashCodeToIndex(MacroAssembler* masm, | 2993 void NumberToStringStub::GenerateConvertHashCodeToIndex(MacroAssembler* masm, |
| 2983 Register hash, | 2994 Register hash, |
| 2984 Register mask) { | 2995 Register mask) { |
| 2985 __ and_(hash, mask); | 2996 __ and_(hash, mask); |
| 2986 // Each entry in string cache consists of two pointer sized fields, | 2997 // Each entry in string cache consists of two pointer sized fields, |
| 2987 // but times_twice_pointer_size (multiplication by 16) scale factor | 2998 // but times_twice_pointer_size (multiplication by 16) scale factor |
| 2988 // is not supported by addrmode on x64 platform. | 2999 // is not supported by addrmode on x64 platform. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3053 // Check for undefined. undefined OP undefined is false even though | 3064 // Check for undefined. undefined OP undefined is false even though |
| 3054 // undefined == undefined. | 3065 // undefined == undefined. |
| 3055 NearLabel check_for_nan; | 3066 NearLabel check_for_nan; |
| 3056 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 3067 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 3057 __ j(not_equal, &check_for_nan); | 3068 __ j(not_equal, &check_for_nan); |
| 3058 __ Set(rax, NegativeComparisonResult(cc_)); | 3069 __ Set(rax, NegativeComparisonResult(cc_)); |
| 3059 __ ret(0); | 3070 __ ret(0); |
| 3060 __ bind(&check_for_nan); | 3071 __ bind(&check_for_nan); |
| 3061 } | 3072 } |
| 3062 | 3073 |
| 3063 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 3074 // Test for NaN. Sadly, we can't just compare to FACTORY->nan_value(), |
| 3064 // so we do the second best thing - test it ourselves. | 3075 // so we do the second best thing - test it ourselves. |
| 3065 // Note: if cc_ != equal, never_nan_nan_ is not used. | 3076 // Note: if cc_ != equal, never_nan_nan_ is not used. |
| 3066 // We cannot set rax to EQUAL until just before return because | 3077 // We cannot set rax to EQUAL until just before return because |
| 3067 // rax must be unchanged on jump to not_identical. | 3078 // rax must be unchanged on jump to not_identical. |
| 3068 | 3079 |
| 3069 if (never_nan_nan_ && (cc_ == equal)) { | 3080 if (never_nan_nan_ && (cc_ == equal)) { |
| 3070 __ Set(rax, EQUAL); | 3081 __ Set(rax, EQUAL); |
| 3071 __ ret(0); | 3082 __ ret(0); |
| 3072 } else { | 3083 } else { |
| 3073 NearLabel heap_number; | 3084 NearLabel heap_number; |
| 3074 // If it's not a heap number, then return equal for (in)equality operator. | 3085 // If it's not a heap number, then return equal for (in)equality operator. |
| 3075 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 3086 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), |
| 3076 Factory::heap_number_map()); | 3087 FACTORY->heap_number_map()); |
| 3077 __ j(equal, &heap_number); | 3088 __ j(equal, &heap_number); |
| 3078 if (cc_ != equal) { | 3089 if (cc_ != equal) { |
| 3079 // Call runtime on identical JSObjects. Otherwise return equal. | 3090 // Call runtime on identical JSObjects. Otherwise return equal. |
| 3080 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); | 3091 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); |
| 3081 __ j(above_equal, ¬_identical); | 3092 __ j(above_equal, ¬_identical); |
| 3082 } | 3093 } |
| 3083 __ Set(rax, EQUAL); | 3094 __ Set(rax, EQUAL); |
| 3084 __ ret(0); | 3095 __ ret(0); |
| 3085 | 3096 |
| 3086 __ bind(&heap_number); | 3097 __ bind(&heap_number); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3111 // slow-case code. | 3122 // slow-case code. |
| 3112 if (strict_) { | 3123 if (strict_) { |
| 3113 // If either is a Smi (we know that not both are), then they can only | 3124 // If either is a Smi (we know that not both are), then they can only |
| 3114 // be equal if the other is a HeapNumber. If so, use the slow case. | 3125 // be equal if the other is a HeapNumber. If so, use the slow case. |
| 3115 { | 3126 { |
| 3116 Label not_smis; | 3127 Label not_smis; |
| 3117 __ SelectNonSmi(rbx, rax, rdx, ¬_smis); | 3128 __ SelectNonSmi(rbx, rax, rdx, ¬_smis); |
| 3118 | 3129 |
| 3119 // Check if the non-smi operand is a heap number. | 3130 // Check if the non-smi operand is a heap number. |
| 3120 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | 3131 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), |
| 3121 Factory::heap_number_map()); | 3132 FACTORY->heap_number_map()); |
| 3122 // If heap number, handle it in the slow case. | 3133 // If heap number, handle it in the slow case. |
| 3123 __ j(equal, &slow); | 3134 __ j(equal, &slow); |
| 3124 // Return non-equal. ebx (the lower half of rbx) is not zero. | 3135 // Return non-equal. ebx (the lower half of rbx) is not zero. |
| 3125 __ movq(rax, rbx); | 3136 __ movq(rax, rbx); |
| 3126 __ ret(0); | 3137 __ ret(0); |
| 3127 | 3138 |
| 3128 __ bind(¬_smis); | 3139 __ bind(¬_smis); |
| 3129 } | 3140 } |
| 3130 | 3141 |
| 3131 // If either operand is a JSObject or an oddball value, then they are not | 3142 // If either operand is a JSObject or an oddball value, then they are not |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3344 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); | 3355 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); |
| 3345 | 3356 |
| 3346 // Slow-case: Non-function called. | 3357 // Slow-case: Non-function called. |
| 3347 __ bind(&slow); | 3358 __ bind(&slow); |
| 3348 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3359 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 3349 // of the original receiver from the call site). | 3360 // of the original receiver from the call site). |
| 3350 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); | 3361 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); |
| 3351 __ Set(rax, argc_); | 3362 __ Set(rax, argc_); |
| 3352 __ Set(rbx, 0); | 3363 __ Set(rbx, 0); |
| 3353 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 3364 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
| 3354 Handle<Code> adaptor(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 3365 Handle<Code> adaptor(Isolate::Current()->builtins()->builtin( |
| 3366 Builtins::ArgumentsAdaptorTrampoline)); |
| 3355 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3367 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3356 } | 3368 } |
| 3357 | 3369 |
| 3358 | 3370 |
| 3359 bool CEntryStub::NeedsImmovableCode() { | 3371 bool CEntryStub::NeedsImmovableCode() { |
| 3360 return false; | 3372 return false; |
| 3361 } | 3373 } |
| 3362 | 3374 |
| 3363 | 3375 |
| 3364 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 3376 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3417 // Call C function. | 3429 // Call C function. |
| 3418 #ifdef _WIN64 | 3430 #ifdef _WIN64 |
| 3419 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9 | 3431 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9 |
| 3420 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. | 3432 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. |
| 3421 __ movq(StackSpaceOperand(0), r14); // argc. | 3433 __ movq(StackSpaceOperand(0), r14); // argc. |
| 3422 __ movq(StackSpaceOperand(1), r15); // argv. | 3434 __ movq(StackSpaceOperand(1), r15); // argv. |
| 3423 if (result_size_ < 2) { | 3435 if (result_size_ < 2) { |
| 3424 // Pass a pointer to the Arguments object as the first argument. | 3436 // Pass a pointer to the Arguments object as the first argument. |
| 3425 // Return result in single register (rax). | 3437 // Return result in single register (rax). |
| 3426 __ lea(rcx, StackSpaceOperand(0)); | 3438 __ lea(rcx, StackSpaceOperand(0)); |
| 3439 __ movq(rdx, ExternalReference::isolate_address()); |
| 3427 } else { | 3440 } else { |
| 3428 ASSERT_EQ(2, result_size_); | 3441 ASSERT_EQ(2, result_size_); |
| 3429 // Pass a pointer to the result location as the first argument. | 3442 // Pass a pointer to the result location as the first argument. |
| 3430 __ lea(rcx, StackSpaceOperand(2)); | 3443 __ lea(rcx, StackSpaceOperand(2)); |
| 3431 // Pass a pointer to the Arguments object as the second argument. | 3444 // Pass a pointer to the Arguments object as the second argument. |
| 3432 __ lea(rdx, StackSpaceOperand(0)); | 3445 __ lea(rdx, StackSpaceOperand(0)); |
| 3446 __ movq(r8, ExternalReference::isolate_address()); |
| 3433 } | 3447 } |
| 3434 | 3448 |
| 3435 #else // _WIN64 | 3449 #else // _WIN64 |
| 3436 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. | 3450 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. |
| 3437 __ movq(rdi, r14); // argc. | 3451 __ movq(rdi, r14); // argc. |
| 3438 __ movq(rsi, r15); // argv. | 3452 __ movq(rsi, r15); // argv. |
| 3453 __ movq(rdx, ExternalReference::isolate_address()); |
| 3439 #endif | 3454 #endif |
| 3440 __ call(rbx); | 3455 __ call(rbx); |
| 3441 // Result is in rax - do not destroy this register! | 3456 // Result is in rax - do not destroy this register! |
| 3442 | 3457 |
| 3443 if (always_allocate_scope) { | 3458 if (always_allocate_scope) { |
| 3444 __ movq(kScratchRegister, scope_depth); | 3459 __ movq(kScratchRegister, scope_depth); |
| 3445 __ decl(Operand(kScratchRegister, 0)); | 3460 __ decl(Operand(kScratchRegister, 0)); |
| 3446 } | 3461 } |
| 3447 | 3462 |
| 3448 // Check for failure result. | 3463 // Check for failure result. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3476 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); | 3491 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); |
| 3477 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); | 3492 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
| 3478 __ j(zero, &retry); | 3493 __ j(zero, &retry); |
| 3479 | 3494 |
| 3480 // Special handling of out of memory exceptions. | 3495 // Special handling of out of memory exceptions. |
| 3481 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); | 3496 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); |
| 3482 __ cmpq(rax, kScratchRegister); | 3497 __ cmpq(rax, kScratchRegister); |
| 3483 __ j(equal, throw_out_of_memory_exception); | 3498 __ j(equal, throw_out_of_memory_exception); |
| 3484 | 3499 |
| 3485 // Retrieve the pending exception and clear the variable. | 3500 // Retrieve the pending exception and clear the variable. |
| 3486 ExternalReference pending_exception_address(Top::k_pending_exception_address); | 3501 ExternalReference pending_exception_address( |
| 3502 Isolate::k_pending_exception_address); |
| 3487 __ movq(kScratchRegister, pending_exception_address); | 3503 __ movq(kScratchRegister, pending_exception_address); |
| 3488 __ movq(rax, Operand(kScratchRegister, 0)); | 3504 __ movq(rax, Operand(kScratchRegister, 0)); |
| 3489 __ movq(rdx, ExternalReference::the_hole_value_location()); | 3505 __ movq(rdx, ExternalReference::the_hole_value_location()); |
| 3490 __ movq(rdx, Operand(rdx, 0)); | 3506 __ movq(rdx, Operand(rdx, 0)); |
| 3491 __ movq(Operand(kScratchRegister, 0), rdx); | 3507 __ movq(Operand(kScratchRegister, 0), rdx); |
| 3492 | 3508 |
| 3493 // Special handling of termination exceptions which are uncatchable | 3509 // Special handling of termination exceptions which are uncatchable |
| 3494 // by javascript code. | 3510 // by javascript code. |
| 3495 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); | 3511 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
| 3496 __ j(equal, throw_termination_exception); | 3512 __ j(equal, throw_termination_exception); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3609 __ push(r15); | 3625 __ push(r15); |
| 3610 #ifdef _WIN64 | 3626 #ifdef _WIN64 |
| 3611 __ push(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI. | 3627 __ push(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI. |
| 3612 __ push(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI. | 3628 __ push(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI. |
| 3613 #endif | 3629 #endif |
| 3614 __ push(rbx); | 3630 __ push(rbx); |
| 3615 // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are | 3631 // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are |
| 3616 // callee save as well. | 3632 // callee save as well. |
| 3617 | 3633 |
| 3618 // Save copies of the top frame descriptor on the stack. | 3634 // Save copies of the top frame descriptor on the stack. |
| 3619 ExternalReference c_entry_fp(Top::k_c_entry_fp_address); | 3635 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address); |
| 3620 __ load_rax(c_entry_fp); | 3636 __ load_rax(c_entry_fp); |
| 3621 __ push(rax); | 3637 __ push(rax); |
| 3622 | 3638 |
| 3623 // Set up the roots and smi constant registers. | 3639 // Set up the roots and smi constant registers. |
| 3624 // Needs to be done before any further smi loads. | 3640 // Needs to be done before any further smi loads. |
| 3625 __ InitializeRootRegister(); | 3641 __ InitializeRootRegister(); |
| 3626 __ InitializeSmiConstantRegister(); | 3642 __ InitializeSmiConstantRegister(); |
| 3627 | 3643 |
| 3628 #ifdef ENABLE_LOGGING_AND_PROFILING | 3644 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3629 // If this is the outermost JS call, set js_entry_sp value. | 3645 // If this is the outermost JS call, set js_entry_sp value. |
| 3630 ExternalReference js_entry_sp(Top::k_js_entry_sp_address); | 3646 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address); |
| 3631 __ load_rax(js_entry_sp); | 3647 __ load_rax(js_entry_sp); |
| 3632 __ testq(rax, rax); | 3648 __ testq(rax, rax); |
| 3633 __ j(not_zero, ¬_outermost_js); | 3649 __ j(not_zero, ¬_outermost_js); |
| 3634 __ movq(rax, rbp); | 3650 __ movq(rax, rbp); |
| 3635 __ store_rax(js_entry_sp); | 3651 __ store_rax(js_entry_sp); |
| 3636 __ bind(¬_outermost_js); | 3652 __ bind(¬_outermost_js); |
| 3637 #endif | 3653 #endif |
| 3638 | 3654 |
| 3639 // Call a faked try-block that does the invoke. | 3655 // Call a faked try-block that does the invoke. |
| 3640 __ call(&invoke); | 3656 __ call(&invoke); |
| 3641 | 3657 |
| 3642 // Caught exception: Store result (exception) in the pending | 3658 // Caught exception: Store result (exception) in the pending |
| 3643 // exception field in the JSEnv and return a failure sentinel. | 3659 // exception field in the JSEnv and return a failure sentinel. |
| 3644 ExternalReference pending_exception(Top::k_pending_exception_address); | 3660 ExternalReference pending_exception(Isolate::k_pending_exception_address); |
| 3645 __ store_rax(pending_exception); | 3661 __ store_rax(pending_exception); |
| 3646 __ movq(rax, Failure::Exception(), RelocInfo::NONE); | 3662 __ movq(rax, Failure::Exception(), RelocInfo::NONE); |
| 3647 __ jmp(&exit); | 3663 __ jmp(&exit); |
| 3648 | 3664 |
| 3649 // Invoke: Link this frame into the handler chain. | 3665 // Invoke: Link this frame into the handler chain. |
| 3650 __ bind(&invoke); | 3666 __ bind(&invoke); |
| 3651 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); | 3667 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); |
| 3652 | 3668 |
| 3653 // Clear any pending exceptions. | 3669 // Clear any pending exceptions. |
| 3654 __ load_rax(ExternalReference::the_hole_value_location()); | 3670 __ load_rax(ExternalReference::the_hole_value_location()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3666 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); | 3682 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); |
| 3667 __ load_rax(construct_entry); | 3683 __ load_rax(construct_entry); |
| 3668 } else { | 3684 } else { |
| 3669 ExternalReference entry(Builtins::JSEntryTrampoline); | 3685 ExternalReference entry(Builtins::JSEntryTrampoline); |
| 3670 __ load_rax(entry); | 3686 __ load_rax(entry); |
| 3671 } | 3687 } |
| 3672 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); | 3688 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); |
| 3673 __ call(kScratchRegister); | 3689 __ call(kScratchRegister); |
| 3674 | 3690 |
| 3675 // Unlink this frame from the handler chain. | 3691 // Unlink this frame from the handler chain. |
| 3676 __ movq(kScratchRegister, ExternalReference(Top::k_handler_address)); | 3692 __ movq(kScratchRegister, ExternalReference(Isolate::k_handler_address)); |
| 3677 __ pop(Operand(kScratchRegister, 0)); | 3693 __ pop(Operand(kScratchRegister, 0)); |
| 3678 // Pop next_sp. | 3694 // Pop next_sp. |
| 3679 __ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); | 3695 __ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); |
| 3680 | 3696 |
| 3681 #ifdef ENABLE_LOGGING_AND_PROFILING | 3697 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 3682 // If current RBP value is the same as js_entry_sp value, it means that | 3698 // If current RBP value is the same as js_entry_sp value, it means that |
| 3683 // the current function is the outermost. | 3699 // the current function is the outermost. |
| 3684 __ movq(kScratchRegister, js_entry_sp); | 3700 __ movq(kScratchRegister, js_entry_sp); |
| 3685 __ cmpq(rbp, Operand(kScratchRegister, 0)); | 3701 __ cmpq(rbp, Operand(kScratchRegister, 0)); |
| 3686 __ j(not_equal, ¬_outermost_js_2); | 3702 __ j(not_equal, ¬_outermost_js_2); |
| 3687 __ movq(Operand(kScratchRegister, 0), Immediate(0)); | 3703 __ movq(Operand(kScratchRegister, 0), Immediate(0)); |
| 3688 __ bind(¬_outermost_js_2); | 3704 __ bind(¬_outermost_js_2); |
| 3689 #endif | 3705 #endif |
| 3690 | 3706 |
| 3691 // Restore the top frame descriptor from the stack. | 3707 // Restore the top frame descriptor from the stack. |
| 3692 __ bind(&exit); | 3708 __ bind(&exit); |
| 3693 __ movq(kScratchRegister, ExternalReference(Top::k_c_entry_fp_address)); | 3709 __ movq(kScratchRegister, ExternalReference(Isolate::k_c_entry_fp_address)); |
| 3694 __ pop(Operand(kScratchRegister, 0)); | 3710 __ pop(Operand(kScratchRegister, 0)); |
| 3695 | 3711 |
| 3696 // Restore callee-saved registers (X64 conventions). | 3712 // Restore callee-saved registers (X64 conventions). |
| 3697 __ pop(rbx); | 3713 __ pop(rbx); |
| 3698 #ifdef _WIN64 | 3714 #ifdef _WIN64 |
| 3699 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. | 3715 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. |
| 3700 __ pop(rsi); | 3716 __ pop(rsi); |
| 3701 __ pop(rdi); | 3717 __ pop(rdi); |
| 3702 #endif | 3718 #endif |
| 3703 __ pop(r15); | 3719 __ pop(r15); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3893 } | 3909 } |
| 3894 | 3910 |
| 3895 | 3911 |
| 3896 // Unfortunately you have to run without snapshots to see most of these | 3912 // Unfortunately you have to run without snapshots to see most of these |
| 3897 // names in the profile since most compare stubs end up in the snapshot. | 3913 // names in the profile since most compare stubs end up in the snapshot. |
| 3898 const char* CompareStub::GetName() { | 3914 const char* CompareStub::GetName() { |
| 3899 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 3915 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
| 3900 | 3916 |
| 3901 if (name_ != NULL) return name_; | 3917 if (name_ != NULL) return name_; |
| 3902 const int kMaxNameLength = 100; | 3918 const int kMaxNameLength = 100; |
| 3903 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength); | 3919 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( |
| 3920 kMaxNameLength); |
| 3904 if (name_ == NULL) return "OOM"; | 3921 if (name_ == NULL) return "OOM"; |
| 3905 | 3922 |
| 3906 const char* cc_name; | 3923 const char* cc_name; |
| 3907 switch (cc_) { | 3924 switch (cc_) { |
| 3908 case less: cc_name = "LT"; break; | 3925 case less: cc_name = "LT"; break; |
| 3909 case greater: cc_name = "GT"; break; | 3926 case greater: cc_name = "GT"; break; |
| 3910 case less_equal: cc_name = "LE"; break; | 3927 case less_equal: cc_name = "LE"; break; |
| 3911 case greater_equal: cc_name = "GE"; break; | 3928 case greater_equal: cc_name = "GE"; break; |
| 3912 case equal: cc_name = "EQ"; break; | 3929 case equal: cc_name = "EQ"; break; |
| 3913 case not_equal: cc_name = "NE"; break; | 3930 case not_equal: cc_name = "NE"; break; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4027 } | 4044 } |
| 4028 | 4045 |
| 4029 | 4046 |
| 4030 void StringCharCodeAtGenerator::GenerateSlow( | 4047 void StringCharCodeAtGenerator::GenerateSlow( |
| 4031 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { | 4048 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { |
| 4032 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); | 4049 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); |
| 4033 | 4050 |
| 4034 // Index is not a smi. | 4051 // Index is not a smi. |
| 4035 __ bind(&index_not_smi_); | 4052 __ bind(&index_not_smi_); |
| 4036 // If index is a heap number, try converting it to an integer. | 4053 // If index is a heap number, try converting it to an integer. |
| 4037 __ CheckMap(index_, Factory::heap_number_map(), index_not_number_, true); | 4054 __ CheckMap(index_, FACTORY->heap_number_map(), index_not_number_, true); |
| 4038 call_helper.BeforeCall(masm); | 4055 call_helper.BeforeCall(masm); |
| 4039 __ push(object_); | 4056 __ push(object_); |
| 4040 __ push(index_); | 4057 __ push(index_); |
| 4041 __ push(index_); // Consumed by runtime conversion function. | 4058 __ push(index_); // Consumed by runtime conversion function. |
| 4042 if (index_flags_ == STRING_INDEX_IS_NUMBER) { | 4059 if (index_flags_ == STRING_INDEX_IS_NUMBER) { |
| 4043 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); | 4060 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); |
| 4044 } else { | 4061 } else { |
| 4045 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); | 4062 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); |
| 4046 // NumberToSmi discards numbers that are not exact integers. | 4063 // NumberToSmi discards numbers that are not exact integers. |
| 4047 __ CallRuntime(Runtime::kNumberToSmi, 1); | 4064 __ CallRuntime(Runtime::kNumberToSmi, 1); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4172 | 4189 |
| 4173 // Both arguments are strings. | 4190 // Both arguments are strings. |
| 4174 // rax: first string | 4191 // rax: first string |
| 4175 // rdx: second string | 4192 // rdx: second string |
| 4176 // Check if either of the strings are empty. In that case return the other. | 4193 // Check if either of the strings are empty. In that case return the other. |
| 4177 NearLabel second_not_zero_length, both_not_zero_length; | 4194 NearLabel second_not_zero_length, both_not_zero_length; |
| 4178 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset)); | 4195 __ movq(rcx, FieldOperand(rdx, String::kLengthOffset)); |
| 4179 __ SmiTest(rcx); | 4196 __ SmiTest(rcx); |
| 4180 __ j(not_zero, &second_not_zero_length); | 4197 __ j(not_zero, &second_not_zero_length); |
| 4181 // Second string is empty, result is first string which is already in rax. | 4198 // Second string is empty, result is first string which is already in rax. |
| 4182 __ IncrementCounter(&Counters::string_add_native, 1); | 4199 __ IncrementCounter(COUNTERS->string_add_native(), 1); |
| 4183 __ ret(2 * kPointerSize); | 4200 __ ret(2 * kPointerSize); |
| 4184 __ bind(&second_not_zero_length); | 4201 __ bind(&second_not_zero_length); |
| 4185 __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); | 4202 __ movq(rbx, FieldOperand(rax, String::kLengthOffset)); |
| 4186 __ SmiTest(rbx); | 4203 __ SmiTest(rbx); |
| 4187 __ j(not_zero, &both_not_zero_length); | 4204 __ j(not_zero, &both_not_zero_length); |
| 4188 // First string is empty, result is second string which is in rdx. | 4205 // First string is empty, result is second string which is in rdx. |
| 4189 __ movq(rax, rdx); | 4206 __ movq(rax, rdx); |
| 4190 __ IncrementCounter(&Counters::string_add_native, 1); | 4207 __ IncrementCounter(COUNTERS->string_add_native(), 1); |
| 4191 __ ret(2 * kPointerSize); | 4208 __ ret(2 * kPointerSize); |
| 4192 | 4209 |
| 4193 // Both strings are non-empty. | 4210 // Both strings are non-empty. |
| 4194 // rax: first string | 4211 // rax: first string |
| 4195 // rbx: length of first string | 4212 // rbx: length of first string |
| 4196 // rcx: length of second string | 4213 // rcx: length of second string |
| 4197 // rdx: second string | 4214 // rdx: second string |
| 4198 // r8: map of first string (if flags_ == NO_STRING_ADD_FLAGS) | 4215 // r8: map of first string (if flags_ == NO_STRING_ADD_FLAGS) |
| 4199 // r9: map of second string (if flags_ == NO_STRING_ADD_FLAGS) | 4216 // r9: map of second string (if flags_ == NO_STRING_ADD_FLAGS) |
| 4200 Label string_add_flat_result, longer_than_two; | 4217 Label string_add_flat_result, longer_than_two; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4224 | 4241 |
| 4225 // Get the two characters forming the sub string. | 4242 // Get the two characters forming the sub string. |
| 4226 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); | 4243 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); |
| 4227 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); | 4244 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); |
| 4228 | 4245 |
| 4229 // Try to lookup two character string in symbol table. If it is not found | 4246 // Try to lookup two character string in symbol table. If it is not found |
| 4230 // just allocate a new one. | 4247 // just allocate a new one. |
| 4231 Label make_two_character_string, make_flat_ascii_string; | 4248 Label make_two_character_string, make_flat_ascii_string; |
| 4232 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 4249 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
| 4233 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string); | 4250 masm, rbx, rcx, r14, r11, rdi, r15, &make_two_character_string); |
| 4234 __ IncrementCounter(&Counters::string_add_native, 1); | 4251 __ IncrementCounter(COUNTERS->string_add_native(), 1); |
| 4235 __ ret(2 * kPointerSize); | 4252 __ ret(2 * kPointerSize); |
| 4236 | 4253 |
| 4237 __ bind(&make_two_character_string); | 4254 __ bind(&make_two_character_string); |
| 4238 __ Set(rbx, 2); | 4255 __ Set(rbx, 2); |
| 4239 __ jmp(&make_flat_ascii_string); | 4256 __ jmp(&make_flat_ascii_string); |
| 4240 | 4257 |
| 4241 __ bind(&longer_than_two); | 4258 __ bind(&longer_than_two); |
| 4242 // Check if resulting string will be flat. | 4259 // Check if resulting string will be flat. |
| 4243 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength)); | 4260 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength)); |
| 4244 __ j(below, &string_add_flat_result); | 4261 __ j(below, &string_add_flat_result); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4264 // Allocate an acsii cons string. | 4281 // Allocate an acsii cons string. |
| 4265 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); | 4282 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); |
| 4266 __ bind(&allocated); | 4283 __ bind(&allocated); |
| 4267 // Fill the fields of the cons string. | 4284 // Fill the fields of the cons string. |
| 4268 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); | 4285 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); |
| 4269 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset), | 4286 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset), |
| 4270 Immediate(String::kEmptyHashField)); | 4287 Immediate(String::kEmptyHashField)); |
| 4271 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); | 4288 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); |
| 4272 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); | 4289 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); |
| 4273 __ movq(rax, rcx); | 4290 __ movq(rax, rcx); |
| 4274 __ IncrementCounter(&Counters::string_add_native, 1); | 4291 __ IncrementCounter(COUNTERS->string_add_native(), 1); |
| 4275 __ ret(2 * kPointerSize); | 4292 __ ret(2 * kPointerSize); |
| 4276 __ bind(&non_ascii); | 4293 __ bind(&non_ascii); |
| 4277 // At least one of the strings is two-byte. Check whether it happens | 4294 // At least one of the strings is two-byte. Check whether it happens |
| 4278 // to contain only ascii characters. | 4295 // to contain only ascii characters. |
| 4279 // rcx: first instance type AND second instance type. | 4296 // rcx: first instance type AND second instance type. |
| 4280 // r8: first instance type. | 4297 // r8: first instance type. |
| 4281 // r9: second instance type. | 4298 // r9: second instance type. |
| 4282 __ testb(rcx, Immediate(kAsciiDataHintMask)); | 4299 __ testb(rcx, Immediate(kAsciiDataHintMask)); |
| 4283 __ j(not_zero, &ascii_data); | 4300 __ j(not_zero, &ascii_data); |
| 4284 __ xor_(r8, r9); | 4301 __ xor_(r8, r9); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4338 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true); | 4355 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, true); |
| 4339 // Locate first character of second argument. | 4356 // Locate first character of second argument. |
| 4340 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset)); | 4357 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset)); |
| 4341 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4358 __ addq(rdx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 4342 // rbx: result string | 4359 // rbx: result string |
| 4343 // rcx: next character of result | 4360 // rcx: next character of result |
| 4344 // rdx: first char of second argument | 4361 // rdx: first char of second argument |
| 4345 // rdi: length of second argument | 4362 // rdi: length of second argument |
| 4346 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true); | 4363 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, true); |
| 4347 __ movq(rax, rbx); | 4364 __ movq(rax, rbx); |
| 4348 __ IncrementCounter(&Counters::string_add_native, 1); | 4365 __ IncrementCounter(COUNTERS->string_add_native(), 1); |
| 4349 __ ret(2 * kPointerSize); | 4366 __ ret(2 * kPointerSize); |
| 4350 | 4367 |
| 4351 // Handle creating a flat two byte result. | 4368 // Handle creating a flat two byte result. |
| 4352 // rax: first string - known to be two byte | 4369 // rax: first string - known to be two byte |
| 4353 // rbx: length of resulting flat string | 4370 // rbx: length of resulting flat string |
| 4354 // rdx: second string | 4371 // rdx: second string |
| 4355 // r8: instance type of first string | 4372 // r8: instance type of first string |
| 4356 // r9: instance type of first string | 4373 // r9: instance type of first string |
| 4357 __ bind(&non_ascii_string_add_flat_result); | 4374 __ bind(&non_ascii_string_add_flat_result); |
| 4358 __ and_(r9, Immediate(kAsciiStringTag)); | 4375 __ and_(r9, Immediate(kAsciiStringTag)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4375 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false); | 4392 StringHelper::GenerateCopyCharacters(masm, rcx, rax, rdi, false); |
| 4376 // Locate first character of second argument. | 4393 // Locate first character of second argument. |
| 4377 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset)); | 4394 __ SmiToInteger32(rdi, FieldOperand(rdx, String::kLengthOffset)); |
| 4378 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 4395 __ addq(rdx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
| 4379 // rbx: result string | 4396 // rbx: result string |
| 4380 // rcx: next character of result | 4397 // rcx: next character of result |
| 4381 // rdx: first char of second argument | 4398 // rdx: first char of second argument |
| 4382 // rdi: length of second argument | 4399 // rdi: length of second argument |
| 4383 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false); | 4400 StringHelper::GenerateCopyCharacters(masm, rcx, rdx, rdi, false); |
| 4384 __ movq(rax, rbx); | 4401 __ movq(rax, rbx); |
| 4385 __ IncrementCounter(&Counters::string_add_native, 1); | 4402 __ IncrementCounter(COUNTERS->string_add_native(), 1); |
| 4386 __ ret(2 * kPointerSize); | 4403 __ ret(2 * kPointerSize); |
| 4387 | 4404 |
| 4388 // Just jump to runtime to add the two strings. | 4405 // Just jump to runtime to add the two strings. |
| 4389 __ bind(&string_add_runtime); | 4406 __ bind(&string_add_runtime); |
| 4390 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 4407 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 4391 | 4408 |
| 4392 if (call_builtin.is_linked()) { | 4409 if (call_builtin.is_linked()) { |
| 4393 __ bind(&call_builtin); | 4410 __ bind(&call_builtin); |
| 4394 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); | 4411 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); |
| 4395 } | 4412 } |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4790 SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4807 SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 4791 } | 4808 } |
| 4792 | 4809 |
| 4793 // rax: result string | 4810 // rax: result string |
| 4794 // rcx: result length | 4811 // rcx: result length |
| 4795 // rdx: original value of rsi | 4812 // rdx: original value of rsi |
| 4796 // rdi: first character of result | 4813 // rdi: first character of result |
| 4797 // rsi: character of sub string start | 4814 // rsi: character of sub string start |
| 4798 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); | 4815 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, true); |
| 4799 __ movq(rsi, rdx); // Restore rsi. | 4816 __ movq(rsi, rdx); // Restore rsi. |
| 4800 __ IncrementCounter(&Counters::sub_string_native, 1); | 4817 __ IncrementCounter(COUNTERS->sub_string_native(), 1); |
| 4801 __ ret(kArgumentsSize); | 4818 __ ret(kArgumentsSize); |
| 4802 | 4819 |
| 4803 __ bind(&non_ascii_flat); | 4820 __ bind(&non_ascii_flat); |
| 4804 // rax: string | 4821 // rax: string |
| 4805 // rbx: instance type & kStringRepresentationMask | kStringEncodingMask | 4822 // rbx: instance type & kStringRepresentationMask | kStringEncodingMask |
| 4806 // rcx: result string length | 4823 // rcx: result string length |
| 4807 // Check for sequential two byte string | 4824 // Check for sequential two byte string |
| 4808 __ cmpb(rbx, Immediate(kSeqStringTag | kTwoByteStringTag)); | 4825 __ cmpb(rbx, Immediate(kSeqStringTag | kTwoByteStringTag)); |
| 4809 __ j(not_equal, &runtime); | 4826 __ j(not_equal, &runtime); |
| 4810 | 4827 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4827 | 4844 |
| 4828 // rax: result string | 4845 // rax: result string |
| 4829 // rcx: result length | 4846 // rcx: result length |
| 4830 // rdx: original value of rsi | 4847 // rdx: original value of rsi |
| 4831 // rdi: first character of result | 4848 // rdi: first character of result |
| 4832 // rsi: character of sub string start | 4849 // rsi: character of sub string start |
| 4833 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); | 4850 StringHelper::GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); |
| 4834 __ movq(rsi, rdx); // Restore esi. | 4851 __ movq(rsi, rdx); // Restore esi. |
| 4835 | 4852 |
| 4836 __ bind(&return_rax); | 4853 __ bind(&return_rax); |
| 4837 __ IncrementCounter(&Counters::sub_string_native, 1); | 4854 __ IncrementCounter(COUNTERS->sub_string_native(), 1); |
| 4838 __ ret(kArgumentsSize); | 4855 __ ret(kArgumentsSize); |
| 4839 | 4856 |
| 4840 // Just jump to runtime to create the sub string. | 4857 // Just jump to runtime to create the sub string. |
| 4841 __ bind(&runtime); | 4858 __ bind(&runtime); |
| 4842 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 4859 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
| 4843 } | 4860 } |
| 4844 | 4861 |
| 4845 | 4862 |
| 4846 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | 4863 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, |
| 4847 Register left, | 4864 Register left, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4941 // rsp[16]: left string | 4958 // rsp[16]: left string |
| 4942 | 4959 |
| 4943 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left | 4960 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left |
| 4944 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right | 4961 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right |
| 4945 | 4962 |
| 4946 // Check for identity. | 4963 // Check for identity. |
| 4947 NearLabel not_same; | 4964 NearLabel not_same; |
| 4948 __ cmpq(rdx, rax); | 4965 __ cmpq(rdx, rax); |
| 4949 __ j(not_equal, ¬_same); | 4966 __ j(not_equal, ¬_same); |
| 4950 __ Move(rax, Smi::FromInt(EQUAL)); | 4967 __ Move(rax, Smi::FromInt(EQUAL)); |
| 4951 __ IncrementCounter(&Counters::string_compare_native, 1); | 4968 __ IncrementCounter(COUNTERS->string_compare_native(), 1); |
| 4952 __ ret(2 * kPointerSize); | 4969 __ ret(2 * kPointerSize); |
| 4953 | 4970 |
| 4954 __ bind(¬_same); | 4971 __ bind(¬_same); |
| 4955 | 4972 |
| 4956 // Check that both are sequential ASCII strings. | 4973 // Check that both are sequential ASCII strings. |
| 4957 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime); | 4974 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime); |
| 4958 | 4975 |
| 4959 // Inline comparison of ascii strings. | 4976 // Inline comparison of ascii strings. |
| 4960 __ IncrementCounter(&Counters::string_compare_native, 1); | 4977 __ IncrementCounter(COUNTERS->string_compare_native(), 1); |
| 4961 // Drop arguments from the stack | 4978 // Drop arguments from the stack |
| 4962 __ pop(rcx); | 4979 __ pop(rcx); |
| 4963 __ addq(rsp, Immediate(2 * kPointerSize)); | 4980 __ addq(rsp, Immediate(2 * kPointerSize)); |
| 4964 __ push(rcx); | 4981 __ push(rcx); |
| 4965 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); | 4982 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); |
| 4966 | 4983 |
| 4967 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 4984 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 4968 // tagged as a small integer. | 4985 // tagged as a small integer. |
| 4969 __ bind(&runtime); | 4986 __ bind(&runtime); |
| 4970 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4987 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5086 // Do a tail call to the rewritten stub. | 5103 // Do a tail call to the rewritten stub. |
| 5087 __ jmp(rdi); | 5104 __ jmp(rdi); |
| 5088 } | 5105 } |
| 5089 | 5106 |
| 5090 | 5107 |
| 5091 #undef __ | 5108 #undef __ |
| 5092 | 5109 |
| 5093 } } // namespace v8::internal | 5110 } } // namespace v8::internal |
| 5094 | 5111 |
| 5095 #endif // V8_TARGET_ARCH_X64 | 5112 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |