Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1685)

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 6880010: Merge (7265, 7271] from bleeding_edge to experimental/gc branch.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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, &not_identical); 3092 __ j(above_equal, &not_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
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, &not_smis); 3128 __ SelectNonSmi(rbx, rax, rdx, &not_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(&not_smis); 3139 __ bind(&not_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
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
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
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
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, &not_outermost_js); 3649 __ j(not_zero, &not_outermost_js);
3634 __ movq(rax, rbp); 3650 __ movq(rax, rbp);
3635 __ store_rax(js_entry_sp); 3651 __ store_rax(js_entry_sp);
3636 __ bind(&not_outermost_js); 3652 __ bind(&not_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
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, &not_outermost_js_2); 3702 __ j(not_equal, &not_outermost_js_2);
3687 __ movq(Operand(kScratchRegister, 0), Immediate(0)); 3703 __ movq(Operand(kScratchRegister, 0), Immediate(0));
3688 __ bind(&not_outermost_js_2); 3704 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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, &not_same); 4966 __ j(not_equal, &not_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(&not_same); 4971 __ bind(&not_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
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
OLDNEW
« src/store-buffer.cc ('K') | « src/x64/builtins-x64.cc ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698