| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 : Assembler(buffer, size), | 45 : Assembler(buffer, size), |
| 46 generating_stub_(false), | 46 generating_stub_(false), |
| 47 allow_stub_calls_(true), | 47 allow_stub_calls_(true), |
| 48 code_object_(HEAP->undefined_value()) { | 48 code_object_(HEAP->undefined_value()) { |
| 49 } | 49 } |
| 50 | 50 |
| 51 | 51 |
| 52 void MacroAssembler::RecordWriteHelper(Register object, | 52 void MacroAssembler::RecordWriteHelper(Register object, |
| 53 Register addr, | 53 Register addr, |
| 54 Register scratch) { | 54 Register scratch) { |
| 55 if (FLAG_debug_code) { | 55 if (emit_debug_code()) { |
| 56 // Check that the object is not in new space. | 56 // Check that the object is not in new space. |
| 57 Label not_in_new_space; | 57 Label not_in_new_space; |
| 58 InNewSpace(object, scratch, not_equal, ¬_in_new_space); | 58 InNewSpace(object, scratch, not_equal, ¬_in_new_space); |
| 59 Abort("new-space object passed to RecordWriteHelper"); | 59 Abort("new-space object passed to RecordWriteHelper"); |
| 60 bind(¬_in_new_space); | 60 bind(¬_in_new_space); |
| 61 } | 61 } |
| 62 | 62 |
| 63 // Compute the page start address from the heap object pointer, and reuse | 63 // Compute the page start address from the heap object pointer, and reuse |
| 64 // the 'object' register for it. | 64 // the 'object' register for it. |
| 65 and_(object, ~Page::kPageAlignmentMask); | 65 and_(object, ~Page::kPageAlignmentMask); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 ASSERT_EQ(0, kSmiTag); | 106 ASSERT_EQ(0, kSmiTag); |
| 107 lea(dst, Operand(object, dst, times_half_pointer_size, | 107 lea(dst, Operand(object, dst, times_half_pointer_size, |
| 108 FixedArray::kHeaderSize - kHeapObjectTag)); | 108 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 109 } | 109 } |
| 110 RecordWriteHelper(object, dst, value); | 110 RecordWriteHelper(object, dst, value); |
| 111 | 111 |
| 112 bind(&done); | 112 bind(&done); |
| 113 | 113 |
| 114 // Clobber all input registers when running with the debug-code flag | 114 // Clobber all input registers when running with the debug-code flag |
| 115 // turned on to provoke errors. | 115 // turned on to provoke errors. |
| 116 if (FLAG_debug_code) { | 116 if (emit_debug_code()) { |
| 117 mov(object, Immediate(BitCast<int32_t>(kZapValue))); | 117 mov(object, Immediate(BitCast<int32_t>(kZapValue))); |
| 118 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 118 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
| 119 mov(scratch, Immediate(BitCast<int32_t>(kZapValue))); | 119 mov(scratch, Immediate(BitCast<int32_t>(kZapValue))); |
| 120 } | 120 } |
| 121 } | 121 } |
| 122 | 122 |
| 123 | 123 |
| 124 void MacroAssembler::RecordWrite(Register object, | 124 void MacroAssembler::RecordWrite(Register object, |
| 125 Register address, | 125 Register address, |
| 126 Register value) { | 126 Register value) { |
| 127 // 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 |
| 128 // catch stores of Smis and stores into young gen. | 128 // catch stores of Smis and stores into young gen. |
| 129 Label done; | 129 Label done; |
| 130 | 130 |
| 131 // Skip barrier if writing a smi. | 131 // Skip barrier if writing a smi. |
| 132 ASSERT_EQ(0, kSmiTag); | 132 ASSERT_EQ(0, kSmiTag); |
| 133 test(value, Immediate(kSmiTagMask)); | 133 test(value, Immediate(kSmiTagMask)); |
| 134 j(zero, &done); | 134 j(zero, &done); |
| 135 | 135 |
| 136 InNewSpace(object, value, equal, &done); | 136 InNewSpace(object, value, equal, &done); |
| 137 | 137 |
| 138 RecordWriteHelper(object, address, value); | 138 RecordWriteHelper(object, address, value); |
| 139 | 139 |
| 140 bind(&done); | 140 bind(&done); |
| 141 | 141 |
| 142 // Clobber all input registers when running with the debug-code flag | 142 // Clobber all input registers when running with the debug-code flag |
| 143 // turned on to provoke errors. | 143 // turned on to provoke errors. |
| 144 if (FLAG_debug_code) { | 144 if (emit_debug_code()) { |
| 145 mov(object, Immediate(BitCast<int32_t>(kZapValue))); | 145 mov(object, Immediate(BitCast<int32_t>(kZapValue))); |
| 146 mov(address, Immediate(BitCast<int32_t>(kZapValue))); | 146 mov(address, Immediate(BitCast<int32_t>(kZapValue))); |
| 147 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 147 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 | 150 |
| 151 | 151 |
| 152 #ifdef ENABLE_DEBUGGER_SUPPORT | 152 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 153 void MacroAssembler::DebugBreak() { | 153 void MacroAssembler::DebugBreak() { |
| 154 Set(eax, Immediate(0)); | 154 Set(eax, Immediate(0)); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 Assert(not_equal, "Operand is a smi"); | 278 Assert(not_equal, "Operand is a smi"); |
| 279 } | 279 } |
| 280 | 280 |
| 281 | 281 |
| 282 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 282 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 283 push(ebp); | 283 push(ebp); |
| 284 mov(ebp, Operand(esp)); | 284 mov(ebp, Operand(esp)); |
| 285 push(esi); | 285 push(esi); |
| 286 push(Immediate(Smi::FromInt(type))); | 286 push(Immediate(Smi::FromInt(type))); |
| 287 push(Immediate(CodeObject())); | 287 push(Immediate(CodeObject())); |
| 288 if (FLAG_debug_code) { | 288 if (emit_debug_code()) { |
| 289 cmp(Operand(esp, 0), Immediate(FACTORY->undefined_value())); | 289 cmp(Operand(esp, 0), Immediate(FACTORY->undefined_value())); |
| 290 Check(not_equal, "code object not properly patched"); | 290 Check(not_equal, "code object not properly patched"); |
| 291 } | 291 } |
| 292 } | 292 } |
| 293 | 293 |
| 294 | 294 |
| 295 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 295 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 296 if (FLAG_debug_code) { | 296 if (emit_debug_code()) { |
| 297 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 297 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), |
| 298 Immediate(Smi::FromInt(type))); | 298 Immediate(Smi::FromInt(type))); |
| 299 Check(equal, "stack frame types must match"); | 299 Check(equal, "stack frame types must match"); |
| 300 } | 300 } |
| 301 leave(); | 301 leave(); |
| 302 } | 302 } |
| 303 | 303 |
| 304 | 304 |
| 305 void MacroAssembler::EnterExitFramePrologue() { | 305 void MacroAssembler::EnterExitFramePrologue() { |
| 306 // Setup the frame structure on the stack. | 306 // Setup the frame structure on the stack. |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 Register scratch, | 546 Register scratch, |
| 547 Label* miss) { | 547 Label* miss) { |
| 548 Label same_contexts; | 548 Label same_contexts; |
| 549 | 549 |
| 550 ASSERT(!holder_reg.is(scratch)); | 550 ASSERT(!holder_reg.is(scratch)); |
| 551 | 551 |
| 552 // Load current lexical context from the stack frame. | 552 // Load current lexical context from the stack frame. |
| 553 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); | 553 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 554 | 554 |
| 555 // When generating debug code, make sure the lexical context is set. | 555 // When generating debug code, make sure the lexical context is set. |
| 556 if (FLAG_debug_code) { | 556 if (emit_debug_code()) { |
| 557 cmp(Operand(scratch), Immediate(0)); | 557 cmp(Operand(scratch), Immediate(0)); |
| 558 Check(not_equal, "we should not have an empty lexical context"); | 558 Check(not_equal, "we should not have an empty lexical context"); |
| 559 } | 559 } |
| 560 // Load the global context of the current context. | 560 // Load the global context of the current context. |
| 561 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 561 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| 562 mov(scratch, FieldOperand(scratch, offset)); | 562 mov(scratch, FieldOperand(scratch, offset)); |
| 563 mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); | 563 mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); |
| 564 | 564 |
| 565 // Check the context is a global context. | 565 // Check the context is a global context. |
| 566 if (FLAG_debug_code) { | 566 if (emit_debug_code()) { |
| 567 push(scratch); | 567 push(scratch); |
| 568 // Read the first word and compare to global_context_map. | 568 // Read the first word and compare to global_context_map. |
| 569 mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 569 mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 570 cmp(scratch, FACTORY->global_context_map()); | 570 cmp(scratch, FACTORY->global_context_map()); |
| 571 Check(equal, "JSGlobalObject::global_context should be a global context."); | 571 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 572 pop(scratch); | 572 pop(scratch); |
| 573 } | 573 } |
| 574 | 574 |
| 575 // Check if both contexts are the same. | 575 // Check if both contexts are the same. |
| 576 cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 576 cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 577 j(equal, &same_contexts, taken); | 577 j(equal, &same_contexts, taken); |
| 578 | 578 |
| 579 // Compare security tokens, save holder_reg on the stack so we can use it | 579 // Compare security tokens, save holder_reg on the stack so we can use it |
| 580 // as a temporary register. | 580 // as a temporary register. |
| 581 // | 581 // |
| 582 // TODO(119): avoid push(holder_reg)/pop(holder_reg) | 582 // TODO(119): avoid push(holder_reg)/pop(holder_reg) |
| 583 push(holder_reg); | 583 push(holder_reg); |
| 584 // Check that the security token in the calling global object is | 584 // Check that the security token in the calling global object is |
| 585 // compatible with the security token in the receiving global | 585 // compatible with the security token in the receiving global |
| 586 // object. | 586 // object. |
| 587 mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 587 mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 588 | 588 |
| 589 // Check the context is a global context. | 589 // Check the context is a global context. |
| 590 if (FLAG_debug_code) { | 590 if (emit_debug_code()) { |
| 591 cmp(holder_reg, FACTORY->null_value()); | 591 cmp(holder_reg, FACTORY->null_value()); |
| 592 Check(not_equal, "JSGlobalProxy::context() should not be null."); | 592 Check(not_equal, "JSGlobalProxy::context() should not be null."); |
| 593 | 593 |
| 594 push(holder_reg); | 594 push(holder_reg); |
| 595 // Read the first word and compare to global_context_map(), | 595 // Read the first word and compare to global_context_map(), |
| 596 mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); | 596 mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); |
| 597 cmp(holder_reg, FACTORY->global_context_map()); | 597 cmp(holder_reg, FACTORY->global_context_map()); |
| 598 Check(equal, "JSGlobalObject::global_context should be a global context."); | 598 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 599 pop(holder_reg); | 599 pop(holder_reg); |
| 600 } | 600 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 mov(result, Operand::StaticVariable(new_space_allocation_top)); | 633 mov(result, Operand::StaticVariable(new_space_allocation_top)); |
| 634 } else { | 634 } else { |
| 635 mov(Operand(scratch), Immediate(new_space_allocation_top)); | 635 mov(Operand(scratch), Immediate(new_space_allocation_top)); |
| 636 mov(result, Operand(scratch, 0)); | 636 mov(result, Operand(scratch, 0)); |
| 637 } | 637 } |
| 638 } | 638 } |
| 639 | 639 |
| 640 | 640 |
| 641 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 641 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 642 Register scratch) { | 642 Register scratch) { |
| 643 if (FLAG_debug_code) { | 643 if (emit_debug_code()) { |
| 644 test(result_end, Immediate(kObjectAlignmentMask)); | 644 test(result_end, Immediate(kObjectAlignmentMask)); |
| 645 Check(zero, "Unaligned allocation in new space"); | 645 Check(zero, "Unaligned allocation in new space"); |
| 646 } | 646 } |
| 647 | 647 |
| 648 ExternalReference new_space_allocation_top = | 648 ExternalReference new_space_allocation_top = |
| 649 ExternalReference::new_space_allocation_top_address(); | 649 ExternalReference::new_space_allocation_top_address(); |
| 650 | 650 |
| 651 // Update new top. Use scratch if available. | 651 // Update new top. Use scratch if available. |
| 652 if (scratch.is(no_reg)) { | 652 if (scratch.is(no_reg)) { |
| 653 mov(Operand::StaticVariable(new_space_allocation_top), result_end); | 653 mov(Operand::StaticVariable(new_space_allocation_top), result_end); |
| 654 } else { | 654 } else { |
| 655 mov(Operand(scratch, 0), result_end); | 655 mov(Operand(scratch, 0), result_end); |
| 656 } | 656 } |
| 657 } | 657 } |
| 658 | 658 |
| 659 | 659 |
| 660 void MacroAssembler::AllocateInNewSpace(int object_size, | 660 void MacroAssembler::AllocateInNewSpace(int object_size, |
| 661 Register result, | 661 Register result, |
| 662 Register result_end, | 662 Register result_end, |
| 663 Register scratch, | 663 Register scratch, |
| 664 Label* gc_required, | 664 Label* gc_required, |
| 665 AllocationFlags flags) { | 665 AllocationFlags flags) { |
| 666 if (!FLAG_inline_new) { | 666 if (!FLAG_inline_new) { |
| 667 if (FLAG_debug_code) { | 667 if (emit_debug_code()) { |
| 668 // Trash the registers to simulate an allocation failure. | 668 // Trash the registers to simulate an allocation failure. |
| 669 mov(result, Immediate(0x7091)); | 669 mov(result, Immediate(0x7091)); |
| 670 if (result_end.is_valid()) { | 670 if (result_end.is_valid()) { |
| 671 mov(result_end, Immediate(0x7191)); | 671 mov(result_end, Immediate(0x7191)); |
| 672 } | 672 } |
| 673 if (scratch.is_valid()) { | 673 if (scratch.is_valid()) { |
| 674 mov(scratch, Immediate(0x7291)); | 674 mov(scratch, Immediate(0x7291)); |
| 675 } | 675 } |
| 676 } | 676 } |
| 677 jmp(gc_required); | 677 jmp(gc_required); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 | 714 |
| 715 void MacroAssembler::AllocateInNewSpace(int header_size, | 715 void MacroAssembler::AllocateInNewSpace(int header_size, |
| 716 ScaleFactor element_size, | 716 ScaleFactor element_size, |
| 717 Register element_count, | 717 Register element_count, |
| 718 Register result, | 718 Register result, |
| 719 Register result_end, | 719 Register result_end, |
| 720 Register scratch, | 720 Register scratch, |
| 721 Label* gc_required, | 721 Label* gc_required, |
| 722 AllocationFlags flags) { | 722 AllocationFlags flags) { |
| 723 if (!FLAG_inline_new) { | 723 if (!FLAG_inline_new) { |
| 724 if (FLAG_debug_code) { | 724 if (emit_debug_code()) { |
| 725 // Trash the registers to simulate an allocation failure. | 725 // Trash the registers to simulate an allocation failure. |
| 726 mov(result, Immediate(0x7091)); | 726 mov(result, Immediate(0x7091)); |
| 727 mov(result_end, Immediate(0x7191)); | 727 mov(result_end, Immediate(0x7191)); |
| 728 if (scratch.is_valid()) { | 728 if (scratch.is_valid()) { |
| 729 mov(scratch, Immediate(0x7291)); | 729 mov(scratch, Immediate(0x7291)); |
| 730 } | 730 } |
| 731 // Register element_count is not modified by the function. | 731 // Register element_count is not modified by the function. |
| 732 } | 732 } |
| 733 jmp(gc_required); | 733 jmp(gc_required); |
| 734 return; | 734 return; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 760 } | 760 } |
| 761 | 761 |
| 762 | 762 |
| 763 void MacroAssembler::AllocateInNewSpace(Register object_size, | 763 void MacroAssembler::AllocateInNewSpace(Register object_size, |
| 764 Register result, | 764 Register result, |
| 765 Register result_end, | 765 Register result_end, |
| 766 Register scratch, | 766 Register scratch, |
| 767 Label* gc_required, | 767 Label* gc_required, |
| 768 AllocationFlags flags) { | 768 AllocationFlags flags) { |
| 769 if (!FLAG_inline_new) { | 769 if (!FLAG_inline_new) { |
| 770 if (FLAG_debug_code) { | 770 if (emit_debug_code()) { |
| 771 // Trash the registers to simulate an allocation failure. | 771 // Trash the registers to simulate an allocation failure. |
| 772 mov(result, Immediate(0x7091)); | 772 mov(result, Immediate(0x7091)); |
| 773 mov(result_end, Immediate(0x7191)); | 773 mov(result_end, Immediate(0x7191)); |
| 774 if (scratch.is_valid()) { | 774 if (scratch.is_valid()) { |
| 775 mov(scratch, Immediate(0x7291)); | 775 mov(scratch, Immediate(0x7291)); |
| 776 } | 776 } |
| 777 // object_size is left unchanged by this function. | 777 // object_size is left unchanged by this function. |
| 778 } | 778 } |
| 779 jmp(gc_required); | 779 jmp(gc_required); |
| 780 return; | 780 return; |
| (...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 // 1: arg1 | 1317 // 1: arg1 |
| 1318 // 0: pointer to the output cell | 1318 // 0: pointer to the output cell |
| 1319 // | 1319 // |
| 1320 // Note that this is one more "argument" than the function expects | 1320 // Note that this is one more "argument" than the function expects |
| 1321 // so the out cell will have to be popped explicitly after returning | 1321 // so the out cell will have to be popped explicitly after returning |
| 1322 // from the function. The out cell contains Handle. | 1322 // from the function. The out cell contains Handle. |
| 1323 | 1323 |
| 1324 // pointer to out cell. | 1324 // pointer to out cell. |
| 1325 lea(scratch, Operand(esp, (argc + 1) * kPointerSize)); | 1325 lea(scratch, Operand(esp, (argc + 1) * kPointerSize)); |
| 1326 mov(Operand(esp, 0 * kPointerSize), scratch); // output. | 1326 mov(Operand(esp, 0 * kPointerSize), scratch); // output. |
| 1327 if (FLAG_debug_code) { | 1327 if (emit_debug_code()) { |
| 1328 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. | 1328 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. |
| 1329 } | 1329 } |
| 1330 } | 1330 } |
| 1331 } | 1331 } |
| 1332 | 1332 |
| 1333 | 1333 |
| 1334 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, | 1334 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, |
| 1335 int stack_space) { | 1335 int stack_space) { |
| 1336 ExternalReference next_address = | 1336 ExternalReference next_address = |
| 1337 ExternalReference::handle_scope_next_address(); | 1337 ExternalReference::handle_scope_next_address(); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1620 // Slot is in the current function context. Move it into the | 1620 // Slot is in the current function context. Move it into the |
| 1621 // destination register in case we store into it (the write barrier | 1621 // destination register in case we store into it (the write barrier |
| 1622 // cannot be allowed to destroy the context in esi). | 1622 // cannot be allowed to destroy the context in esi). |
| 1623 mov(dst, esi); | 1623 mov(dst, esi); |
| 1624 } | 1624 } |
| 1625 | 1625 |
| 1626 // We should not have found a 'with' context by walking the context chain | 1626 // We should not have found a 'with' context by walking the context chain |
| 1627 // (i.e., the static scope chain and runtime context chain do not agree). | 1627 // (i.e., the static scope chain and runtime context chain do not agree). |
| 1628 // A variable occurring in such a scope should have slot type LOOKUP and | 1628 // A variable occurring in such a scope should have slot type LOOKUP and |
| 1629 // not CONTEXT. | 1629 // not CONTEXT. |
| 1630 if (FLAG_debug_code) { | 1630 if (emit_debug_code()) { |
| 1631 cmp(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); | 1631 cmp(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 1632 Check(equal, "Yo dawg, I heard you liked function contexts " | 1632 Check(equal, "Yo dawg, I heard you liked function contexts " |
| 1633 "so I put function contexts in all your contexts"); | 1633 "so I put function contexts in all your contexts"); |
| 1634 } | 1634 } |
| 1635 } | 1635 } |
| 1636 | 1636 |
| 1637 | 1637 |
| 1638 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 1638 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 1639 // Load the global or builtins object from the current context. | 1639 // Load the global or builtins object from the current context. |
| 1640 mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 1640 mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 1641 // Load the global context from the global or builtins object. | 1641 // Load the global context from the global or builtins object. |
| 1642 mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); | 1642 mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); |
| 1643 // Load the function from the global context. | 1643 // Load the function from the global context. |
| 1644 mov(function, Operand(function, Context::SlotOffset(index))); | 1644 mov(function, Operand(function, Context::SlotOffset(index))); |
| 1645 } | 1645 } |
| 1646 | 1646 |
| 1647 | 1647 |
| 1648 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 1648 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 1649 Register map) { | 1649 Register map) { |
| 1650 // Load the initial map. The global functions all have initial maps. | 1650 // Load the initial map. The global functions all have initial maps. |
| 1651 mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 1651 mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 1652 if (FLAG_debug_code) { | 1652 if (emit_debug_code()) { |
| 1653 Label ok, fail; | 1653 Label ok, fail; |
| 1654 CheckMap(map, FACTORY->meta_map(), &fail, false); | 1654 CheckMap(map, FACTORY->meta_map(), &fail, false); |
| 1655 jmp(&ok); | 1655 jmp(&ok); |
| 1656 bind(&fail); | 1656 bind(&fail); |
| 1657 Abort("Global functions must have initial map"); | 1657 Abort("Global functions must have initial map"); |
| 1658 bind(&ok); | 1658 bind(&ok); |
| 1659 } | 1659 } |
| 1660 } | 1660 } |
| 1661 | 1661 |
| 1662 | 1662 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1786 j(NegateCondition(cc), &skip); | 1786 j(NegateCondition(cc), &skip); |
| 1787 pushfd(); | 1787 pushfd(); |
| 1788 DecrementCounter(counter, value); | 1788 DecrementCounter(counter, value); |
| 1789 popfd(); | 1789 popfd(); |
| 1790 bind(&skip); | 1790 bind(&skip); |
| 1791 } | 1791 } |
| 1792 } | 1792 } |
| 1793 | 1793 |
| 1794 | 1794 |
| 1795 void MacroAssembler::Assert(Condition cc, const char* msg) { | 1795 void MacroAssembler::Assert(Condition cc, const char* msg) { |
| 1796 if (FLAG_debug_code) Check(cc, msg); | 1796 if (emit_debug_code()) Check(cc, msg); |
| 1797 } | 1797 } |
| 1798 | 1798 |
| 1799 | 1799 |
| 1800 void MacroAssembler::AssertFastElements(Register elements) { | 1800 void MacroAssembler::AssertFastElements(Register elements) { |
| 1801 if (FLAG_debug_code) { | 1801 if (emit_debug_code()) { |
| 1802 Label ok; | 1802 Label ok; |
| 1803 cmp(FieldOperand(elements, HeapObject::kMapOffset), | 1803 cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 1804 Immediate(FACTORY->fixed_array_map())); | 1804 Immediate(FACTORY->fixed_array_map())); |
| 1805 j(equal, &ok); | 1805 j(equal, &ok); |
| 1806 cmp(FieldOperand(elements, HeapObject::kMapOffset), | 1806 cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 1807 Immediate(FACTORY->fixed_cow_array_map())); | 1807 Immediate(FACTORY->fixed_cow_array_map())); |
| 1808 j(equal, &ok); | 1808 j(equal, &ok); |
| 1809 Abort("JSObject with fast elements map has slow elements"); | 1809 Abort("JSObject with fast elements map has slow elements"); |
| 1810 bind(&ok); | 1810 bind(&ok); |
| 1811 } | 1811 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1859 push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); | 1859 push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); |
| 1860 CallRuntime(Runtime::kAbort, 2); | 1860 CallRuntime(Runtime::kAbort, 2); |
| 1861 // will not return here | 1861 // will not return here |
| 1862 int3(); | 1862 int3(); |
| 1863 } | 1863 } |
| 1864 | 1864 |
| 1865 | 1865 |
| 1866 void MacroAssembler::JumpIfNotNumber(Register reg, | 1866 void MacroAssembler::JumpIfNotNumber(Register reg, |
| 1867 TypeInfo info, | 1867 TypeInfo info, |
| 1868 Label* on_not_number) { | 1868 Label* on_not_number) { |
| 1869 if (FLAG_debug_code) AbortIfSmi(reg); | 1869 if (emit_debug_code()) AbortIfSmi(reg); |
| 1870 if (!info.IsNumber()) { | 1870 if (!info.IsNumber()) { |
| 1871 cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1871 cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1872 FACTORY->heap_number_map()); | 1872 FACTORY->heap_number_map()); |
| 1873 j(not_equal, on_not_number); | 1873 j(not_equal, on_not_number); |
| 1874 } | 1874 } |
| 1875 } | 1875 } |
| 1876 | 1876 |
| 1877 | 1877 |
| 1878 void MacroAssembler::ConvertToInt32(Register dst, | 1878 void MacroAssembler::ConvertToInt32(Register dst, |
| 1879 Register source, | 1879 Register source, |
| 1880 Register scratch, | 1880 Register scratch, |
| 1881 TypeInfo info, | 1881 TypeInfo info, |
| 1882 Label* on_not_int32) { | 1882 Label* on_not_int32) { |
| 1883 if (FLAG_debug_code) { | 1883 if (emit_debug_code()) { |
| 1884 AbortIfSmi(source); | 1884 AbortIfSmi(source); |
| 1885 AbortIfNotNumber(source); | 1885 AbortIfNotNumber(source); |
| 1886 } | 1886 } |
| 1887 if (info.IsInteger32()) { | 1887 if (info.IsInteger32()) { |
| 1888 cvttsd2si(dst, FieldOperand(source, HeapNumber::kValueOffset)); | 1888 cvttsd2si(dst, FieldOperand(source, HeapNumber::kValueOffset)); |
| 1889 } else { | 1889 } else { |
| 1890 Label done; | 1890 Label done; |
| 1891 bool push_pop = (scratch.is(no_reg) && dst.is(source)); | 1891 bool push_pop = (scratch.is(no_reg) && dst.is(source)); |
| 1892 ASSERT(!scratch.is(source)); | 1892 ASSERT(!scratch.is(source)); |
| 1893 if (push_pop) { | 1893 if (push_pop) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 | 2001 |
| 2002 | 2002 |
| 2003 void MacroAssembler::CallCFunction(Register function, | 2003 void MacroAssembler::CallCFunction(Register function, |
| 2004 int num_arguments) { | 2004 int num_arguments) { |
| 2005 // Pass current isolate address as additional parameter. | 2005 // Pass current isolate address as additional parameter. |
| 2006 mov(Operand(esp, num_arguments * kPointerSize), | 2006 mov(Operand(esp, num_arguments * kPointerSize), |
| 2007 Immediate(ExternalReference::isolate_address())); | 2007 Immediate(ExternalReference::isolate_address())); |
| 2008 num_arguments += 1; | 2008 num_arguments += 1; |
| 2009 | 2009 |
| 2010 // Check stack alignment. | 2010 // Check stack alignment. |
| 2011 if (FLAG_debug_code) { | 2011 if (emit_debug_code()) { |
| 2012 CheckStackAlignment(); | 2012 CheckStackAlignment(); |
| 2013 } | 2013 } |
| 2014 | 2014 |
| 2015 call(Operand(function)); | 2015 call(Operand(function)); |
| 2016 if (OS::ActivationFrameAlignment() != 0) { | 2016 if (OS::ActivationFrameAlignment() != 0) { |
| 2017 mov(esp, Operand(esp, num_arguments * kPointerSize)); | 2017 mov(esp, Operand(esp, num_arguments * kPointerSize)); |
| 2018 } else { | 2018 } else { |
| 2019 add(Operand(esp), Immediate(num_arguments * sizeof(int32_t))); | 2019 add(Operand(esp), Immediate(num_arguments * sizeof(int32_t))); |
| 2020 } | 2020 } |
| 2021 } | 2021 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2036 | 2036 |
| 2037 // Check that the code was patched as expected. | 2037 // Check that the code was patched as expected. |
| 2038 ASSERT(masm_.pc_ == address_ + size_); | 2038 ASSERT(masm_.pc_ == address_ + size_); |
| 2039 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2039 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 2040 } | 2040 } |
| 2041 | 2041 |
| 2042 | 2042 |
| 2043 } } // namespace v8::internal | 2043 } } // namespace v8::internal |
| 2044 | 2044 |
| 2045 #endif // V8_TARGET_ARCH_IA32 | 2045 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |