| 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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 bind(&done); | 113 bind(&done); |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 | 117 |
| 118 | 118 |
| 119 void MacroAssembler::RecordWriteHelper(Register object, | 119 void MacroAssembler::RecordWriteHelper(Register object, |
| 120 Register addr, | 120 Register addr, |
| 121 Register scratch, | 121 Register scratch, |
| 122 SaveFPRegsMode save_fp) { | 122 SaveFPRegsMode save_fp) { |
| 123 if (FLAG_debug_code) { | 123 if (emit_debug_code()) { |
| 124 // Check that the object is not in new space. | 124 // Check that the object is not in new space. |
| 125 Label not_in_new_space; | 125 Label not_in_new_space; |
| 126 InNewSpace(object, scratch, not_equal, ¬_in_new_space); | 126 InNewSpace(object, scratch, not_equal, ¬_in_new_space); |
| 127 Abort("new-space object passed to RecordWriteHelper"); | 127 Abort("new-space object passed to RecordWriteHelper"); |
| 128 bind(¬_in_new_space); | 128 bind(¬_in_new_space); |
| 129 } | 129 } |
| 130 | 130 |
| 131 // Load store buffer top. | 131 // Load store buffer top. |
| 132 ExternalReference store_buffer = ExternalReference::store_buffer_top(); | 132 ExternalReference store_buffer = ExternalReference::store_buffer_top(); |
| 133 mov(scratch, Operand::StaticVariable(store_buffer)); | 133 mov(scratch, Operand::StaticVariable(store_buffer)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 ASSERT_EQ(0, kSmiTag); | 191 ASSERT_EQ(0, kSmiTag); |
| 192 lea(dst, Operand(object, dst, times_half_pointer_size, | 192 lea(dst, Operand(object, dst, times_half_pointer_size, |
| 193 FixedArray::kHeaderSize - kHeapObjectTag)); | 193 FixedArray::kHeaderSize - kHeapObjectTag)); |
| 194 } | 194 } |
| 195 RecordWriteHelper(object, dst, value, save_fp); | 195 RecordWriteHelper(object, dst, value, save_fp); |
| 196 | 196 |
| 197 bind(&done); | 197 bind(&done); |
| 198 | 198 |
| 199 // Clobber all input registers when running with the debug-code flag | 199 // Clobber all input registers when running with the debug-code flag |
| 200 // turned on to provoke errors. | 200 // turned on to provoke errors. |
| 201 if (FLAG_debug_code) { | 201 if (emit_debug_code()) { |
| 202 mov(object, Immediate(BitCast<int32_t>(kZapValue))); | 202 mov(object, Immediate(BitCast<int32_t>(kZapValue))); |
| 203 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 203 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
| 204 mov(scratch, Immediate(BitCast<int32_t>(kZapValue))); | 204 mov(scratch, Immediate(BitCast<int32_t>(kZapValue))); |
| 205 } | 205 } |
| 206 } | 206 } |
| 207 | 207 |
| 208 | 208 |
| 209 void MacroAssembler::RecordWrite(Register object, | 209 void MacroAssembler::RecordWrite(Register object, |
| 210 Register address, | 210 Register address, |
| 211 Register value, | 211 Register value, |
| 212 SaveFPRegsMode save_fp) { | 212 SaveFPRegsMode save_fp) { |
| 213 // First, check if a write barrier is even needed. The tests below | 213 // First, check if a write barrier is even needed. The tests below |
| 214 // catch stores of Smis and stores into young gen. | 214 // catch stores of Smis and stores into young gen. |
| 215 Label done; | 215 Label done; |
| 216 | 216 |
| 217 // Skip barrier if writing a smi. | 217 // Skip barrier if writing a smi. |
| 218 ASSERT_EQ(0, kSmiTag); | 218 ASSERT_EQ(0, kSmiTag); |
| 219 test(value, Immediate(kSmiTagMask)); | 219 test(value, Immediate(kSmiTagMask)); |
| 220 j(zero, &done); | 220 j(zero, &done); |
| 221 | 221 |
| 222 InNewSpace(object, value, equal, &done); | 222 InNewSpace(object, value, equal, &done); |
| 223 | 223 |
| 224 RecordWriteHelper(object, address, value, save_fp); | 224 RecordWriteHelper(object, address, value, save_fp); |
| 225 | 225 |
| 226 bind(&done); | 226 bind(&done); |
| 227 | 227 |
| 228 // Clobber all input registers when running with the debug-code flag | 228 // Clobber all input registers when running with the debug-code flag |
| 229 // turned on to provoke errors. | 229 // turned on to provoke errors. |
| 230 if (FLAG_debug_code) { | 230 if (emit_debug_code()) { |
| 231 mov(object, Immediate(BitCast<int32_t>(kZapValue))); | 231 mov(object, Immediate(BitCast<int32_t>(kZapValue))); |
| 232 mov(address, Immediate(BitCast<int32_t>(kZapValue))); | 232 mov(address, Immediate(BitCast<int32_t>(kZapValue))); |
| 233 mov(value, Immediate(BitCast<int32_t>(kZapValue))); | 233 mov(value, Immediate(BitCast<int32_t>(kZapValue))); |
| 234 } | 234 } |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 #ifdef ENABLE_DEBUGGER_SUPPORT | 238 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 239 void MacroAssembler::DebugBreak() { | 239 void MacroAssembler::DebugBreak() { |
| 240 Set(eax, Immediate(0)); | 240 Set(eax, Immediate(0)); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 Assert(not_equal, "Operand is a smi"); | 364 Assert(not_equal, "Operand is a smi"); |
| 365 } | 365 } |
| 366 | 366 |
| 367 | 367 |
| 368 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 368 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 369 push(ebp); | 369 push(ebp); |
| 370 mov(ebp, Operand(esp)); | 370 mov(ebp, Operand(esp)); |
| 371 push(esi); | 371 push(esi); |
| 372 push(Immediate(Smi::FromInt(type))); | 372 push(Immediate(Smi::FromInt(type))); |
| 373 push(Immediate(CodeObject())); | 373 push(Immediate(CodeObject())); |
| 374 if (FLAG_debug_code) { | 374 if (emit_debug_code()) { |
| 375 cmp(Operand(esp, 0), Immediate(Factory::undefined_value())); | 375 cmp(Operand(esp, 0), Immediate(Factory::undefined_value())); |
| 376 Check(not_equal, "code object not properly patched"); | 376 Check(not_equal, "code object not properly patched"); |
| 377 } | 377 } |
| 378 } | 378 } |
| 379 | 379 |
| 380 | 380 |
| 381 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 381 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 382 if (FLAG_debug_code) { | 382 if (emit_debug_code()) { |
| 383 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 383 cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), |
| 384 Immediate(Smi::FromInt(type))); | 384 Immediate(Smi::FromInt(type))); |
| 385 Check(equal, "stack frame types must match"); | 385 Check(equal, "stack frame types must match"); |
| 386 } | 386 } |
| 387 leave(); | 387 leave(); |
| 388 } | 388 } |
| 389 | 389 |
| 390 | 390 |
| 391 void MacroAssembler::EnterExitFramePrologue() { | 391 void MacroAssembler::EnterExitFramePrologue() { |
| 392 // Setup the frame structure on the stack. | 392 // Setup the frame structure on the stack. |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 Register scratch, | 629 Register scratch, |
| 630 Label* miss) { | 630 Label* miss) { |
| 631 Label same_contexts; | 631 Label same_contexts; |
| 632 | 632 |
| 633 ASSERT(!holder_reg.is(scratch)); | 633 ASSERT(!holder_reg.is(scratch)); |
| 634 | 634 |
| 635 // Load current lexical context from the stack frame. | 635 // Load current lexical context from the stack frame. |
| 636 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); | 636 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 637 | 637 |
| 638 // When generating debug code, make sure the lexical context is set. | 638 // When generating debug code, make sure the lexical context is set. |
| 639 if (FLAG_debug_code) { | 639 if (emit_debug_code()) { |
| 640 cmp(Operand(scratch), Immediate(0)); | 640 cmp(Operand(scratch), Immediate(0)); |
| 641 Check(not_equal, "we should not have an empty lexical context"); | 641 Check(not_equal, "we should not have an empty lexical context"); |
| 642 } | 642 } |
| 643 // Load the global context of the current context. | 643 // Load the global context of the current context. |
| 644 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 644 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| 645 mov(scratch, FieldOperand(scratch, offset)); | 645 mov(scratch, FieldOperand(scratch, offset)); |
| 646 mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); | 646 mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); |
| 647 | 647 |
| 648 // Check the context is a global context. | 648 // Check the context is a global context. |
| 649 if (FLAG_debug_code) { | 649 if (emit_debug_code()) { |
| 650 push(scratch); | 650 push(scratch); |
| 651 // Read the first word and compare to global_context_map. | 651 // Read the first word and compare to global_context_map. |
| 652 mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 652 mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 653 cmp(scratch, Factory::global_context_map()); | 653 cmp(scratch, Factory::global_context_map()); |
| 654 Check(equal, "JSGlobalObject::global_context should be a global context."); | 654 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 655 pop(scratch); | 655 pop(scratch); |
| 656 } | 656 } |
| 657 | 657 |
| 658 // Check if both contexts are the same. | 658 // Check if both contexts are the same. |
| 659 cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 659 cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 660 j(equal, &same_contexts, taken); | 660 j(equal, &same_contexts, taken); |
| 661 | 661 |
| 662 // Compare security tokens, save holder_reg on the stack so we can use it | 662 // Compare security tokens, save holder_reg on the stack so we can use it |
| 663 // as a temporary register. | 663 // as a temporary register. |
| 664 // | 664 // |
| 665 // TODO(119): avoid push(holder_reg)/pop(holder_reg) | 665 // TODO(119): avoid push(holder_reg)/pop(holder_reg) |
| 666 push(holder_reg); | 666 push(holder_reg); |
| 667 // Check that the security token in the calling global object is | 667 // Check that the security token in the calling global object is |
| 668 // compatible with the security token in the receiving global | 668 // compatible with the security token in the receiving global |
| 669 // object. | 669 // object. |
| 670 mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 670 mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 671 | 671 |
| 672 // Check the context is a global context. | 672 // Check the context is a global context. |
| 673 if (FLAG_debug_code) { | 673 if (emit_debug_code()) { |
| 674 cmp(holder_reg, Factory::null_value()); | 674 cmp(holder_reg, Factory::null_value()); |
| 675 Check(not_equal, "JSGlobalProxy::context() should not be null."); | 675 Check(not_equal, "JSGlobalProxy::context() should not be null."); |
| 676 | 676 |
| 677 push(holder_reg); | 677 push(holder_reg); |
| 678 // Read the first word and compare to global_context_map(), | 678 // Read the first word and compare to global_context_map(), |
| 679 mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); | 679 mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); |
| 680 cmp(holder_reg, Factory::global_context_map()); | 680 cmp(holder_reg, Factory::global_context_map()); |
| 681 Check(equal, "JSGlobalObject::global_context should be a global context."); | 681 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 682 pop(holder_reg); | 682 pop(holder_reg); |
| 683 } | 683 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 mov(result, Operand::StaticVariable(new_space_allocation_top)); | 716 mov(result, Operand::StaticVariable(new_space_allocation_top)); |
| 717 } else { | 717 } else { |
| 718 mov(Operand(scratch), Immediate(new_space_allocation_top)); | 718 mov(Operand(scratch), Immediate(new_space_allocation_top)); |
| 719 mov(result, Operand(scratch, 0)); | 719 mov(result, Operand(scratch, 0)); |
| 720 } | 720 } |
| 721 } | 721 } |
| 722 | 722 |
| 723 | 723 |
| 724 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 724 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 725 Register scratch) { | 725 Register scratch) { |
| 726 if (FLAG_debug_code) { | 726 if (emit_debug_code()) { |
| 727 test(result_end, Immediate(kObjectAlignmentMask)); | 727 test(result_end, Immediate(kObjectAlignmentMask)); |
| 728 Check(zero, "Unaligned allocation in new space"); | 728 Check(zero, "Unaligned allocation in new space"); |
| 729 } | 729 } |
| 730 | 730 |
| 731 ExternalReference new_space_allocation_top = | 731 ExternalReference new_space_allocation_top = |
| 732 ExternalReference::new_space_allocation_top_address(); | 732 ExternalReference::new_space_allocation_top_address(); |
| 733 | 733 |
| 734 // Update new top. Use scratch if available. | 734 // Update new top. Use scratch if available. |
| 735 if (scratch.is(no_reg)) { | 735 if (scratch.is(no_reg)) { |
| 736 mov(Operand::StaticVariable(new_space_allocation_top), result_end); | 736 mov(Operand::StaticVariable(new_space_allocation_top), result_end); |
| 737 } else { | 737 } else { |
| 738 mov(Operand(scratch, 0), result_end); | 738 mov(Operand(scratch, 0), result_end); |
| 739 } | 739 } |
| 740 } | 740 } |
| 741 | 741 |
| 742 | 742 |
| 743 void MacroAssembler::AllocateInNewSpace(int object_size, | 743 void MacroAssembler::AllocateInNewSpace(int object_size, |
| 744 Register result, | 744 Register result, |
| 745 Register result_end, | 745 Register result_end, |
| 746 Register scratch, | 746 Register scratch, |
| 747 Label* gc_required, | 747 Label* gc_required, |
| 748 AllocationFlags flags) { | 748 AllocationFlags flags) { |
| 749 if (!FLAG_inline_new) { | 749 if (!FLAG_inline_new) { |
| 750 if (FLAG_debug_code) { | 750 if (emit_debug_code()) { |
| 751 // Trash the registers to simulate an allocation failure. | 751 // Trash the registers to simulate an allocation failure. |
| 752 mov(result, Immediate(0x7091)); | 752 mov(result, Immediate(0x7091)); |
| 753 if (result_end.is_valid()) { | 753 if (result_end.is_valid()) { |
| 754 mov(result_end, Immediate(0x7191)); | 754 mov(result_end, Immediate(0x7191)); |
| 755 } | 755 } |
| 756 if (scratch.is_valid()) { | 756 if (scratch.is_valid()) { |
| 757 mov(scratch, Immediate(0x7291)); | 757 mov(scratch, Immediate(0x7291)); |
| 758 } | 758 } |
| 759 } | 759 } |
| 760 jmp(gc_required); | 760 jmp(gc_required); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 | 797 |
| 798 void MacroAssembler::AllocateInNewSpace(int header_size, | 798 void MacroAssembler::AllocateInNewSpace(int header_size, |
| 799 ScaleFactor element_size, | 799 ScaleFactor element_size, |
| 800 Register element_count, | 800 Register element_count, |
| 801 Register result, | 801 Register result, |
| 802 Register result_end, | 802 Register result_end, |
| 803 Register scratch, | 803 Register scratch, |
| 804 Label* gc_required, | 804 Label* gc_required, |
| 805 AllocationFlags flags) { | 805 AllocationFlags flags) { |
| 806 if (!FLAG_inline_new) { | 806 if (!FLAG_inline_new) { |
| 807 if (FLAG_debug_code) { | 807 if (emit_debug_code()) { |
| 808 // Trash the registers to simulate an allocation failure. | 808 // Trash the registers to simulate an allocation failure. |
| 809 mov(result, Immediate(0x7091)); | 809 mov(result, Immediate(0x7091)); |
| 810 mov(result_end, Immediate(0x7191)); | 810 mov(result_end, Immediate(0x7191)); |
| 811 if (scratch.is_valid()) { | 811 if (scratch.is_valid()) { |
| 812 mov(scratch, Immediate(0x7291)); | 812 mov(scratch, Immediate(0x7291)); |
| 813 } | 813 } |
| 814 // Register element_count is not modified by the function. | 814 // Register element_count is not modified by the function. |
| 815 } | 815 } |
| 816 jmp(gc_required); | 816 jmp(gc_required); |
| 817 return; | 817 return; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 843 } | 843 } |
| 844 | 844 |
| 845 | 845 |
| 846 void MacroAssembler::AllocateInNewSpace(Register object_size, | 846 void MacroAssembler::AllocateInNewSpace(Register object_size, |
| 847 Register result, | 847 Register result, |
| 848 Register result_end, | 848 Register result_end, |
| 849 Register scratch, | 849 Register scratch, |
| 850 Label* gc_required, | 850 Label* gc_required, |
| 851 AllocationFlags flags) { | 851 AllocationFlags flags) { |
| 852 if (!FLAG_inline_new) { | 852 if (!FLAG_inline_new) { |
| 853 if (FLAG_debug_code) { | 853 if (emit_debug_code()) { |
| 854 // Trash the registers to simulate an allocation failure. | 854 // Trash the registers to simulate an allocation failure. |
| 855 mov(result, Immediate(0x7091)); | 855 mov(result, Immediate(0x7091)); |
| 856 mov(result_end, Immediate(0x7191)); | 856 mov(result_end, Immediate(0x7191)); |
| 857 if (scratch.is_valid()) { | 857 if (scratch.is_valid()) { |
| 858 mov(scratch, Immediate(0x7291)); | 858 mov(scratch, Immediate(0x7291)); |
| 859 } | 859 } |
| 860 // object_size is left unchanged by this function. | 860 // object_size is left unchanged by this function. |
| 861 } | 861 } |
| 862 jmp(gc_required); | 862 jmp(gc_required); |
| 863 return; | 863 return; |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 ExternalReference(fid), num_arguments, result_size); | 1361 ExternalReference(fid), num_arguments, result_size); |
| 1362 } | 1362 } |
| 1363 | 1363 |
| 1364 | 1364 |
| 1365 // If true, a Handle<T> returned by value from a function with cdecl calling | 1365 // If true, a Handle<T> returned by value from a function with cdecl calling |
| 1366 // convention will be returned directly as a value of location_ field in a | 1366 // convention will be returned directly as a value of location_ field in a |
| 1367 // register eax. | 1367 // register eax. |
| 1368 // If false, it is returned as a pointer to a preallocated by caller memory | 1368 // If false, it is returned as a pointer to a preallocated by caller memory |
| 1369 // region. Pointer to this region should be passed to a function as an | 1369 // region. Pointer to this region should be passed to a function as an |
| 1370 // implicit first argument. | 1370 // implicit first argument. |
| 1371 #if defined(USING_BSD_ABI) || defined(__MINGW32__) | 1371 #if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__) |
| 1372 static const bool kReturnHandlesDirectly = true; | 1372 static const bool kReturnHandlesDirectly = true; |
| 1373 #else | 1373 #else |
| 1374 static const bool kReturnHandlesDirectly = false; | 1374 static const bool kReturnHandlesDirectly = false; |
| 1375 #endif | 1375 #endif |
| 1376 | 1376 |
| 1377 | 1377 |
| 1378 Operand ApiParameterOperand(int index) { | 1378 Operand ApiParameterOperand(int index) { |
| 1379 return Operand( | 1379 return Operand( |
| 1380 esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize); | 1380 esp, (index + (kReturnHandlesDirectly ? 0 : 1)) * kPointerSize); |
| 1381 } | 1381 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1398 // 1: arg1 | 1398 // 1: arg1 |
| 1399 // 0: pointer to the output cell | 1399 // 0: pointer to the output cell |
| 1400 // | 1400 // |
| 1401 // Note that this is one more "argument" than the function expects | 1401 // Note that this is one more "argument" than the function expects |
| 1402 // so the out cell will have to be popped explicitly after returning | 1402 // so the out cell will have to be popped explicitly after returning |
| 1403 // from the function. The out cell contains Handle. | 1403 // from the function. The out cell contains Handle. |
| 1404 | 1404 |
| 1405 // pointer to out cell. | 1405 // pointer to out cell. |
| 1406 lea(scratch, Operand(esp, (argc + 1) * kPointerSize)); | 1406 lea(scratch, Operand(esp, (argc + 1) * kPointerSize)); |
| 1407 mov(Operand(esp, 0 * kPointerSize), scratch); // output. | 1407 mov(Operand(esp, 0 * kPointerSize), scratch); // output. |
| 1408 if (FLAG_debug_code) { | 1408 if (emit_debug_code()) { |
| 1409 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. | 1409 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. |
| 1410 } | 1410 } |
| 1411 } | 1411 } |
| 1412 } | 1412 } |
| 1413 | 1413 |
| 1414 | 1414 |
| 1415 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, | 1415 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, |
| 1416 int stack_space) { | 1416 int stack_space) { |
| 1417 ExternalReference next_address = | 1417 ExternalReference next_address = |
| 1418 ExternalReference::handle_scope_next_address(); | 1418 ExternalReference::handle_scope_next_address(); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1502 mov(ebx, Immediate(ext)); | 1502 mov(ebx, Immediate(ext)); |
| 1503 CEntryStub ces(1); | 1503 CEntryStub ces(1); |
| 1504 return TryTailCallStub(&ces); | 1504 return TryTailCallStub(&ces); |
| 1505 } | 1505 } |
| 1506 | 1506 |
| 1507 | 1507 |
| 1508 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1508 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
| 1509 const ParameterCount& actual, | 1509 const ParameterCount& actual, |
| 1510 Handle<Code> code_constant, | 1510 Handle<Code> code_constant, |
| 1511 const Operand& code_operand, | 1511 const Operand& code_operand, |
| 1512 Label* done, | 1512 NearLabel* done, |
| 1513 InvokeFlag flag, | 1513 InvokeFlag flag, |
| 1514 PostCallGenerator* post_call_generator) { | 1514 PostCallGenerator* post_call_generator) { |
| 1515 bool definitely_matches = false; | 1515 bool definitely_matches = false; |
| 1516 Label invoke; | 1516 Label invoke; |
| 1517 if (expected.is_immediate()) { | 1517 if (expected.is_immediate()) { |
| 1518 ASSERT(actual.is_immediate()); | 1518 ASSERT(actual.is_immediate()); |
| 1519 if (expected.immediate() == actual.immediate()) { | 1519 if (expected.immediate() == actual.immediate()) { |
| 1520 definitely_matches = true; | 1520 definitely_matches = true; |
| 1521 } else { | 1521 } else { |
| 1522 mov(eax, actual.immediate()); | 1522 mov(eax, actual.immediate()); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1570 bind(&invoke); | 1570 bind(&invoke); |
| 1571 } | 1571 } |
| 1572 } | 1572 } |
| 1573 | 1573 |
| 1574 | 1574 |
| 1575 void MacroAssembler::InvokeCode(const Operand& code, | 1575 void MacroAssembler::InvokeCode(const Operand& code, |
| 1576 const ParameterCount& expected, | 1576 const ParameterCount& expected, |
| 1577 const ParameterCount& actual, | 1577 const ParameterCount& actual, |
| 1578 InvokeFlag flag, | 1578 InvokeFlag flag, |
| 1579 PostCallGenerator* post_call_generator) { | 1579 PostCallGenerator* post_call_generator) { |
| 1580 Label done; | 1580 NearLabel done; |
| 1581 InvokePrologue(expected, actual, Handle<Code>::null(), code, | 1581 InvokePrologue(expected, actual, Handle<Code>::null(), code, |
| 1582 &done, flag, post_call_generator); | 1582 &done, flag, post_call_generator); |
| 1583 if (flag == CALL_FUNCTION) { | 1583 if (flag == CALL_FUNCTION) { |
| 1584 call(code); | 1584 call(code); |
| 1585 if (post_call_generator != NULL) post_call_generator->Generate(); | 1585 if (post_call_generator != NULL) post_call_generator->Generate(); |
| 1586 } else { | 1586 } else { |
| 1587 ASSERT(flag == JUMP_FUNCTION); | 1587 ASSERT(flag == JUMP_FUNCTION); |
| 1588 jmp(code); | 1588 jmp(code); |
| 1589 } | 1589 } |
| 1590 bind(&done); | 1590 bind(&done); |
| 1591 } | 1591 } |
| 1592 | 1592 |
| 1593 | 1593 |
| 1594 void MacroAssembler::InvokeCode(Handle<Code> code, | 1594 void MacroAssembler::InvokeCode(Handle<Code> code, |
| 1595 const ParameterCount& expected, | 1595 const ParameterCount& expected, |
| 1596 const ParameterCount& actual, | 1596 const ParameterCount& actual, |
| 1597 RelocInfo::Mode rmode, | 1597 RelocInfo::Mode rmode, |
| 1598 InvokeFlag flag, | 1598 InvokeFlag flag, |
| 1599 PostCallGenerator* post_call_generator) { | 1599 PostCallGenerator* post_call_generator) { |
| 1600 Label done; | 1600 NearLabel done; |
| 1601 Operand dummy(eax); | 1601 Operand dummy(eax); |
| 1602 InvokePrologue(expected, actual, code, dummy, &done, | 1602 InvokePrologue(expected, actual, code, dummy, &done, |
| 1603 flag, post_call_generator); | 1603 flag, post_call_generator); |
| 1604 if (flag == CALL_FUNCTION) { | 1604 if (flag == CALL_FUNCTION) { |
| 1605 call(code, rmode); | 1605 call(code, rmode); |
| 1606 if (post_call_generator != NULL) post_call_generator->Generate(); | 1606 if (post_call_generator != NULL) post_call_generator->Generate(); |
| 1607 } else { | 1607 } else { |
| 1608 ASSERT(flag == JUMP_FUNCTION); | 1608 ASSERT(flag == JUMP_FUNCTION); |
| 1609 jmp(code, rmode); | 1609 jmp(code, rmode); |
| 1610 } | 1610 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 // Slot is in the current function context. Move it into the | 1699 // Slot is in the current function context. Move it into the |
| 1700 // destination register in case we store into it (the write barrier | 1700 // destination register in case we store into it (the write barrier |
| 1701 // cannot be allowed to destroy the context in esi). | 1701 // cannot be allowed to destroy the context in esi). |
| 1702 mov(dst, esi); | 1702 mov(dst, esi); |
| 1703 } | 1703 } |
| 1704 | 1704 |
| 1705 // We should not have found a 'with' context by walking the context chain | 1705 // We should not have found a 'with' context by walking the context chain |
| 1706 // (i.e., the static scope chain and runtime context chain do not agree). | 1706 // (i.e., the static scope chain and runtime context chain do not agree). |
| 1707 // A variable occurring in such a scope should have slot type LOOKUP and | 1707 // A variable occurring in such a scope should have slot type LOOKUP and |
| 1708 // not CONTEXT. | 1708 // not CONTEXT. |
| 1709 if (FLAG_debug_code) { | 1709 if (emit_debug_code()) { |
| 1710 cmp(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); | 1710 cmp(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 1711 Check(equal, "Yo dawg, I heard you liked function contexts " | 1711 Check(equal, "Yo dawg, I heard you liked function contexts " |
| 1712 "so I put function contexts in all your contexts"); | 1712 "so I put function contexts in all your contexts"); |
| 1713 } | 1713 } |
| 1714 } | 1714 } |
| 1715 | 1715 |
| 1716 | 1716 |
| 1717 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 1717 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 1718 // Load the global or builtins object from the current context. | 1718 // Load the global or builtins object from the current context. |
| 1719 mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 1719 mov(function, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 1720 // Load the global context from the global or builtins object. | 1720 // Load the global context from the global or builtins object. |
| 1721 mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); | 1721 mov(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); |
| 1722 // Load the function from the global context. | 1722 // Load the function from the global context. |
| 1723 mov(function, Operand(function, Context::SlotOffset(index))); | 1723 mov(function, Operand(function, Context::SlotOffset(index))); |
| 1724 } | 1724 } |
| 1725 | 1725 |
| 1726 | 1726 |
| 1727 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 1727 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 1728 Register map) { | 1728 Register map) { |
| 1729 // Load the initial map. The global functions all have initial maps. | 1729 // Load the initial map. The global functions all have initial maps. |
| 1730 mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 1730 mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 1731 if (FLAG_debug_code) { | 1731 if (emit_debug_code()) { |
| 1732 Label ok, fail; | 1732 Label ok, fail; |
| 1733 CheckMap(map, Factory::meta_map(), &fail, false); | 1733 CheckMap(map, Factory::meta_map(), &fail, false); |
| 1734 jmp(&ok); | 1734 jmp(&ok); |
| 1735 bind(&fail); | 1735 bind(&fail); |
| 1736 Abort("Global functions must have initial map"); | 1736 Abort("Global functions must have initial map"); |
| 1737 bind(&ok); | 1737 bind(&ok); |
| 1738 } | 1738 } |
| 1739 } | 1739 } |
| 1740 | 1740 |
| 1741 | 1741 |
| 1742 // Store the value in register src in the safepoint register stack |
| 1743 // slot for register dst. |
| 1744 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Register src) { |
| 1745 mov(SafepointRegisterSlot(dst), src); |
| 1746 } |
| 1747 |
| 1748 |
| 1749 void MacroAssembler::StoreToSafepointRegisterSlot(Register dst, Immediate src) { |
| 1750 mov(SafepointRegisterSlot(dst), src); |
| 1751 } |
| 1752 |
| 1753 |
| 1754 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { |
| 1755 mov(dst, SafepointRegisterSlot(src)); |
| 1756 } |
| 1757 |
| 1758 |
| 1759 Operand MacroAssembler::SafepointRegisterSlot(Register reg) { |
| 1760 return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); |
| 1761 } |
| 1762 |
| 1763 |
| 1742 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { | 1764 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { |
| 1743 // The registers are pushed starting with the lowest encoding, | 1765 // The registers are pushed starting with the lowest encoding, |
| 1744 // which means that lowest encodings are furthest away from | 1766 // which means that lowest encodings are furthest away from |
| 1745 // the stack pointer. | 1767 // the stack pointer. |
| 1746 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); | 1768 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); |
| 1747 return kNumSafepointRegisters - reg_code - 1; | 1769 return kNumSafepointRegisters - reg_code - 1; |
| 1748 } | 1770 } |
| 1749 | 1771 |
| 1750 | 1772 |
| 1751 void MacroAssembler::Ret() { | 1773 void MacroAssembler::Ret() { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1843 j(NegateCondition(cc), &skip); | 1865 j(NegateCondition(cc), &skip); |
| 1844 pushfd(); | 1866 pushfd(); |
| 1845 DecrementCounter(counter, value); | 1867 DecrementCounter(counter, value); |
| 1846 popfd(); | 1868 popfd(); |
| 1847 bind(&skip); | 1869 bind(&skip); |
| 1848 } | 1870 } |
| 1849 } | 1871 } |
| 1850 | 1872 |
| 1851 | 1873 |
| 1852 void MacroAssembler::Assert(Condition cc, const char* msg) { | 1874 void MacroAssembler::Assert(Condition cc, const char* msg) { |
| 1853 if (FLAG_debug_code) Check(cc, msg); | 1875 if (emit_debug_code()) Check(cc, msg); |
| 1854 } | 1876 } |
| 1855 | 1877 |
| 1856 | 1878 |
| 1857 void MacroAssembler::AssertFastElements(Register elements) { | 1879 void MacroAssembler::AssertFastElements(Register elements) { |
| 1858 if (FLAG_debug_code) { | 1880 if (emit_debug_code()) { |
| 1859 Label ok; | 1881 Label ok; |
| 1860 cmp(FieldOperand(elements, HeapObject::kMapOffset), | 1882 cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 1861 Immediate(Factory::fixed_array_map())); | 1883 Immediate(Factory::fixed_array_map())); |
| 1862 j(equal, &ok); | 1884 j(equal, &ok); |
| 1863 cmp(FieldOperand(elements, HeapObject::kMapOffset), | 1885 cmp(FieldOperand(elements, HeapObject::kMapOffset), |
| 1864 Immediate(Factory::fixed_cow_array_map())); | 1886 Immediate(Factory::fixed_cow_array_map())); |
| 1865 j(equal, &ok); | 1887 j(equal, &ok); |
| 1866 Abort("JSObject with fast elements map has slow elements"); | 1888 Abort("JSObject with fast elements map has slow elements"); |
| 1867 bind(&ok); | 1889 bind(&ok); |
| 1868 } | 1890 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1916 push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); | 1938 push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); |
| 1917 CallRuntime(Runtime::kAbort, 2); | 1939 CallRuntime(Runtime::kAbort, 2); |
| 1918 // will not return here | 1940 // will not return here |
| 1919 int3(); | 1941 int3(); |
| 1920 } | 1942 } |
| 1921 | 1943 |
| 1922 | 1944 |
| 1923 void MacroAssembler::JumpIfNotNumber(Register reg, | 1945 void MacroAssembler::JumpIfNotNumber(Register reg, |
| 1924 TypeInfo info, | 1946 TypeInfo info, |
| 1925 Label* on_not_number) { | 1947 Label* on_not_number) { |
| 1926 if (FLAG_debug_code) AbortIfSmi(reg); | 1948 if (emit_debug_code()) AbortIfSmi(reg); |
| 1927 if (!info.IsNumber()) { | 1949 if (!info.IsNumber()) { |
| 1928 cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1950 cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1929 Factory::heap_number_map()); | 1951 Factory::heap_number_map()); |
| 1930 j(not_equal, on_not_number); | 1952 j(not_equal, on_not_number); |
| 1931 } | 1953 } |
| 1932 } | 1954 } |
| 1933 | 1955 |
| 1934 | 1956 |
| 1935 void MacroAssembler::ConvertToInt32(Register dst, | 1957 void MacroAssembler::ConvertToInt32(Register dst, |
| 1936 Register source, | 1958 Register source, |
| 1937 Register scratch, | 1959 Register scratch, |
| 1938 TypeInfo info, | 1960 TypeInfo info, |
| 1939 Label* on_not_int32) { | 1961 Label* on_not_int32) { |
| 1940 if (FLAG_debug_code) { | 1962 if (emit_debug_code()) { |
| 1941 AbortIfSmi(source); | 1963 AbortIfSmi(source); |
| 1942 AbortIfNotNumber(source); | 1964 AbortIfNotNumber(source); |
| 1943 } | 1965 } |
| 1944 if (info.IsInteger32()) { | 1966 if (info.IsInteger32()) { |
| 1945 cvttsd2si(dst, FieldOperand(source, HeapNumber::kValueOffset)); | 1967 cvttsd2si(dst, FieldOperand(source, HeapNumber::kValueOffset)); |
| 1946 } else { | 1968 } else { |
| 1947 Label done; | 1969 Label done; |
| 1948 bool push_pop = (scratch.is(no_reg) && dst.is(source)); | 1970 bool push_pop = (scratch.is(no_reg) && dst.is(source)); |
| 1949 ASSERT(!scratch.is(source)); | 1971 ASSERT(!scratch.is(source)); |
| 1950 if (push_pop) { | 1972 if (push_pop) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2050 int num_arguments) { | 2072 int num_arguments) { |
| 2051 // Trashing eax is ok as it will be the return value. | 2073 // Trashing eax is ok as it will be the return value. |
| 2052 mov(Operand(eax), Immediate(function)); | 2074 mov(Operand(eax), Immediate(function)); |
| 2053 CallCFunction(eax, num_arguments); | 2075 CallCFunction(eax, num_arguments); |
| 2054 } | 2076 } |
| 2055 | 2077 |
| 2056 | 2078 |
| 2057 void MacroAssembler::CallCFunction(Register function, | 2079 void MacroAssembler::CallCFunction(Register function, |
| 2058 int num_arguments) { | 2080 int num_arguments) { |
| 2059 // Check stack alignment. | 2081 // Check stack alignment. |
| 2060 if (FLAG_debug_code) { | 2082 if (emit_debug_code()) { |
| 2061 CheckStackAlignment(); | 2083 CheckStackAlignment(); |
| 2062 } | 2084 } |
| 2063 | 2085 |
| 2064 call(Operand(function)); | 2086 call(Operand(function)); |
| 2065 if (OS::ActivationFrameAlignment() != 0) { | 2087 if (OS::ActivationFrameAlignment() != 0) { |
| 2066 mov(esp, Operand(esp, num_arguments * kPointerSize)); | 2088 mov(esp, Operand(esp, num_arguments * kPointerSize)); |
| 2067 } else { | 2089 } else { |
| 2068 add(Operand(esp), Immediate(num_arguments * sizeof(int32_t))); | 2090 add(Operand(esp), Immediate(num_arguments * sizeof(int32_t))); |
| 2069 } | 2091 } |
| 2070 } | 2092 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2085 | 2107 |
| 2086 // Check that the code was patched as expected. | 2108 // Check that the code was patched as expected. |
| 2087 ASSERT(masm_.pc_ == address_ + size_); | 2109 ASSERT(masm_.pc_ == address_ + size_); |
| 2088 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2110 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 2089 } | 2111 } |
| 2090 | 2112 |
| 2091 | 2113 |
| 2092 } } // namespace v8::internal | 2114 } } // namespace v8::internal |
| 2093 | 2115 |
| 2094 #endif // V8_TARGET_ARCH_IA32 | 2116 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |