| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 | 71 |
| 72 // Set dirty mark for region. | 72 // Set dirty mark for region. |
| 73 bts(Operand(object, Page::kDirtyFlagOffset), addr); | 73 bts(Operand(object, Page::kDirtyFlagOffset), addr); |
| 74 } | 74 } |
| 75 | 75 |
| 76 | 76 |
| 77 void MacroAssembler::RecordWrite(Register object, | 77 void MacroAssembler::RecordWrite(Register object, |
| 78 int offset, | 78 int offset, |
| 79 Register value, | 79 Register value, |
| 80 Register scratch) { | 80 Register scratch) { |
| 81 // The compiled code assumes that record write doesn't change the | |
| 82 // context register, so we check that none of the clobbered | |
| 83 // registers are esi. | |
| 84 ASSERT(!object.is(esi) && !value.is(esi) && !scratch.is(esi)); | |
| 85 | |
| 86 // First, check if a write barrier is even needed. The tests below | 81 // First, check if a write barrier is even needed. The tests below |
| 87 // catch stores of Smis and stores into young gen. | 82 // catch stores of Smis and stores into young gen. |
| 88 NearLabel done; | 83 NearLabel done; |
| 89 | 84 |
| 90 // Skip barrier if writing a smi. | 85 // Skip barrier if writing a smi. |
| 91 ASSERT_EQ(0, kSmiTag); | 86 ASSERT_EQ(0, kSmiTag); |
| 92 test(value, Immediate(kSmiTagMask)); | 87 test(value, Immediate(kSmiTagMask)); |
| 93 j(zero, &done); | 88 j(zero, &done); |
| 94 | 89 |
| 95 InNewSpace(object, value, equal, &done); | 90 InNewSpace(object, value, equal, &done); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 122 mov(object, Immediate(BitCast<int32_t>(kZapValue))); | 117 mov(object, Immediate(BitCast<int32_t>(kZapValue))); |
| 123 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 118 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
| 124 mov(scratch, Immediate(BitCast<int32_t>(kZapValue))); | 119 mov(scratch, Immediate(BitCast<int32_t>(kZapValue))); |
| 125 } | 120 } |
| 126 } | 121 } |
| 127 | 122 |
| 128 | 123 |
| 129 void MacroAssembler::RecordWrite(Register object, | 124 void MacroAssembler::RecordWrite(Register object, |
| 130 Register address, | 125 Register address, |
| 131 Register value) { | 126 Register value) { |
| 132 // The compiled code assumes that record write doesn't change the | |
| 133 // context register, so we check that none of the clobbered | |
| 134 // registers are esi. | |
| 135 ASSERT(!object.is(esi) && !value.is(esi) && !address.is(esi)); | |
| 136 | |
| 137 // First, check if a write barrier is even needed. The tests below | 127 // First, check if a write barrier is even needed. The tests below |
| 138 // catch stores of Smis and stores into young gen. | 128 // catch stores of Smis and stores into young gen. |
| 139 Label done; | 129 Label done; |
| 140 | 130 |
| 141 // Skip barrier if writing a smi. | 131 // Skip barrier if writing a smi. |
| 142 ASSERT_EQ(0, kSmiTag); | 132 ASSERT_EQ(0, kSmiTag); |
| 143 test(value, Immediate(kSmiTagMask)); | 133 test(value, Immediate(kSmiTagMask)); |
| 144 j(zero, &done); | 134 j(zero, &done); |
| 145 | 135 |
| 146 InNewSpace(object, value, equal, &done); | 136 InNewSpace(object, value, equal, &done); |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 } | 443 } |
| 454 | 444 |
| 455 | 445 |
| 456 void MacroAssembler::PopTryHandler() { | 446 void MacroAssembler::PopTryHandler() { |
| 457 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 447 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); |
| 458 pop(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address))); | 448 pop(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address))); |
| 459 add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); | 449 add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); |
| 460 } | 450 } |
| 461 | 451 |
| 462 | 452 |
| 453 void MacroAssembler::Throw(Register value) { |
| 454 // Adjust this code if not the case. |
| 455 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 456 |
| 457 // eax must hold the exception. |
| 458 if (!value.is(eax)) { |
| 459 mov(eax, value); |
| 460 } |
| 461 |
| 462 // Drop the sp to the top of the handler. |
| 463 ExternalReference handler_address(Isolate::k_handler_address); |
| 464 mov(esp, Operand::StaticVariable(handler_address)); |
| 465 |
| 466 // Restore next handler and frame pointer, discard handler state. |
| 467 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 468 pop(Operand::StaticVariable(handler_address)); |
| 469 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); |
| 470 pop(ebp); |
| 471 pop(edx); // Remove state. |
| 472 |
| 473 // Before returning we restore the context from the frame pointer if |
| 474 // not NULL. The frame pointer is NULL in the exception handler of |
| 475 // a JS entry frame. |
| 476 Set(esi, Immediate(0)); // Tentatively set context pointer to NULL. |
| 477 NearLabel skip; |
| 478 cmp(ebp, 0); |
| 479 j(equal, &skip, not_taken); |
| 480 mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 481 bind(&skip); |
| 482 |
| 483 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 484 ret(0); |
| 485 } |
| 486 |
| 487 |
| 488 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
| 489 Register value) { |
| 490 // Adjust this code if not the case. |
| 491 STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 492 |
| 493 // eax must hold the exception. |
| 494 if (!value.is(eax)) { |
| 495 mov(eax, value); |
| 496 } |
| 497 |
| 498 // Drop sp to the top stack handler. |
| 499 ExternalReference handler_address(Isolate::k_handler_address); |
| 500 mov(esp, Operand::StaticVariable(handler_address)); |
| 501 |
| 502 // Unwind the handlers until the ENTRY handler is found. |
| 503 NearLabel loop, done; |
| 504 bind(&loop); |
| 505 // Load the type of the current stack handler. |
| 506 const int kStateOffset = StackHandlerConstants::kStateOffset; |
| 507 cmp(Operand(esp, kStateOffset), Immediate(StackHandler::ENTRY)); |
| 508 j(equal, &done); |
| 509 // Fetch the next handler in the list. |
| 510 const int kNextOffset = StackHandlerConstants::kNextOffset; |
| 511 mov(esp, Operand(esp, kNextOffset)); |
| 512 jmp(&loop); |
| 513 bind(&done); |
| 514 |
| 515 // Set the top handler address to next handler past the current ENTRY handler. |
| 516 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 517 pop(Operand::StaticVariable(handler_address)); |
| 518 |
| 519 if (type == OUT_OF_MEMORY) { |
| 520 // Set external caught exception to false. |
| 521 ExternalReference external_caught( |
| 522 Isolate::k_external_caught_exception_address); |
| 523 mov(eax, false); |
| 524 mov(Operand::StaticVariable(external_caught), eax); |
| 525 |
| 526 // Set pending exception and eax to out of memory exception. |
| 527 ExternalReference pending_exception(Isolate::k_pending_exception_address); |
| 528 mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); |
| 529 mov(Operand::StaticVariable(pending_exception), eax); |
| 530 } |
| 531 |
| 532 // Clear the context pointer. |
| 533 Set(esi, Immediate(0)); |
| 534 |
| 535 // Restore fp from handler and discard handler state. |
| 536 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 1 * kPointerSize); |
| 537 pop(ebp); |
| 538 pop(edx); // State. |
| 539 |
| 540 STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| 541 ret(0); |
| 542 } |
| 543 |
| 544 |
| 463 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 545 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 464 Register scratch, | 546 Register scratch, |
| 465 Label* miss) { | 547 Label* miss) { |
| 466 Label same_contexts; | 548 Label same_contexts; |
| 467 | 549 |
| 468 ASSERT(!holder_reg.is(scratch)); | 550 ASSERT(!holder_reg.is(scratch)); |
| 469 | 551 |
| 470 // Load current lexical context from the stack frame. | 552 // Load current lexical context from the stack frame. |
| 471 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); | 553 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 472 | 554 |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 ExternalReference(fid), num_arguments, result_size); | 1280 ExternalReference(fid), num_arguments, result_size); |
| 1199 } | 1281 } |
| 1200 | 1282 |
| 1201 | 1283 |
| 1202 // If true, a Handle<T> returned by value from a function with cdecl calling | 1284 // If true, a Handle<T> returned by value from a function with cdecl calling |
| 1203 // convention will be returned directly as a value of location_ field in a | 1285 // convention will be returned directly as a value of location_ field in a |
| 1204 // register eax. | 1286 // register eax. |
| 1205 // If false, it is returned as a pointer to a preallocated by caller memory | 1287 // If false, it is returned as a pointer to a preallocated by caller memory |
| 1206 // region. Pointer to this region should be passed to a function as an | 1288 // region. Pointer to this region should be passed to a function as an |
| 1207 // implicit first argument. | 1289 // implicit first argument. |
| 1208 #if defined(USING_BSD_ABI) || defined(__MINGW32__) | 1290 #if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__) |
| 1209 static const bool kReturnHandlesDirectly = true; | 1291 static const bool kReturnHandlesDirectly = true; |
| 1210 #else | 1292 #else |
| 1211 static const bool kReturnHandlesDirectly = false; | 1293 static const bool kReturnHandlesDirectly = false; |
| 1212 #endif | 1294 #endif |
| 1213 | 1295 |
| 1214 | 1296 |
| 1215 Operand ApiParameterOperand(int index) { | 1297 Operand ApiParameterOperand(int index) { |
| 1216 return Operand( | 1298 return Operand( |
| 1217 esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize); | 1299 esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize); |
| 1218 } | 1300 } |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 Label ok, fail; | 1653 Label ok, fail; |
| 1572 CheckMap(map, FACTORY->meta_map(), &fail, false); | 1654 CheckMap(map, FACTORY->meta_map(), &fail, false); |
| 1573 jmp(&ok); | 1655 jmp(&ok); |
| 1574 bind(&fail); | 1656 bind(&fail); |
| 1575 Abort("Global functions must have initial map"); | 1657 Abort("Global functions must have initial map"); |
| 1576 bind(&ok); | 1658 bind(&ok); |
| 1577 } | 1659 } |
| 1578 } | 1660 } |
| 1579 | 1661 |
| 1580 | 1662 |
| 1663 // Store the value in register src in the safepoint register stack |
| 1664 // slot for register dst. |
| 1665 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { |
| 1666 mov(SafepointRegisterSlot(dst), src); |
| 1667 } |
| 1668 |
| 1669 |
| 1670 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) { |
| 1671 mov(SafepointRegisterSlot(dst), src); |
| 1672 } |
| 1673 |
| 1674 |
| 1675 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { |
| 1676 mov(dst, SafepointRegisterSlot(src)); |
| 1677 } |
| 1678 |
| 1679 |
| 1680 Operand MacroAssembler::SafepointRegisterSlot(Register reg) { |
| 1681 return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); |
| 1682 } |
| 1683 |
| 1684 |
| 1581 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { | 1685 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { |
| 1582 // The registers are pushed starting with the lowest encoding, | 1686 // The registers are pushed starting with the lowest encoding, |
| 1583 // which means that lowest encodings are furthest away from | 1687 // which means that lowest encodings are furthest away from |
| 1584 // the stack pointer. | 1688 // the stack pointer. |
| 1585 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); | 1689 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); |
| 1586 return kNumSafepointRegisters - reg_code - 1; | 1690 return kNumSafepointRegisters - reg_code - 1; |
| 1587 } | 1691 } |
| 1588 | 1692 |
| 1589 | 1693 |
| 1590 void MacroAssembler::Ret() { | 1694 void MacroAssembler::Ret() { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1932 | 2036 |
| 1933 // Check that the code was patched as expected. | 2037 // Check that the code was patched as expected. |
| 1934 ASSERT(masm_.pc_ == address_ + size_); | 2038 ASSERT(masm_.pc_ == address_ + size_); |
| 1935 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2039 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 1936 } | 2040 } |
| 1937 | 2041 |
| 1938 | 2042 |
| 1939 } } // namespace v8::internal | 2043 } } // namespace v8::internal |
| 1940 | 2044 |
| 1941 #endif // V8_TARGET_ARCH_IA32 | 2045 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |