OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 | 462 |
463 | 463 |
464 static int Offset(ExternalReference ref0, ExternalReference ref1) { | 464 static int Offset(ExternalReference ref0, ExternalReference ref1) { |
465 int64_t offset = (ref0.address() - ref1.address()); | 465 int64_t offset = (ref0.address() - ref1.address()); |
466 // Check that fits into int. | 466 // Check that fits into int. |
467 ASSERT(static_cast<int>(offset) == offset); | 467 ASSERT(static_cast<int>(offset) == offset); |
468 return static_cast<int>(offset); | 468 return static_cast<int>(offset); |
469 } | 469 } |
470 | 470 |
471 | 471 |
472 void MacroAssembler::PushHandleScope(Register scratch) { | 472 void MacroAssembler::PrepareCallApiFunction(int stack_space) { |
473 ExternalReference extensions_address = | 473 EnterApiExitFrame(stack_space, 0); |
474 ExternalReference::handle_scope_extensions_address(); | |
475 const int kExtensionsOffset = 0; | |
476 const int kNextOffset = Offset( | |
477 ExternalReference::handle_scope_next_address(), | |
478 extensions_address); | |
479 const int kLimitOffset = Offset( | |
480 ExternalReference::handle_scope_limit_address(), | |
481 extensions_address); | |
482 | |
483 // Push the number of extensions, smi-tagged so the gc will ignore it. | |
484 movq(kScratchRegister, extensions_address); | |
485 movq(scratch, Operand(kScratchRegister, kExtensionsOffset)); | |
486 movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); | |
487 Integer32ToSmi(scratch, scratch); | |
488 push(scratch); | |
489 // Push next and limit pointers which will be wordsize aligned and | |
490 // hence automatically smi tagged. | |
491 push(Operand(kScratchRegister, kNextOffset)); | |
492 push(Operand(kScratchRegister, kLimitOffset)); | |
493 } | 474 } |
494 | 475 |
495 | 476 |
496 Object* MacroAssembler::PopHandleScopeHelper(Register saved, | 477 void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) { |
497 Register scratch, | 478 Label empty_result; |
498 bool gc_allowed) { | 479 Label prologue; |
499 ExternalReference extensions_address = | 480 Label promote_scheduled_exception; |
500 ExternalReference::handle_scope_extensions_address(); | 481 Label delete_allocated_handles; |
501 const int kExtensionsOffset = 0; | 482 Label leave_exit_frame; |
502 const int kNextOffset = Offset( | 483 Label write_back; |
503 ExternalReference::handle_scope_next_address(), | 484 |
504 extensions_address); | 485 ExternalReference next_address = |
| 486 ExternalReference::handle_scope_next_address(); |
| 487 const int kNextOffset = 0; |
505 const int kLimitOffset = Offset( | 488 const int kLimitOffset = Offset( |
506 ExternalReference::handle_scope_limit_address(), | 489 ExternalReference::handle_scope_limit_address(), |
507 extensions_address); | 490 next_address); |
| 491 const int kLevelOffset = Offset( |
| 492 ExternalReference::handle_scope_level_address(), |
| 493 next_address); |
| 494 ExternalReference scheduled_exception_address = |
| 495 ExternalReference::scheduled_exception_address(); |
508 | 496 |
509 Object* result = NULL; | 497 // Allocate HandleScope in callee-save registers. |
510 Label write_back; | 498 Register prev_next_address_reg = r14; |
511 movq(kScratchRegister, extensions_address); | 499 Register prev_limit_reg = rbx; |
512 cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); | 500 Register base_reg = kSmiConstantRegister; |
513 j(equal, &write_back); | 501 movq(base_reg, next_address); |
514 push(saved); | 502 movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); |
515 if (gc_allowed) { | 503 movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
516 CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); | 504 addl(Operand(base_reg, kLevelOffset), Immediate(1)); |
517 } else { | 505 // Call the api function! |
518 result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); | 506 movq(rax, |
519 if (result->IsFailure()) return result; | 507 reinterpret_cast<int64_t>(function->address()), |
520 } | 508 RelocInfo::RUNTIME_ENTRY); |
521 pop(saved); | 509 call(rax); |
522 movq(kScratchRegister, extensions_address); | |
523 | 510 |
524 bind(&write_back); | 511 #ifdef _WIN64 |
525 pop(Operand(kScratchRegister, kLimitOffset)); | 512 // rax keeps a pointer to v8::Handle, unpack it. |
526 pop(Operand(kScratchRegister, kNextOffset)); | 513 movq(rax, Operand(rax, 0)); |
527 pop(scratch); | 514 #endif |
528 SmiToInteger32(scratch, scratch); | 515 // Check if the result handle holds 0. |
529 movq(Operand(kScratchRegister, kExtensionsOffset), scratch); | 516 testq(rax, rax); |
| 517 j(zero, &empty_result); |
| 518 // It was non-zero. Dereference to get the result value. |
| 519 movq(rax, Operand(rax, 0)); |
| 520 bind(&prologue); |
530 | 521 |
531 return result; | 522 // No more valid handles (the result handle was the last one). Restore |
| 523 // previous handle scope. |
| 524 subl(Operand(base_reg, kLevelOffset), Immediate(1)); |
| 525 movq(Operand(base_reg, kNextOffset), prev_next_address_reg); |
| 526 cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
| 527 j(not_equal, &delete_allocated_handles); |
| 528 bind(&leave_exit_frame); |
| 529 InitializeSmiConstantRegister(); |
| 530 |
| 531 // Check if the function scheduled an exception. |
| 532 movq(rsi, scheduled_exception_address); |
| 533 Cmp(Operand(rsi, 0), Factory::the_hole_value()); |
| 534 j(not_equal, &promote_scheduled_exception); |
| 535 |
| 536 LeaveExitFrame(); |
| 537 ret(0); |
| 538 |
| 539 bind(&promote_scheduled_exception); |
| 540 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
| 541 |
| 542 bind(&empty_result); |
| 543 // It was zero; the result is undefined. |
| 544 Move(rax, Factory::undefined_value()); |
| 545 jmp(&prologue); |
| 546 |
| 547 // HandleScope limit has changed. Delete allocated extensions. |
| 548 bind(&delete_allocated_handles); |
| 549 movq(Operand(base_reg, kLimitOffset), prev_limit_reg); |
| 550 movq(prev_limit_reg, rax); |
| 551 movq(rax, ExternalReference::delete_handle_scope_extensions()); |
| 552 call(rax); |
| 553 movq(rax, prev_limit_reg); |
| 554 jmp(&leave_exit_frame); |
532 } | 555 } |
533 | 556 |
534 | 557 |
535 void MacroAssembler::PopHandleScope(Register saved, Register scratch) { | |
536 PopHandleScopeHelper(saved, scratch, true); | |
537 } | |
538 | |
539 | |
540 Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { | |
541 return PopHandleScopeHelper(saved, scratch, false); | |
542 } | |
543 | |
544 | |
545 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, | 558 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, |
546 int result_size) { | 559 int result_size) { |
547 // Set the entry point and jump to the C entry runtime stub. | 560 // Set the entry point and jump to the C entry runtime stub. |
548 movq(rbx, ext); | 561 movq(rbx, ext); |
549 CEntryStub ces(result_size); | 562 CEntryStub ces(result_size); |
550 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 563 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
551 } | 564 } |
552 | 565 |
553 | 566 |
554 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { | 567 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { |
(...skipping 1668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 CPU::FlushICache(address_, size_); | 2236 CPU::FlushICache(address_, size_); |
2224 | 2237 |
2225 // Check that the code was patched as expected. | 2238 // Check that the code was patched as expected. |
2226 ASSERT(masm_.pc_ == address_ + size_); | 2239 ASSERT(masm_.pc_ == address_ + size_); |
2227 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2240 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
2228 } | 2241 } |
2229 | 2242 |
2230 } } // namespace v8::internal | 2243 } } // namespace v8::internal |
2231 | 2244 |
2232 #endif // V8_TARGET_ARCH_X64 | 2245 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |