| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 } | 156 } |
| 157 // Size of movp(destination, src); | 157 // Size of movp(destination, src); |
| 158 return Assembler::kMoveAddressIntoScratchRegisterInstructionLength; | 158 return Assembler::kMoveAddressIntoScratchRegisterInstructionLength; |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 void MacroAssembler::PushAddress(ExternalReference source) { | 162 void MacroAssembler::PushAddress(ExternalReference source) { |
| 163 int64_t address = reinterpret_cast<int64_t>(source.address()); | 163 int64_t address = reinterpret_cast<int64_t>(source.address()); |
| 164 if (is_int32(address) && !Serializer::enabled()) { | 164 if (is_int32(address) && !Serializer::enabled()) { |
| 165 if (emit_debug_code()) { | 165 if (emit_debug_code()) { |
| 166 Move(kScratchRegister, kZapValue, RelocInfo::NONE64); | 166 Move(kScratchRegister, kZapValue, Assembler::RelocInfoNone()); |
| 167 } | 167 } |
| 168 push(Immediate(static_cast<int32_t>(address))); | 168 push(Immediate(static_cast<int32_t>(address))); |
| 169 return; | 169 return; |
| 170 } | 170 } |
| 171 LoadAddress(kScratchRegister, source); | 171 LoadAddress(kScratchRegister, source); |
| 172 push(kScratchRegister); | 172 push(kScratchRegister); |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { | 176 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 and_(scratch, object); | 282 and_(scratch, object); |
| 283 } | 283 } |
| 284 Move(kScratchRegister, ExternalReference::new_space_start(isolate())); | 284 Move(kScratchRegister, ExternalReference::new_space_start(isolate())); |
| 285 cmpq(scratch, kScratchRegister); | 285 cmpq(scratch, kScratchRegister); |
| 286 j(cc, branch, distance); | 286 j(cc, branch, distance); |
| 287 } else { | 287 } else { |
| 288 ASSERT(is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))); | 288 ASSERT(is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))); |
| 289 intptr_t new_space_start = | 289 intptr_t new_space_start = |
| 290 reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart()); | 290 reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart()); |
| 291 Move(kScratchRegister, reinterpret_cast<Address>(-new_space_start), | 291 Move(kScratchRegister, reinterpret_cast<Address>(-new_space_start), |
| 292 RelocInfo::NONE64); | 292 Assembler::RelocInfoNone()); |
| 293 if (scratch.is(object)) { | 293 if (scratch.is(object)) { |
| 294 addq(scratch, kScratchRegister); | 294 addq(scratch, kScratchRegister); |
| 295 } else { | 295 } else { |
| 296 lea(scratch, Operand(object, kScratchRegister, times_1, 0)); | 296 lea(scratch, Operand(object, kScratchRegister, times_1, 0)); |
| 297 } | 297 } |
| 298 and_(scratch, | 298 and_(scratch, |
| 299 Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask()))); | 299 Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask()))); |
| 300 j(cc, branch, distance); | 300 j(cc, branch, distance); |
| 301 } | 301 } |
| 302 } | 302 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 333 } | 333 } |
| 334 | 334 |
| 335 RecordWrite( | 335 RecordWrite( |
| 336 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); | 336 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); |
| 337 | 337 |
| 338 bind(&done); | 338 bind(&done); |
| 339 | 339 |
| 340 // Clobber clobbered input registers when running with the debug-code flag | 340 // Clobber clobbered input registers when running with the debug-code flag |
| 341 // turned on to provoke errors. | 341 // turned on to provoke errors. |
| 342 if (emit_debug_code()) { | 342 if (emit_debug_code()) { |
| 343 Move(value, kZapValue, RelocInfo::NONE64); | 343 Move(value, kZapValue, Assembler::RelocInfoNone()); |
| 344 Move(dst, kZapValue, RelocInfo::NONE64); | 344 Move(dst, kZapValue, Assembler::RelocInfoNone()); |
| 345 } | 345 } |
| 346 } | 346 } |
| 347 | 347 |
| 348 | 348 |
| 349 void MacroAssembler::RecordWriteArray(Register object, | 349 void MacroAssembler::RecordWriteArray(Register object, |
| 350 Register value, | 350 Register value, |
| 351 Register index, | 351 Register index, |
| 352 SaveFPRegsMode save_fp, | 352 SaveFPRegsMode save_fp, |
| 353 RememberedSetAction remembered_set_action, | 353 RememberedSetAction remembered_set_action, |
| 354 SmiCheck smi_check) { | 354 SmiCheck smi_check) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 367 FixedArray::kHeaderSize - kHeapObjectTag)); | 367 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 368 | 368 |
| 369 RecordWrite( | 369 RecordWrite( |
| 370 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); | 370 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); |
| 371 | 371 |
| 372 bind(&done); | 372 bind(&done); |
| 373 | 373 |
| 374 // Clobber clobbered input registers when running with the debug-code flag | 374 // Clobber clobbered input registers when running with the debug-code flag |
| 375 // turned on to provoke errors. | 375 // turned on to provoke errors. |
| 376 if (emit_debug_code()) { | 376 if (emit_debug_code()) { |
| 377 Move(value, kZapValue, RelocInfo::NONE64); | 377 Move(value, kZapValue, Assembler::RelocInfoNone()); |
| 378 Move(index, kZapValue, RelocInfo::NONE64); | 378 Move(index, kZapValue, Assembler::RelocInfoNone()); |
| 379 } | 379 } |
| 380 } | 380 } |
| 381 | 381 |
| 382 | 382 |
| 383 void MacroAssembler::RecordWrite(Register object, | 383 void MacroAssembler::RecordWrite(Register object, |
| 384 Register address, | 384 Register address, |
| 385 Register value, | 385 Register value, |
| 386 SaveFPRegsMode fp_mode, | 386 SaveFPRegsMode fp_mode, |
| 387 RememberedSetAction remembered_set_action, | 387 RememberedSetAction remembered_set_action, |
| 388 SmiCheck smi_check) { | 388 SmiCheck smi_check) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 Label::kNear); | 432 Label::kNear); |
| 433 | 433 |
| 434 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); | 434 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); |
| 435 CallStub(&stub); | 435 CallStub(&stub); |
| 436 | 436 |
| 437 bind(&done); | 437 bind(&done); |
| 438 | 438 |
| 439 // Clobber clobbered registers when running with the debug-code flag | 439 // Clobber clobbered registers when running with the debug-code flag |
| 440 // turned on to provoke errors. | 440 // turned on to provoke errors. |
| 441 if (emit_debug_code()) { | 441 if (emit_debug_code()) { |
| 442 Move(address, kZapValue, RelocInfo::NONE64); | 442 Move(address, kZapValue, Assembler::RelocInfoNone()); |
| 443 Move(value, kZapValue, RelocInfo::NONE64); | 443 Move(value, kZapValue, Assembler::RelocInfoNone()); |
| 444 } | 444 } |
| 445 } | 445 } |
| 446 | 446 |
| 447 | 447 |
| 448 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { | 448 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { |
| 449 if (emit_debug_code()) Check(cc, reason); | 449 if (emit_debug_code()) Check(cc, reason); |
| 450 } | 450 } |
| 451 | 451 |
| 452 | 452 |
| 453 void MacroAssembler::AssertFastElements(Register elements) { | 453 void MacroAssembler::AssertFastElements(Register elements) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 Label ok; | 498 Label ok; |
| 499 testl(result, result); | 499 testl(result, result); |
| 500 j(not_zero, &ok, Label::kNear); | 500 j(not_zero, &ok, Label::kNear); |
| 501 testl(op, op); | 501 testl(op, op); |
| 502 j(sign, then_label); | 502 j(sign, then_label); |
| 503 bind(&ok); | 503 bind(&ok); |
| 504 } | 504 } |
| 505 | 505 |
| 506 | 506 |
| 507 void MacroAssembler::Abort(BailoutReason reason) { | 507 void MacroAssembler::Abort(BailoutReason reason) { |
| 508 // We want to pass the msg string like a smi to avoid GC | 508 #ifdef DEBUG |
| 509 // problems, however msg is not guaranteed to be aligned | |
| 510 // properly. Instead, we pass an aligned pointer that is | |
| 511 // a proper v8 smi, but also pass the alignment difference | |
| 512 // from the real pointer as a smi. | |
| 513 const char* msg = GetBailoutReason(reason); | 509 const char* msg = GetBailoutReason(reason); |
| 514 intptr_t p1 = reinterpret_cast<intptr_t>(msg); | |
| 515 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; | |
| 516 // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag. | |
| 517 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); | |
| 518 #ifdef DEBUG | |
| 519 if (msg != NULL) { | 510 if (msg != NULL) { |
| 520 RecordComment("Abort message: "); | 511 RecordComment("Abort message: "); |
| 521 RecordComment(msg); | 512 RecordComment(msg); |
| 522 } | 513 } |
| 523 | 514 |
| 524 if (FLAG_trap_on_abort) { | 515 if (FLAG_trap_on_abort) { |
| 525 int3(); | 516 int3(); |
| 526 return; | 517 return; |
| 527 } | 518 } |
| 528 #endif | 519 #endif |
| 529 | 520 |
| 530 push(rax); | 521 push(rax); |
| 531 Move(kScratchRegister, reinterpret_cast<Smi*>(p0), RelocInfo::NONE64); | 522 Move(kScratchRegister, Smi::FromInt(static_cast<int>(reason)), |
| 532 push(kScratchRegister); | 523 Assembler::RelocInfoNone()); |
| 533 Move(kScratchRegister, Smi::FromInt(static_cast<int>(p1 - p0)), | |
| 534 RelocInfo::NONE64); | |
| 535 push(kScratchRegister); | 524 push(kScratchRegister); |
| 536 | 525 |
| 537 if (!has_frame_) { | 526 if (!has_frame_) { |
| 538 // We don't actually want to generate a pile of code for this, so just | 527 // We don't actually want to generate a pile of code for this, so just |
| 539 // claim there is a stack frame, without generating one. | 528 // claim there is a stack frame, without generating one. |
| 540 FrameScope scope(this, StackFrame::NONE); | 529 FrameScope scope(this, StackFrame::NONE); |
| 541 CallRuntime(Runtime::kAbort, 2); | 530 CallRuntime(Runtime::kAbort, 1); |
| 542 } else { | 531 } else { |
| 543 CallRuntime(Runtime::kAbort, 2); | 532 CallRuntime(Runtime::kAbort, 1); |
| 544 } | 533 } |
| 545 // Control will not return here. | 534 // Control will not return here. |
| 546 int3(); | 535 int3(); |
| 547 } | 536 } |
| 548 | 537 |
| 549 | 538 |
| 550 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { | 539 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { |
| 551 ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs | 540 ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs |
| 552 Call(stub->GetCode(isolate()), RelocInfo::CODE_TARGET, ast_id); | 541 Call(stub->GetCode(isolate()), RelocInfo::CODE_TARGET, ast_id); |
| 553 } | 542 } |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 return static_cast<int>(offset); | 652 return static_cast<int>(offset); |
| 664 } | 653 } |
| 665 | 654 |
| 666 | 655 |
| 667 void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) { | 656 void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) { |
| 668 EnterApiExitFrame(arg_stack_space); | 657 EnterApiExitFrame(arg_stack_space); |
| 669 } | 658 } |
| 670 | 659 |
| 671 | 660 |
| 672 void MacroAssembler::CallApiFunctionAndReturn( | 661 void MacroAssembler::CallApiFunctionAndReturn( |
| 673 Address function_address, | 662 Register function_address, |
| 674 Address thunk_address, | 663 Address thunk_address, |
| 675 Register thunk_last_arg, | 664 Register thunk_last_arg, |
| 676 int stack_space, | 665 int stack_space, |
| 677 Operand return_value_operand, | 666 Operand return_value_operand, |
| 678 Operand* context_restore_operand) { | 667 Operand* context_restore_operand) { |
| 679 Label prologue; | 668 Label prologue; |
| 680 Label promote_scheduled_exception; | 669 Label promote_scheduled_exception; |
| 681 Label exception_handled; | 670 Label exception_handled; |
| 682 Label delete_allocated_handles; | 671 Label delete_allocated_handles; |
| 683 Label leave_exit_frame; | 672 Label leave_exit_frame; |
| 684 Label write_back; | 673 Label write_back; |
| 685 | 674 |
| 686 Factory* factory = isolate()->factory(); | 675 Factory* factory = isolate()->factory(); |
| 687 ExternalReference next_address = | 676 ExternalReference next_address = |
| 688 ExternalReference::handle_scope_next_address(isolate()); | 677 ExternalReference::handle_scope_next_address(isolate()); |
| 689 const int kNextOffset = 0; | 678 const int kNextOffset = 0; |
| 690 const int kLimitOffset = Offset( | 679 const int kLimitOffset = Offset( |
| 691 ExternalReference::handle_scope_limit_address(isolate()), | 680 ExternalReference::handle_scope_limit_address(isolate()), |
| 692 next_address); | 681 next_address); |
| 693 const int kLevelOffset = Offset( | 682 const int kLevelOffset = Offset( |
| 694 ExternalReference::handle_scope_level_address(isolate()), | 683 ExternalReference::handle_scope_level_address(isolate()), |
| 695 next_address); | 684 next_address); |
| 696 ExternalReference scheduled_exception_address = | 685 ExternalReference scheduled_exception_address = |
| 697 ExternalReference::scheduled_exception_address(isolate()); | 686 ExternalReference::scheduled_exception_address(isolate()); |
| 698 | 687 |
| 688 ASSERT(rdx.is(function_address) || r8.is(function_address)); |
| 699 // Allocate HandleScope in callee-save registers. | 689 // Allocate HandleScope in callee-save registers. |
| 700 Register prev_next_address_reg = r14; | 690 Register prev_next_address_reg = r14; |
| 701 Register prev_limit_reg = rbx; | 691 Register prev_limit_reg = rbx; |
| 702 Register base_reg = r15; | 692 Register base_reg = r15; |
| 703 Move(base_reg, next_address); | 693 Move(base_reg, next_address); |
| 704 movp(prev_next_address_reg, Operand(base_reg, kNextOffset)); | 694 movp(prev_next_address_reg, Operand(base_reg, kNextOffset)); |
| 705 movp(prev_limit_reg, Operand(base_reg, kLimitOffset)); | 695 movp(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
| 706 addl(Operand(base_reg, kLevelOffset), Immediate(1)); | 696 addl(Operand(base_reg, kLevelOffset), Immediate(1)); |
| 707 | 697 |
| 708 if (FLAG_log_timer_events) { | 698 if (FLAG_log_timer_events) { |
| 709 FrameScope frame(this, StackFrame::MANUAL); | 699 FrameScope frame(this, StackFrame::MANUAL); |
| 710 PushSafepointRegisters(); | 700 PushSafepointRegisters(); |
| 711 PrepareCallCFunction(1); | 701 PrepareCallCFunction(1); |
| 712 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); | 702 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); |
| 713 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); | 703 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); |
| 714 PopSafepointRegisters(); | 704 PopSafepointRegisters(); |
| 715 } | 705 } |
| 716 | 706 |
| 717 | 707 |
| 718 Label profiler_disabled; | 708 Label profiler_disabled; |
| 719 Label end_profiler_check; | 709 Label end_profiler_check; |
| 720 bool* is_profiling_flag = | 710 bool* is_profiling_flag = |
| 721 isolate()->cpu_profiler()->is_profiling_address(); | 711 isolate()->cpu_profiler()->is_profiling_address(); |
| 722 STATIC_ASSERT(sizeof(*is_profiling_flag) == 1); | 712 STATIC_ASSERT(sizeof(*is_profiling_flag) == 1); |
| 723 Move(rax, is_profiling_flag, RelocInfo::EXTERNAL_REFERENCE); | 713 Move(rax, is_profiling_flag, RelocInfo::EXTERNAL_REFERENCE); |
| 724 cmpb(Operand(rax, 0), Immediate(0)); | 714 cmpb(Operand(rax, 0), Immediate(0)); |
| 725 j(zero, &profiler_disabled); | 715 j(zero, &profiler_disabled); |
| 726 | 716 |
| 727 // Third parameter is the address of the actual getter function. | 717 // Third parameter is the address of the actual getter function. |
| 728 Move(thunk_last_arg, function_address, RelocInfo::EXTERNAL_REFERENCE); | 718 Move(thunk_last_arg, function_address); |
| 729 Move(rax, thunk_address, RelocInfo::EXTERNAL_REFERENCE); | 719 Move(rax, thunk_address, RelocInfo::EXTERNAL_REFERENCE); |
| 730 jmp(&end_profiler_check); | 720 jmp(&end_profiler_check); |
| 731 | 721 |
| 732 bind(&profiler_disabled); | 722 bind(&profiler_disabled); |
| 733 // Call the api function! | 723 // Call the api function! |
| 734 Move(rax, reinterpret_cast<Address>(function_address), | 724 Move(rax, function_address); |
| 735 RelocInfo::EXTERNAL_REFERENCE); | |
| 736 | 725 |
| 737 bind(&end_profiler_check); | 726 bind(&end_profiler_check); |
| 738 | 727 |
| 739 // Call the api function! | 728 // Call the api function! |
| 740 call(rax); | 729 call(rax); |
| 741 | 730 |
| 742 if (FLAG_log_timer_events) { | 731 if (FLAG_log_timer_events) { |
| 743 FrameScope frame(this, StackFrame::MANUAL); | 732 FrameScope frame(this, StackFrame::MANUAL); |
| 744 PushSafepointRegisters(); | 733 PushSafepointRegisters(); |
| 745 PrepareCallCFunction(1); | 734 PrepareCallCFunction(1); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 } else if (is_uint32(x)) { | 965 } else if (is_uint32(x)) { |
| 977 movl(dst, Immediate(static_cast<uint32_t>(x))); | 966 movl(dst, Immediate(static_cast<uint32_t>(x))); |
| 978 } else if (is_int32(x)) { | 967 } else if (is_int32(x)) { |
| 979 movq(dst, Immediate(static_cast<int32_t>(x))); | 968 movq(dst, Immediate(static_cast<int32_t>(x))); |
| 980 } else { | 969 } else { |
| 981 movq(dst, x); | 970 movq(dst, x); |
| 982 } | 971 } |
| 983 } | 972 } |
| 984 | 973 |
| 985 | 974 |
| 986 void MacroAssembler::Set(const Operand& dst, int64_t x) { | 975 void MacroAssembler::Set(const Operand& dst, intptr_t x) { |
| 987 if (is_int32(x)) { | 976 if (kPointerSize == kInt64Size) { |
| 988 movq(dst, Immediate(static_cast<int32_t>(x))); | 977 if (is_int32(x)) { |
| 978 movp(dst, Immediate(static_cast<int32_t>(x))); |
| 979 } else { |
| 980 Set(kScratchRegister, x); |
| 981 movp(dst, kScratchRegister); |
| 982 } |
| 989 } else { | 983 } else { |
| 990 Set(kScratchRegister, x); | 984 ASSERT(kPointerSize == kInt32Size); |
| 991 movq(dst, kScratchRegister); | 985 movp(dst, Immediate(static_cast<int32_t>(x))); |
| 992 } | 986 } |
| 993 } | 987 } |
| 994 | 988 |
| 995 | 989 |
| 996 // ---------------------------------------------------------------------------- | 990 // ---------------------------------------------------------------------------- |
| 997 // Smi tagging, untagging and tag detection. | 991 // Smi tagging, untagging and tag detection. |
| 998 | 992 |
| 999 bool MacroAssembler::IsUnsafeInt(const int32_t x) { | 993 bool MacroAssembler::IsUnsafeInt(const int32_t x) { |
| 1000 static const int kMaxBits = 17; | 994 static const int kMaxBits = 17; |
| 1001 return !is_intn(x, kMaxBits); | 995 return !is_intn(x, kMaxBits); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1036 if (value == 1) { | 1030 if (value == 1) { |
| 1037 return kSmiConstantRegister; | 1031 return kSmiConstantRegister; |
| 1038 } | 1032 } |
| 1039 LoadSmiConstant(kScratchRegister, source); | 1033 LoadSmiConstant(kScratchRegister, source); |
| 1040 return kScratchRegister; | 1034 return kScratchRegister; |
| 1041 } | 1035 } |
| 1042 | 1036 |
| 1043 | 1037 |
| 1044 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { | 1038 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { |
| 1045 if (emit_debug_code()) { | 1039 if (emit_debug_code()) { |
| 1046 Move(dst, Smi::FromInt(kSmiConstantRegisterValue), RelocInfo::NONE64); | 1040 Move(dst, Smi::FromInt(kSmiConstantRegisterValue), |
| 1041 Assembler::RelocInfoNone()); |
| 1047 cmpq(dst, kSmiConstantRegister); | 1042 cmpq(dst, kSmiConstantRegister); |
| 1048 Assert(equal, kUninitializedKSmiConstantRegister); | 1043 Assert(equal, kUninitializedKSmiConstantRegister); |
| 1049 } | 1044 } |
| 1050 int value = source->value(); | 1045 int value = source->value(); |
| 1051 if (value == 0) { | 1046 if (value == 0) { |
| 1052 xorl(dst, dst); | 1047 xorl(dst, dst); |
| 1053 return; | 1048 return; |
| 1054 } | 1049 } |
| 1055 bool negative = value < 0; | 1050 bool negative = value < 0; |
| 1056 unsigned int uvalue = negative ? -value : value; | 1051 unsigned int uvalue = negative ? -value : value; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1076 case 2: | 1071 case 2: |
| 1077 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0)); | 1072 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0)); |
| 1078 break; | 1073 break; |
| 1079 case 1: | 1074 case 1: |
| 1080 movp(dst, kSmiConstantRegister); | 1075 movp(dst, kSmiConstantRegister); |
| 1081 break; | 1076 break; |
| 1082 case 0: | 1077 case 0: |
| 1083 UNREACHABLE(); | 1078 UNREACHABLE(); |
| 1084 return; | 1079 return; |
| 1085 default: | 1080 default: |
| 1086 Move(dst, source, RelocInfo::NONE64); | 1081 Move(dst, source, Assembler::RelocInfoNone()); |
| 1087 return; | 1082 return; |
| 1088 } | 1083 } |
| 1089 if (negative) { | 1084 if (negative) { |
| 1090 neg(dst); | 1085 neg(dst); |
| 1091 } | 1086 } |
| 1092 } | 1087 } |
| 1093 | 1088 |
| 1094 | 1089 |
| 1095 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { | 1090 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
| 1096 STATIC_ASSERT(kSmiTag == 0); | 1091 STATIC_ASSERT(kSmiTag == 0); |
| (...skipping 1486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2583 testb(Operand(src, byte_offset), Immediate(1 << bit_in_byte)); | 2578 testb(Operand(src, byte_offset), Immediate(1 << bit_in_byte)); |
| 2584 } | 2579 } |
| 2585 | 2580 |
| 2586 | 2581 |
| 2587 void MacroAssembler::Jump(ExternalReference ext) { | 2582 void MacroAssembler::Jump(ExternalReference ext) { |
| 2588 LoadAddress(kScratchRegister, ext); | 2583 LoadAddress(kScratchRegister, ext); |
| 2589 jmp(kScratchRegister); | 2584 jmp(kScratchRegister); |
| 2590 } | 2585 } |
| 2591 | 2586 |
| 2592 | 2587 |
| 2588 void MacroAssembler::Jump(const Operand& op) { |
| 2589 if (kPointerSize == kInt64Size) { |
| 2590 jmp(op); |
| 2591 } else { |
| 2592 ASSERT(kPointerSize == kInt32Size); |
| 2593 movp(kScratchRegister, op); |
| 2594 jmp(kScratchRegister); |
| 2595 } |
| 2596 } |
| 2597 |
| 2598 |
| 2593 void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { | 2599 void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { |
| 2594 Move(kScratchRegister, destination, rmode); | 2600 Move(kScratchRegister, destination, rmode); |
| 2595 jmp(kScratchRegister); | 2601 jmp(kScratchRegister); |
| 2596 } | 2602 } |
| 2597 | 2603 |
| 2598 | 2604 |
| 2599 void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { | 2605 void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { |
| 2600 // TODO(X64): Inline this | 2606 // TODO(X64): Inline this |
| 2601 jmp(code_object, rmode); | 2607 jmp(code_object, rmode); |
| 2602 } | 2608 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2614 int end_position = pc_offset() + CallSize(ext); | 2620 int end_position = pc_offset() + CallSize(ext); |
| 2615 #endif | 2621 #endif |
| 2616 LoadAddress(kScratchRegister, ext); | 2622 LoadAddress(kScratchRegister, ext); |
| 2617 call(kScratchRegister); | 2623 call(kScratchRegister); |
| 2618 #ifdef DEBUG | 2624 #ifdef DEBUG |
| 2619 CHECK_EQ(end_position, pc_offset()); | 2625 CHECK_EQ(end_position, pc_offset()); |
| 2620 #endif | 2626 #endif |
| 2621 } | 2627 } |
| 2622 | 2628 |
| 2623 | 2629 |
| 2630 void MacroAssembler::Call(const Operand& op) { |
| 2631 if (kPointerSize == kInt64Size) { |
| 2632 call(op); |
| 2633 } else { |
| 2634 ASSERT(kPointerSize == kInt32Size); |
| 2635 movp(kScratchRegister, op); |
| 2636 call(kScratchRegister); |
| 2637 } |
| 2638 } |
| 2639 |
| 2640 |
| 2624 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { | 2641 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { |
| 2625 #ifdef DEBUG | 2642 #ifdef DEBUG |
| 2626 int end_position = pc_offset() + CallSize(destination, rmode); | 2643 int end_position = pc_offset() + CallSize(destination); |
| 2627 #endif | 2644 #endif |
| 2628 Move(kScratchRegister, destination, rmode); | 2645 Move(kScratchRegister, destination, rmode); |
| 2629 call(kScratchRegister); | 2646 call(kScratchRegister); |
| 2630 #ifdef DEBUG | 2647 #ifdef DEBUG |
| 2631 CHECK_EQ(pc_offset(), end_position); | 2648 CHECK_EQ(pc_offset(), end_position); |
| 2632 #endif | 2649 #endif |
| 2633 } | 2650 } |
| 2634 | 2651 |
| 2635 | 2652 |
| 2636 void MacroAssembler::Call(Handle<Code> code_object, | 2653 void MacroAssembler::Call(Handle<Code> code_object, |
| (...skipping 1404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4041 } | 4058 } |
| 4042 | 4059 |
| 4043 | 4060 |
| 4044 void MacroAssembler::Allocate(int object_size, | 4061 void MacroAssembler::Allocate(int object_size, |
| 4045 Register result, | 4062 Register result, |
| 4046 Register result_end, | 4063 Register result_end, |
| 4047 Register scratch, | 4064 Register scratch, |
| 4048 Label* gc_required, | 4065 Label* gc_required, |
| 4049 AllocationFlags flags) { | 4066 AllocationFlags flags) { |
| 4050 ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); | 4067 ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); |
| 4051 ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize); | 4068 ASSERT(object_size <= Page::kMaxRegularHeapObjectSize); |
| 4052 if (!FLAG_inline_new) { | 4069 if (!FLAG_inline_new) { |
| 4053 if (emit_debug_code()) { | 4070 if (emit_debug_code()) { |
| 4054 // Trash the registers to simulate an allocation failure. | 4071 // Trash the registers to simulate an allocation failure. |
| 4055 movl(result, Immediate(0x7091)); | 4072 movl(result, Immediate(0x7091)); |
| 4056 if (result_end.is_valid()) { | 4073 if (result_end.is_valid()) { |
| 4057 movl(result_end, Immediate(0x7191)); | 4074 movl(result_end, Immediate(0x7191)); |
| 4058 } | 4075 } |
| 4059 if (scratch.is_valid()) { | 4076 if (scratch.is_valid()) { |
| 4060 movl(scratch, Immediate(0x7291)); | 4077 movl(scratch, Immediate(0x7291)); |
| 4061 } | 4078 } |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4506 cmpq(map_in_out, FieldOperand(scratch, offset)); | 4523 cmpq(map_in_out, FieldOperand(scratch, offset)); |
| 4507 j(not_equal, no_map_match); | 4524 j(not_equal, no_map_match); |
| 4508 | 4525 |
| 4509 // Use the transitioned cached map. | 4526 // Use the transitioned cached map. |
| 4510 offset = transitioned_kind * kPointerSize + | 4527 offset = transitioned_kind * kPointerSize + |
| 4511 FixedArrayBase::kHeaderSize; | 4528 FixedArrayBase::kHeaderSize; |
| 4512 movp(map_in_out, FieldOperand(scratch, offset)); | 4529 movp(map_in_out, FieldOperand(scratch, offset)); |
| 4513 } | 4530 } |
| 4514 | 4531 |
| 4515 | 4532 |
| 4516 void MacroAssembler::LoadInitialArrayMap( | |
| 4517 Register function_in, Register scratch, | |
| 4518 Register map_out, bool can_have_holes) { | |
| 4519 ASSERT(!function_in.is(map_out)); | |
| 4520 Label done; | |
| 4521 movp(map_out, FieldOperand(function_in, | |
| 4522 JSFunction::kPrototypeOrInitialMapOffset)); | |
| 4523 if (!FLAG_smi_only_arrays) { | |
| 4524 ElementsKind kind = can_have_holes ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; | |
| 4525 LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | |
| 4526 kind, | |
| 4527 map_out, | |
| 4528 scratch, | |
| 4529 &done); | |
| 4530 } else if (can_have_holes) { | |
| 4531 LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | |
| 4532 FAST_HOLEY_SMI_ELEMENTS, | |
| 4533 map_out, | |
| 4534 scratch, | |
| 4535 &done); | |
| 4536 } | |
| 4537 bind(&done); | |
| 4538 } | |
| 4539 | |
| 4540 #ifdef _WIN64 | 4533 #ifdef _WIN64 |
| 4541 static const int kRegisterPassedArguments = 4; | 4534 static const int kRegisterPassedArguments = 4; |
| 4542 #else | 4535 #else |
| 4543 static const int kRegisterPassedArguments = 6; | 4536 static const int kRegisterPassedArguments = 6; |
| 4544 #endif | 4537 #endif |
| 4545 | 4538 |
| 4546 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 4539 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 4547 // Load the global or builtins object from the current context. | 4540 // Load the global or builtins object from the current context. |
| 4548 movp(function, | 4541 movp(function, |
| 4549 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4542 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 4550 // Load the native context from the global or builtins object. | 4543 // Load the native context from the global or builtins object. |
| 4551 movp(function, FieldOperand(function, GlobalObject::kNativeContextOffset)); | 4544 movp(function, FieldOperand(function, GlobalObject::kNativeContextOffset)); |
| 4552 // Load the function from the native context. | 4545 // Load the function from the native context. |
| 4553 movp(function, Operand(function, Context::SlotOffset(index))); | 4546 movp(function, Operand(function, Context::SlotOffset(index))); |
| 4554 } | 4547 } |
| 4555 | 4548 |
| 4556 | 4549 |
| 4557 void MacroAssembler::LoadArrayFunction(Register function) { | |
| 4558 movp(function, | |
| 4559 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
| 4560 movp(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); | |
| 4561 movp(function, | |
| 4562 Operand(function, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | |
| 4563 } | |
| 4564 | |
| 4565 | |
| 4566 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 4550 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 4567 Register map) { | 4551 Register map) { |
| 4568 // Load the initial map. The global functions all have initial maps. | 4552 // Load the initial map. The global functions all have initial maps. |
| 4569 movp(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 4553 movp(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 4570 if (emit_debug_code()) { | 4554 if (emit_debug_code()) { |
| 4571 Label ok, fail; | 4555 Label ok, fail; |
| 4572 CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); | 4556 CheckMap(map, isolate()->factory()->meta_map(), &fail, DO_SMI_CHECK); |
| 4573 jmp(&ok); | 4557 jmp(&ok); |
| 4574 bind(&fail); | 4558 bind(&fail); |
| 4575 Abort(kGlobalFunctionsMustHaveInitialMap); | 4559 Abort(kGlobalFunctionsMustHaveInitialMap); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4596 #endif | 4580 #endif |
| 4597 } | 4581 } |
| 4598 | 4582 |
| 4599 | 4583 |
| 4600 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, | 4584 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, |
| 4601 Register index, | 4585 Register index, |
| 4602 Register value, | 4586 Register value, |
| 4603 uint32_t encoding_mask) { | 4587 uint32_t encoding_mask) { |
| 4604 Label is_object; | 4588 Label is_object; |
| 4605 JumpIfNotSmi(string, &is_object); | 4589 JumpIfNotSmi(string, &is_object); |
| 4606 Throw(kNonObject); | 4590 Abort(kNonObject); |
| 4607 bind(&is_object); | 4591 bind(&is_object); |
| 4608 | 4592 |
| 4609 push(value); | 4593 push(value); |
| 4610 movp(value, FieldOperand(string, HeapObject::kMapOffset)); | 4594 movp(value, FieldOperand(string, HeapObject::kMapOffset)); |
| 4611 movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset)); | 4595 movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset)); |
| 4612 | 4596 |
| 4613 andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); | 4597 andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
| 4614 cmpq(value, Immediate(encoding_mask)); | 4598 cmpq(value, Immediate(encoding_mask)); |
| 4615 pop(value); | 4599 pop(value); |
| 4616 ThrowIf(not_equal, kUnexpectedStringType); | 4600 Check(equal, kUnexpectedStringType); |
| 4617 | 4601 |
| 4618 // The index is assumed to be untagged coming in, tag it to compare with the | 4602 // The index is assumed to be untagged coming in, tag it to compare with the |
| 4619 // string length without using a temp register, it is restored at the end of | 4603 // string length without using a temp register, it is restored at the end of |
| 4620 // this function. | 4604 // this function. |
| 4621 Integer32ToSmi(index, index); | 4605 Integer32ToSmi(index, index); |
| 4622 SmiCompare(index, FieldOperand(string, String::kLengthOffset)); | 4606 SmiCompare(index, FieldOperand(string, String::kLengthOffset)); |
| 4623 ThrowIf(greater_equal, kIndexIsTooLarge); | 4607 Check(less, kIndexIsTooLarge); |
| 4624 | 4608 |
| 4625 SmiCompare(index, Smi::FromInt(0)); | 4609 SmiCompare(index, Smi::FromInt(0)); |
| 4626 ThrowIf(less, kIndexIsNegative); | 4610 Check(greater_equal, kIndexIsNegative); |
| 4627 | 4611 |
| 4628 // Restore the index | 4612 // Restore the index |
| 4629 SmiToInteger32(index, index); | 4613 SmiToInteger32(index, index); |
| 4630 } | 4614 } |
| 4631 | 4615 |
| 4632 | 4616 |
| 4633 void MacroAssembler::PrepareCallCFunction(int num_arguments) { | 4617 void MacroAssembler::PrepareCallCFunction(int num_arguments) { |
| 4634 int frame_alignment = OS::ActivationFrameAlignment(); | 4618 int frame_alignment = OS::ActivationFrameAlignment(); |
| 4635 ASSERT(frame_alignment != 0); | 4619 ASSERT(frame_alignment != 0); |
| 4636 ASSERT(num_arguments >= 0); | 4620 ASSERT(num_arguments >= 0); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4925 | 4909 |
| 4926 // For all objects but the receiver, check that the cache is empty. | 4910 // For all objects but the receiver, check that the cache is empty. |
| 4927 EnumLength(rdx, rbx); | 4911 EnumLength(rdx, rbx); |
| 4928 Cmp(rdx, Smi::FromInt(0)); | 4912 Cmp(rdx, Smi::FromInt(0)); |
| 4929 j(not_equal, call_runtime); | 4913 j(not_equal, call_runtime); |
| 4930 | 4914 |
| 4931 bind(&start); | 4915 bind(&start); |
| 4932 | 4916 |
| 4933 // Check that there are no elements. Register rcx contains the current JS | 4917 // Check that there are no elements. Register rcx contains the current JS |
| 4934 // object we've reached through the prototype chain. | 4918 // object we've reached through the prototype chain. |
| 4919 Label no_elements; |
| 4935 cmpq(empty_fixed_array_value, | 4920 cmpq(empty_fixed_array_value, |
| 4936 FieldOperand(rcx, JSObject::kElementsOffset)); | 4921 FieldOperand(rcx, JSObject::kElementsOffset)); |
| 4922 j(equal, &no_elements); |
| 4923 |
| 4924 // Second chance, the object may be using the empty slow element dictionary. |
| 4925 LoadRoot(kScratchRegister, Heap::kEmptySlowElementDictionaryRootIndex); |
| 4926 cmpq(kScratchRegister, FieldOperand(rcx, JSObject::kElementsOffset)); |
| 4937 j(not_equal, call_runtime); | 4927 j(not_equal, call_runtime); |
| 4938 | 4928 |
| 4929 bind(&no_elements); |
| 4939 movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); | 4930 movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); |
| 4940 cmpq(rcx, null_value); | 4931 cmpq(rcx, null_value); |
| 4941 j(not_equal, &next); | 4932 j(not_equal, &next); |
| 4942 } | 4933 } |
| 4943 | 4934 |
| 4944 void MacroAssembler::TestJSArrayForAllocationMemento( | 4935 void MacroAssembler::TestJSArrayForAllocationMemento( |
| 4945 Register receiver_reg, | 4936 Register receiver_reg, |
| 4946 Register scratch_reg, | 4937 Register scratch_reg, |
| 4947 Label* no_memento_found) { | 4938 Label* no_memento_found) { |
| 4948 ExternalReference new_space_start = | 4939 ExternalReference new_space_start = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4984 j(equal, found); | 4975 j(equal, found); |
| 4985 movp(current, FieldOperand(current, Map::kPrototypeOffset)); | 4976 movp(current, FieldOperand(current, Map::kPrototypeOffset)); |
| 4986 CompareRoot(current, Heap::kNullValueRootIndex); | 4977 CompareRoot(current, Heap::kNullValueRootIndex); |
| 4987 j(not_equal, &loop_again); | 4978 j(not_equal, &loop_again); |
| 4988 } | 4979 } |
| 4989 | 4980 |
| 4990 | 4981 |
| 4991 } } // namespace v8::internal | 4982 } } // namespace v8::internal |
| 4992 | 4983 |
| 4993 #endif // V8_TARGET_ARCH_X64 | 4984 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |