OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 // and may not have contained the exponent value in the first place when the | 610 // and may not have contained the exponent value in the first place when the |
611 // exponent is a smi. We reset it with exponent value before bailing out. | 611 // exponent is a smi. We reset it with exponent value before bailing out. |
612 __ j(not_equal, &done); | 612 __ j(not_equal, &done); |
613 __ Cvtsi2sd(double_exponent, exponent); | 613 __ Cvtsi2sd(double_exponent, exponent); |
614 | 614 |
615 // Returning or bailing out. | 615 // Returning or bailing out. |
616 Counters* counters = isolate()->counters(); | 616 Counters* counters = isolate()->counters(); |
617 if (exponent_type() == ON_STACK) { | 617 if (exponent_type() == ON_STACK) { |
618 // The arguments are still on the stack. | 618 // The arguments are still on the stack. |
619 __ bind(&call_runtime); | 619 __ bind(&call_runtime); |
620 __ TailCallRuntime(Runtime::kMathPowRT, 2); | 620 __ TailCallRuntime(Runtime::kMathPowRT); |
621 | 621 |
622 // The stub is called from non-optimized code, which expects the result | 622 // The stub is called from non-optimized code, which expects the result |
623 // as heap number in exponent. | 623 // as heap number in exponent. |
624 __ bind(&done); | 624 __ bind(&done); |
625 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); | 625 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); |
626 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), double_result); | 626 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), double_result); |
627 __ IncrementCounter(counters->math_pow(), 1); | 627 __ IncrementCounter(counters->math_pow(), 1); |
628 __ ret(2 * kPointerSize); | 628 __ ret(2 * kPointerSize); |
629 } else { | 629 } else { |
630 __ bind(&call_runtime); | 630 __ bind(&call_runtime); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 __ test(key, Immediate(kSmiTagMask | kSmiSignMask)); | 681 __ test(key, Immediate(kSmiTagMask | kSmiSignMask)); |
682 __ j(not_zero, &slow); | 682 __ j(not_zero, &slow); |
683 | 683 |
684 // Everything is fine, call runtime. | 684 // Everything is fine, call runtime. |
685 __ pop(scratch); | 685 __ pop(scratch); |
686 __ push(receiver); // receiver | 686 __ push(receiver); // receiver |
687 __ push(key); // key | 687 __ push(key); // key |
688 __ push(scratch); // return address | 688 __ push(scratch); // return address |
689 | 689 |
690 // Perform tail call to the entry. | 690 // Perform tail call to the entry. |
691 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2); | 691 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor); |
692 | 692 |
693 __ bind(&slow); | 693 __ bind(&slow); |
694 PropertyAccessCompiler::TailCallBuiltin( | 694 PropertyAccessCompiler::TailCallBuiltin( |
695 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 695 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
696 } | 696 } |
697 | 697 |
698 | 698 |
699 void LoadIndexedStringStub::Generate(MacroAssembler* masm) { | 699 void LoadIndexedStringStub::Generate(MacroAssembler* masm) { |
700 // Return address is on the stack. | 700 // Return address is on the stack. |
701 Label miss; | 701 Label miss; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 __ neg(edx); | 780 __ neg(edx); |
781 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); | 781 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); |
782 __ ret(0); | 782 __ ret(0); |
783 | 783 |
784 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 784 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
785 // by calling the runtime system. | 785 // by calling the runtime system. |
786 __ bind(&slow); | 786 __ bind(&slow); |
787 __ pop(ebx); // Return address. | 787 __ pop(ebx); // Return address. |
788 __ push(edx); | 788 __ push(edx); |
789 __ push(ebx); | 789 __ push(ebx); |
790 __ TailCallRuntime(Runtime::kArguments, 1); | 790 __ TailCallRuntime(Runtime::kArguments); |
791 } | 791 } |
792 | 792 |
793 | 793 |
794 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | 794 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { |
795 // ecx : number of parameters (tagged) | 795 // ecx : number of parameters (tagged) |
796 // edx : parameters pointer | 796 // edx : parameters pointer |
797 // edi : function | 797 // edi : function |
798 // esp[0] : return address | 798 // esp[0] : return address |
799 | 799 |
800 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | 800 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); |
(...skipping 11 matching lines...) Expand all Loading... |
812 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 812 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
813 __ lea(edx, | 813 __ lea(edx, |
814 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | 814 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); |
815 | 815 |
816 __ bind(&runtime); | 816 __ bind(&runtime); |
817 __ pop(eax); // Pop return address. | 817 __ pop(eax); // Pop return address. |
818 __ push(edi); // Push function. | 818 __ push(edi); // Push function. |
819 __ push(edx); // Push parameters pointer. | 819 __ push(edx); // Push parameters pointer. |
820 __ push(ecx); // Push parameter count. | 820 __ push(ecx); // Push parameter count. |
821 __ push(eax); // Push return address. | 821 __ push(eax); // Push return address. |
822 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); | 822 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
823 } | 823 } |
824 | 824 |
825 | 825 |
826 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | 826 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
827 // ecx : number of parameters (tagged) | 827 // ecx : number of parameters (tagged) |
828 // edx : parameters pointer | 828 // edx : parameters pointer |
829 // edi : function | 829 // edi : function |
830 // esp[0] : return address | 830 // esp[0] : return address |
831 | 831 |
832 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | 832 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 // Do the runtime call to allocate the arguments object. | 1047 // Do the runtime call to allocate the arguments object. |
1048 __ bind(&runtime); | 1048 __ bind(&runtime); |
1049 __ pop(eax); // Remove saved mapped parameter count. | 1049 __ pop(eax); // Remove saved mapped parameter count. |
1050 __ pop(edi); // Pop saved function. | 1050 __ pop(edi); // Pop saved function. |
1051 __ pop(eax); // Remove saved parameter count. | 1051 __ pop(eax); // Remove saved parameter count. |
1052 __ pop(eax); // Pop return address. | 1052 __ pop(eax); // Pop return address. |
1053 __ push(edi); // Push function. | 1053 __ push(edi); // Push function. |
1054 __ push(edx); // Push parameters pointer. | 1054 __ push(edx); // Push parameters pointer. |
1055 __ push(ecx); // Push parameter count. | 1055 __ push(ecx); // Push parameter count. |
1056 __ push(eax); // Push return address. | 1056 __ push(eax); // Push return address. |
1057 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); | 1057 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
1058 } | 1058 } |
1059 | 1059 |
1060 | 1060 |
1061 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | 1061 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
1062 // ecx : number of parameters (tagged) | 1062 // ecx : number of parameters (tagged) |
1063 // edx : parameters pointer | 1063 // edx : parameters pointer |
1064 // edi : function | 1064 // edi : function |
1065 // esp[0] : return address | 1065 // esp[0] : return address |
1066 | 1066 |
1067 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | 1067 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 __ bind(&done); | 1141 __ bind(&done); |
1142 __ ret(0); | 1142 __ ret(0); |
1143 | 1143 |
1144 // Do the runtime call to allocate the arguments object. | 1144 // Do the runtime call to allocate the arguments object. |
1145 __ bind(&runtime); | 1145 __ bind(&runtime); |
1146 __ pop(eax); // Pop return address. | 1146 __ pop(eax); // Pop return address. |
1147 __ push(edi); // Push function. | 1147 __ push(edi); // Push function. |
1148 __ push(edx); // Push parameters pointer. | 1148 __ push(edx); // Push parameters pointer. |
1149 __ push(ecx); // Push parameter count. | 1149 __ push(ecx); // Push parameter count. |
1150 __ push(eax); // Push return address. | 1150 __ push(eax); // Push return address. |
1151 __ TailCallRuntime(Runtime::kNewStrictArguments, 3); | 1151 __ TailCallRuntime(Runtime::kNewStrictArguments); |
1152 } | 1152 } |
1153 | 1153 |
1154 | 1154 |
1155 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) { | 1155 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) { |
1156 // esp[0] : return address | 1156 // esp[0] : return address |
1157 // esp[4] : language mode | 1157 // esp[4] : language mode |
1158 // esp[8] : index of rest parameter | 1158 // esp[8] : index of rest parameter |
1159 // esp[12] : number of parameters | 1159 // esp[12] : number of parameters |
1160 // esp[16] : receiver displacement | 1160 // esp[16] : receiver displacement |
1161 | 1161 |
1162 // Check if the calling frame is an arguments adaptor frame. | 1162 // Check if the calling frame is an arguments adaptor frame. |
1163 Label runtime; | 1163 Label runtime; |
1164 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 1164 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
1165 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | 1165 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); |
1166 __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1166 __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
1167 __ j(not_equal, &runtime); | 1167 __ j(not_equal, &runtime); |
1168 | 1168 |
1169 // Patch the arguments.length and the parameters pointer. | 1169 // Patch the arguments.length and the parameters pointer. |
1170 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 1170 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
1171 __ mov(Operand(esp, 3 * kPointerSize), ecx); | 1171 __ mov(Operand(esp, 3 * kPointerSize), ecx); |
1172 __ lea(edx, | 1172 __ lea(edx, |
1173 Operand(edx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | 1173 Operand(edx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); |
1174 __ mov(Operand(esp, 4 * kPointerSize), edx); | 1174 __ mov(Operand(esp, 4 * kPointerSize), edx); |
1175 | 1175 |
1176 __ bind(&runtime); | 1176 __ bind(&runtime); |
1177 __ TailCallRuntime(Runtime::kNewRestParam, 4); | 1177 __ TailCallRuntime(Runtime::kNewRestParam); |
1178 } | 1178 } |
1179 | 1179 |
1180 | 1180 |
1181 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1181 void RegExpExecStub::Generate(MacroAssembler* masm) { |
1182 // Just jump directly to runtime if native RegExp is not selected at compile | 1182 // Just jump directly to runtime if native RegExp is not selected at compile |
1183 // time or if regexp entry in generated code is turned off runtime switch or | 1183 // time or if regexp entry in generated code is turned off runtime switch or |
1184 // at compilation. | 1184 // at compilation. |
1185 #ifdef V8_INTERPRETED_REGEXP | 1185 #ifdef V8_INTERPRETED_REGEXP |
1186 __ TailCallRuntime(Runtime::kRegExpExec, 4); | 1186 __ TailCallRuntime(Runtime::kRegExpExec); |
1187 #else // V8_INTERPRETED_REGEXP | 1187 #else // V8_INTERPRETED_REGEXP |
1188 | 1188 |
1189 // Stack frame on entry. | 1189 // Stack frame on entry. |
1190 // esp[0]: return address | 1190 // esp[0]: return address |
1191 // esp[4]: last_match_info (expected JSArray) | 1191 // esp[4]: last_match_info (expected JSArray) |
1192 // esp[8]: previous index | 1192 // esp[8]: previous index |
1193 // esp[12]: subject string | 1193 // esp[12]: subject string |
1194 // esp[16]: JSRegExp object | 1194 // esp[16]: JSRegExp object |
1195 | 1195 |
1196 static const int kLastMatchInfoOffset = 1 * kPointerSize; | 1196 static const int kLastMatchInfoOffset = 1 * kPointerSize; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1454 // haven't created the exception yet. Handle that in the runtime system. | 1454 // haven't created the exception yet. Handle that in the runtime system. |
1455 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 1455 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
1456 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 1456 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
1457 isolate()); | 1457 isolate()); |
1458 __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); | 1458 __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); |
1459 __ mov(eax, Operand::StaticVariable(pending_exception)); | 1459 __ mov(eax, Operand::StaticVariable(pending_exception)); |
1460 __ cmp(edx, eax); | 1460 __ cmp(edx, eax); |
1461 __ j(equal, &runtime); | 1461 __ j(equal, &runtime); |
1462 | 1462 |
1463 // For exception, throw the exception again. | 1463 // For exception, throw the exception again. |
1464 __ TailCallRuntime(Runtime::kRegExpExecReThrow, 4); | 1464 __ TailCallRuntime(Runtime::kRegExpExecReThrow); |
1465 | 1465 |
1466 __ bind(&failure); | 1466 __ bind(&failure); |
1467 // For failure to match, return null. | 1467 // For failure to match, return null. |
1468 __ mov(eax, factory->null_value()); | 1468 __ mov(eax, factory->null_value()); |
1469 __ ret(4 * kPointerSize); | 1469 __ ret(4 * kPointerSize); |
1470 | 1470 |
1471 // Load RegExp data. | 1471 // Load RegExp data. |
1472 __ bind(&success); | 1472 __ bind(&success); |
1473 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 1473 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
1474 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 1474 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 edi); | 1546 edi); |
1547 __ jmp(&next_capture); | 1547 __ jmp(&next_capture); |
1548 __ bind(&done); | 1548 __ bind(&done); |
1549 | 1549 |
1550 // Return last match info. | 1550 // Return last match info. |
1551 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 1551 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
1552 __ ret(4 * kPointerSize); | 1552 __ ret(4 * kPointerSize); |
1553 | 1553 |
1554 // Do the runtime call to execute the regexp. | 1554 // Do the runtime call to execute the regexp. |
1555 __ bind(&runtime); | 1555 __ bind(&runtime); |
1556 __ TailCallRuntime(Runtime::kRegExpExec, 4); | 1556 __ TailCallRuntime(Runtime::kRegExpExec); |
1557 | 1557 |
1558 // Deferred code for string handling. | 1558 // Deferred code for string handling. |
1559 // (7) Not a long external string? If yes, go to (10). | 1559 // (7) Not a long external string? If yes, go to (10). |
1560 __ bind(¬_seq_nor_cons); | 1560 __ bind(¬_seq_nor_cons); |
1561 // Compare flags are still set from (3). | 1561 // Compare flags are still set from (3). |
1562 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). | 1562 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
1563 | 1563 |
1564 // (8) External string. Short external strings have been ruled out. | 1564 // (8) External string. Short external strings have been ruled out. |
1565 __ bind(&external_string); | 1565 __ bind(&external_string); |
1566 // Reload instance type. | 1566 // Reload instance type. |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1899 __ bind(&runtime_call); | 1899 __ bind(&runtime_call); |
1900 | 1900 |
1901 // Push arguments below the return address. | 1901 // Push arguments below the return address. |
1902 __ pop(ecx); | 1902 __ pop(ecx); |
1903 __ push(edx); | 1903 __ push(edx); |
1904 __ push(eax); | 1904 __ push(eax); |
1905 | 1905 |
1906 // Figure out which native to call and setup the arguments. | 1906 // Figure out which native to call and setup the arguments. |
1907 if (cc == equal) { | 1907 if (cc == equal) { |
1908 __ push(ecx); | 1908 __ push(ecx); |
1909 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2); | 1909 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); |
1910 } else { | 1910 } else { |
1911 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 1911 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
1912 | 1912 |
1913 // Restore return address on the stack. | 1913 // Restore return address on the stack. |
1914 __ push(ecx); | 1914 __ push(ecx); |
1915 | 1915 |
1916 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1916 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1917 // tagged as a small integer. | 1917 // tagged as a small integer. |
1918 __ TailCallRuntime( | 1918 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong |
1919 is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, | 1919 : Runtime::kCompare); |
1920 3); | |
1921 } | 1920 } |
1922 | 1921 |
1923 __ bind(&miss); | 1922 __ bind(&miss); |
1924 GenerateMiss(masm); | 1923 GenerateMiss(masm); |
1925 } | 1924 } |
1926 | 1925 |
1927 | 1926 |
1928 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1927 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
1929 // eax : number of arguments to the construct function | 1928 // eax : number of arguments to the construct function |
1930 // ebx : feedback vector | 1929 // ebx : feedback vector |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2242 | 2241 |
2243 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2242 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
2244 FrameScope scope(masm, StackFrame::INTERNAL); | 2243 FrameScope scope(masm, StackFrame::INTERNAL); |
2245 | 2244 |
2246 // Push the function and feedback info. | 2245 // Push the function and feedback info. |
2247 __ push(edi); | 2246 __ push(edi); |
2248 __ push(ebx); | 2247 __ push(ebx); |
2249 __ push(edx); | 2248 __ push(edx); |
2250 | 2249 |
2251 // Call the entry. | 2250 // Call the entry. |
2252 __ CallRuntime(Runtime::kCallIC_Miss, 3); | 2251 __ CallRuntime(Runtime::kCallIC_Miss); |
2253 | 2252 |
2254 // Move result to edi and exit the internal frame. | 2253 // Move result to edi and exit the internal frame. |
2255 __ mov(edi, eax); | 2254 __ mov(edi, eax); |
2256 } | 2255 } |
2257 | 2256 |
2258 | 2257 |
2259 bool CEntryStub::NeedsImmovableCode() { | 2258 bool CEntryStub::NeedsImmovableCode() { |
2260 return false; | 2259 return false; |
2261 } | 2260 } |
2262 | 2261 |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2607 | 2606 |
2608 // Found Proxy or access check needed: Call the runtime. | 2607 // Found Proxy or access check needed: Call the runtime. |
2609 __ bind(&fast_runtime_fallback); | 2608 __ bind(&fast_runtime_fallback); |
2610 __ PopReturnAddressTo(scratch); | 2609 __ PopReturnAddressTo(scratch); |
2611 __ Push(object); | 2610 __ Push(object); |
2612 __ Push(function_prototype); | 2611 __ Push(function_prototype); |
2613 __ PushReturnAddressFrom(scratch); | 2612 __ PushReturnAddressFrom(scratch); |
2614 // Invalidate the instanceof cache. | 2613 // Invalidate the instanceof cache. |
2615 __ Move(eax, Immediate(Smi::FromInt(0))); | 2614 __ Move(eax, Immediate(Smi::FromInt(0))); |
2616 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); | 2615 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); |
2617 __ TailCallRuntime(Runtime::kHasInPrototypeChain, 2); | 2616 __ TailCallRuntime(Runtime::kHasInPrototypeChain); |
2618 | 2617 |
2619 // Slow-case: Call the %InstanceOf runtime function. | 2618 // Slow-case: Call the %InstanceOf runtime function. |
2620 __ bind(&slow_case); | 2619 __ bind(&slow_case); |
2621 __ PopReturnAddressTo(scratch); | 2620 __ PopReturnAddressTo(scratch); |
2622 __ Push(object); | 2621 __ Push(object); |
2623 __ Push(function); | 2622 __ Push(function); |
2624 __ PushReturnAddressFrom(scratch); | 2623 __ PushReturnAddressFrom(scratch); |
2625 __ TailCallRuntime(Runtime::kInstanceOf, 2); | 2624 __ TailCallRuntime(Runtime::kInstanceOf); |
2626 } | 2625 } |
2627 | 2626 |
2628 | 2627 |
2629 // ------------------------------------------------------------------------- | 2628 // ------------------------------------------------------------------------- |
2630 // StringCharCodeAtGenerator | 2629 // StringCharCodeAtGenerator |
2631 | 2630 |
2632 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2631 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
2633 // If the receiver is a smi trigger the non-string case. | 2632 // If the receiver is a smi trigger the non-string case. |
2634 STATIC_ASSERT(kSmiTag == 0); | 2633 STATIC_ASSERT(kSmiTag == 0); |
2635 if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 2634 if (check_mode_ == RECEIVER_IS_UNKNOWN) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2676 index_not_number_, | 2675 index_not_number_, |
2677 DONT_DO_SMI_CHECK); | 2676 DONT_DO_SMI_CHECK); |
2678 call_helper.BeforeCall(masm); | 2677 call_helper.BeforeCall(masm); |
2679 if (embed_mode == PART_OF_IC_HANDLER) { | 2678 if (embed_mode == PART_OF_IC_HANDLER) { |
2680 __ push(LoadWithVectorDescriptor::VectorRegister()); | 2679 __ push(LoadWithVectorDescriptor::VectorRegister()); |
2681 __ push(LoadDescriptor::SlotRegister()); | 2680 __ push(LoadDescriptor::SlotRegister()); |
2682 } | 2681 } |
2683 __ push(object_); | 2682 __ push(object_); |
2684 __ push(index_); // Consumed by runtime conversion function. | 2683 __ push(index_); // Consumed by runtime conversion function. |
2685 if (index_flags_ == STRING_INDEX_IS_NUMBER) { | 2684 if (index_flags_ == STRING_INDEX_IS_NUMBER) { |
2686 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); | 2685 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero); |
2687 } else { | 2686 } else { |
2688 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); | 2687 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); |
2689 // NumberToSmi discards numbers that are not exact integers. | 2688 // NumberToSmi discards numbers that are not exact integers. |
2690 __ CallRuntime(Runtime::kNumberToSmi, 1); | 2689 __ CallRuntime(Runtime::kNumberToSmi); |
2691 } | 2690 } |
2692 if (!index_.is(eax)) { | 2691 if (!index_.is(eax)) { |
2693 // Save the conversion result before the pop instructions below | 2692 // Save the conversion result before the pop instructions below |
2694 // have a chance to overwrite it. | 2693 // have a chance to overwrite it. |
2695 __ mov(index_, eax); | 2694 __ mov(index_, eax); |
2696 } | 2695 } |
2697 __ pop(object_); | 2696 __ pop(object_); |
2698 if (embed_mode == PART_OF_IC_HANDLER) { | 2697 if (embed_mode == PART_OF_IC_HANDLER) { |
2699 __ pop(LoadDescriptor::SlotRegister()); | 2698 __ pop(LoadDescriptor::SlotRegister()); |
2700 __ pop(LoadWithVectorDescriptor::VectorRegister()); | 2699 __ pop(LoadWithVectorDescriptor::VectorRegister()); |
2701 } | 2700 } |
2702 // Reload the instance type. | 2701 // Reload the instance type. |
2703 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 2702 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
2704 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 2703 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
2705 call_helper.AfterCall(masm); | 2704 call_helper.AfterCall(masm); |
2706 // If index is still not a smi, it must be out of range. | 2705 // If index is still not a smi, it must be out of range. |
2707 STATIC_ASSERT(kSmiTag == 0); | 2706 STATIC_ASSERT(kSmiTag == 0); |
2708 __ JumpIfNotSmi(index_, index_out_of_range_); | 2707 __ JumpIfNotSmi(index_, index_out_of_range_); |
2709 // Otherwise, return to the fast path. | 2708 // Otherwise, return to the fast path. |
2710 __ jmp(&got_smi_index_); | 2709 __ jmp(&got_smi_index_); |
2711 | 2710 |
2712 // Call runtime. We get here when the receiver is a string and the | 2711 // Call runtime. We get here when the receiver is a string and the |
2713 // index is a number, but the code of getting the actual character | 2712 // index is a number, but the code of getting the actual character |
2714 // is too complex (e.g., when the string needs to be flattened). | 2713 // is too complex (e.g., when the string needs to be flattened). |
2715 __ bind(&call_runtime_); | 2714 __ bind(&call_runtime_); |
2716 call_helper.BeforeCall(masm); | 2715 call_helper.BeforeCall(masm); |
2717 __ push(object_); | 2716 __ push(object_); |
2718 __ SmiTag(index_); | 2717 __ SmiTag(index_); |
2719 __ push(index_); | 2718 __ push(index_); |
2720 __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); | 2719 __ CallRuntime(Runtime::kStringCharCodeAtRT); |
2721 if (!result_.is(eax)) { | 2720 if (!result_.is(eax)) { |
2722 __ mov(result_, eax); | 2721 __ mov(result_, eax); |
2723 } | 2722 } |
2724 call_helper.AfterCall(masm); | 2723 call_helper.AfterCall(masm); |
2725 __ jmp(&exit_); | 2724 __ jmp(&exit_); |
2726 | 2725 |
2727 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); | 2726 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); |
2728 } | 2727 } |
2729 | 2728 |
2730 | 2729 |
(...skipping 25 matching lines...) Expand all Loading... |
2756 | 2755 |
2757 | 2756 |
2758 void StringCharFromCodeGenerator::GenerateSlow( | 2757 void StringCharFromCodeGenerator::GenerateSlow( |
2759 MacroAssembler* masm, | 2758 MacroAssembler* masm, |
2760 const RuntimeCallHelper& call_helper) { | 2759 const RuntimeCallHelper& call_helper) { |
2761 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); | 2760 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); |
2762 | 2761 |
2763 __ bind(&slow_case_); | 2762 __ bind(&slow_case_); |
2764 call_helper.BeforeCall(masm); | 2763 call_helper.BeforeCall(masm); |
2765 __ push(code_); | 2764 __ push(code_); |
2766 __ CallRuntime(Runtime::kStringCharFromCode, 1); | 2765 __ CallRuntime(Runtime::kStringCharFromCode); |
2767 if (!result_.is(eax)) { | 2766 if (!result_.is(eax)) { |
2768 __ mov(result_, eax); | 2767 __ mov(result_, eax); |
2769 } | 2768 } |
2770 call_helper.AfterCall(masm); | 2769 call_helper.AfterCall(masm); |
2771 __ jmp(&exit_); | 2770 __ jmp(&exit_); |
2772 | 2771 |
2773 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 2772 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
2774 } | 2773 } |
2775 | 2774 |
2776 | 2775 |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3006 masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); | 3005 masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); |
3007 __ IncrementCounter(counters->sub_string_native(), 1); | 3006 __ IncrementCounter(counters->sub_string_native(), 1); |
3008 __ ret(3 * kPointerSize); | 3007 __ ret(3 * kPointerSize); |
3009 | 3008 |
3010 // Drop pushed values on the stack before tail call. | 3009 // Drop pushed values on the stack before tail call. |
3011 __ bind(&runtime_drop_two); | 3010 __ bind(&runtime_drop_two); |
3012 __ Drop(2); | 3011 __ Drop(2); |
3013 | 3012 |
3014 // Just jump to runtime to create the sub string. | 3013 // Just jump to runtime to create the sub string. |
3015 __ bind(&runtime); | 3014 __ bind(&runtime); |
3016 __ TailCallRuntime(Runtime::kSubString, 3); | 3015 __ TailCallRuntime(Runtime::kSubString); |
3017 | 3016 |
3018 __ bind(&single_char); | 3017 __ bind(&single_char); |
3019 // eax: string | 3018 // eax: string |
3020 // ebx: instance type | 3019 // ebx: instance type |
3021 // ecx: sub string length (smi) | 3020 // ecx: sub string length (smi) |
3022 // edx: from index (smi) | 3021 // edx: from index (smi) |
3023 StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime, | 3022 StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime, |
3024 &runtime, STRING_INDEX_IS_NUMBER, | 3023 &runtime, STRING_INDEX_IS_NUMBER, |
3025 RECEIVER_IS_STRING); | 3024 RECEIVER_IS_STRING); |
3026 generator.GenerateFast(masm); | 3025 generator.GenerateFast(masm); |
(...skipping 24 matching lines...) Expand all Loading... |
3051 __ test(FieldOperand(eax, String::kHashFieldOffset), | 3050 __ test(FieldOperand(eax, String::kHashFieldOffset), |
3052 Immediate(String::kContainsCachedArrayIndexMask)); | 3051 Immediate(String::kContainsCachedArrayIndexMask)); |
3053 __ j(not_zero, &slow_string, Label::kNear); | 3052 __ j(not_zero, &slow_string, Label::kNear); |
3054 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | 3053 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); |
3055 __ IndexFromHash(eax, eax); | 3054 __ IndexFromHash(eax, eax); |
3056 __ Ret(); | 3055 __ Ret(); |
3057 __ bind(&slow_string); | 3056 __ bind(&slow_string); |
3058 __ pop(ecx); // Pop return address. | 3057 __ pop(ecx); // Pop return address. |
3059 __ push(eax); // Push argument. | 3058 __ push(eax); // Push argument. |
3060 __ push(ecx); // Push return address. | 3059 __ push(ecx); // Push return address. |
3061 __ TailCallRuntime(Runtime::kStringToNumber, 1); | 3060 __ TailCallRuntime(Runtime::kStringToNumber); |
3062 __ bind(¬_string); | 3061 __ bind(¬_string); |
3063 | 3062 |
3064 Label not_oddball; | 3063 Label not_oddball; |
3065 __ CmpInstanceType(edi, ODDBALL_TYPE); | 3064 __ CmpInstanceType(edi, ODDBALL_TYPE); |
3066 __ j(not_equal, ¬_oddball, Label::kNear); | 3065 __ j(not_equal, ¬_oddball, Label::kNear); |
3067 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 3066 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
3068 __ Ret(); | 3067 __ Ret(); |
3069 __ bind(¬_oddball); | 3068 __ bind(¬_oddball); |
3070 | 3069 |
3071 __ pop(ecx); // Pop return address. | 3070 __ pop(ecx); // Pop return address. |
3072 __ push(eax); // Push argument. | 3071 __ push(eax); // Push argument. |
3073 __ push(ecx); // Push return address. | 3072 __ push(ecx); // Push return address. |
3074 __ TailCallRuntime(Runtime::kToNumber, 1); | 3073 __ TailCallRuntime(Runtime::kToNumber); |
3075 } | 3074 } |
3076 | 3075 |
3077 | 3076 |
3078 void ToLengthStub::Generate(MacroAssembler* masm) { | 3077 void ToLengthStub::Generate(MacroAssembler* masm) { |
3079 // The ToLength stub takes on argument in eax. | 3078 // The ToLength stub takes on argument in eax. |
3080 Label not_smi, positive_smi; | 3079 Label not_smi, positive_smi; |
3081 __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); | 3080 __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); |
3082 STATIC_ASSERT(kSmiTag == 0); | 3081 STATIC_ASSERT(kSmiTag == 0); |
3083 __ test(eax, eax); | 3082 __ test(eax, eax); |
3084 __ j(greater_equal, &positive_smi, Label::kNear); | 3083 __ j(greater_equal, &positive_smi, Label::kNear); |
3085 __ xor_(eax, eax); | 3084 __ xor_(eax, eax); |
3086 __ bind(&positive_smi); | 3085 __ bind(&positive_smi); |
3087 __ Ret(); | 3086 __ Ret(); |
3088 __ bind(¬_smi); | 3087 __ bind(¬_smi); |
3089 | 3088 |
3090 __ pop(ecx); // Pop return address. | 3089 __ pop(ecx); // Pop return address. |
3091 __ push(eax); // Push argument. | 3090 __ push(eax); // Push argument. |
3092 __ push(ecx); // Push return address. | 3091 __ push(ecx); // Push return address. |
3093 __ TailCallRuntime(Runtime::kToLength, 1); | 3092 __ TailCallRuntime(Runtime::kToLength); |
3094 } | 3093 } |
3095 | 3094 |
3096 | 3095 |
3097 void ToStringStub::Generate(MacroAssembler* masm) { | 3096 void ToStringStub::Generate(MacroAssembler* masm) { |
3098 // The ToString stub takes one argument in eax. | 3097 // The ToString stub takes one argument in eax. |
3099 Label is_number; | 3098 Label is_number; |
3100 __ JumpIfSmi(eax, &is_number, Label::kNear); | 3099 __ JumpIfSmi(eax, &is_number, Label::kNear); |
3101 | 3100 |
3102 Label not_string; | 3101 Label not_string; |
3103 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); | 3102 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); |
(...skipping 14 matching lines...) Expand all Loading... |
3118 Label not_oddball; | 3117 Label not_oddball; |
3119 __ CmpInstanceType(edi, ODDBALL_TYPE); | 3118 __ CmpInstanceType(edi, ODDBALL_TYPE); |
3120 __ j(not_equal, ¬_oddball, Label::kNear); | 3119 __ j(not_equal, ¬_oddball, Label::kNear); |
3121 __ mov(eax, FieldOperand(eax, Oddball::kToStringOffset)); | 3120 __ mov(eax, FieldOperand(eax, Oddball::kToStringOffset)); |
3122 __ Ret(); | 3121 __ Ret(); |
3123 __ bind(¬_oddball); | 3122 __ bind(¬_oddball); |
3124 | 3123 |
3125 __ pop(ecx); // Pop return address. | 3124 __ pop(ecx); // Pop return address. |
3126 __ push(eax); // Push argument. | 3125 __ push(eax); // Push argument. |
3127 __ push(ecx); // Push return address. | 3126 __ push(ecx); // Push return address. |
3128 __ TailCallRuntime(Runtime::kToString, 1); | 3127 __ TailCallRuntime(Runtime::kToString); |
3129 } | 3128 } |
3130 | 3129 |
3131 | 3130 |
3132 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, | 3131 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, |
3133 Register left, | 3132 Register left, |
3134 Register right, | 3133 Register right, |
3135 Register scratch1, | 3134 Register scratch1, |
3136 Register scratch2) { | 3135 Register scratch2) { |
3137 Register length = scratch1; | 3136 Register length = scratch1; |
3138 | 3137 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3281 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, | 3280 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, |
3282 edi); | 3281 edi); |
3283 | 3282 |
3284 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 3283 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
3285 // tagged as a small integer. | 3284 // tagged as a small integer. |
3286 __ bind(&runtime); | 3285 __ bind(&runtime); |
3287 __ PopReturnAddressTo(ecx); | 3286 __ PopReturnAddressTo(ecx); |
3288 __ Push(edx); | 3287 __ Push(edx); |
3289 __ Push(eax); | 3288 __ Push(eax); |
3290 __ PushReturnAddressFrom(ecx); | 3289 __ PushReturnAddressFrom(ecx); |
3291 __ TailCallRuntime(Runtime::kStringCompare, 2); | 3290 __ TailCallRuntime(Runtime::kStringCompare); |
3292 } | 3291 } |
3293 | 3292 |
3294 | 3293 |
3295 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3294 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
3296 // ----------- S t a t e ------------- | 3295 // ----------- S t a t e ------------- |
3297 // -- edx : left | 3296 // -- edx : left |
3298 // -- eax : right | 3297 // -- eax : right |
3299 // -- esp[0] : return address | 3298 // -- esp[0] : return address |
3300 // ----------------------------------- | 3299 // ----------------------------------- |
3301 | 3300 |
(...skipping 24 matching lines...) Expand all Loading... |
3326 Label::Distance const miss_distance = | 3325 Label::Distance const miss_distance = |
3327 masm->emit_debug_code() ? Label::kFar : Label::kNear; | 3326 masm->emit_debug_code() ? Label::kFar : Label::kNear; |
3328 | 3327 |
3329 __ JumpIfSmi(edx, &miss, miss_distance); | 3328 __ JumpIfSmi(edx, &miss, miss_distance); |
3330 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 3329 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
3331 __ JumpIfSmi(eax, &miss, miss_distance); | 3330 __ JumpIfSmi(eax, &miss, miss_distance); |
3332 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3331 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3333 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3332 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
3334 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3333 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
3335 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 3334 if (op() != Token::EQ_STRICT && is_strong(strength())) { |
3336 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); | 3335 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); |
3337 } else { | 3336 } else { |
3338 if (!Token::IsEqualityOp(op())) { | 3337 if (!Token::IsEqualityOp(op())) { |
3339 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 3338 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
3340 __ AssertSmi(eax); | 3339 __ AssertSmi(eax); |
3341 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); | 3340 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); |
3342 __ AssertSmi(edx); | 3341 __ AssertSmi(edx); |
3343 __ xchg(eax, edx); | 3342 __ xchg(eax, edx); |
3344 } | 3343 } |
3345 __ sub(eax, edx); | 3344 __ sub(eax, edx); |
3346 __ Ret(); | 3345 __ Ret(); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3622 tmp2, tmp3); | 3621 tmp2, tmp3); |
3623 } | 3622 } |
3624 | 3623 |
3625 // Handle more complex cases in runtime. | 3624 // Handle more complex cases in runtime. |
3626 __ bind(&runtime); | 3625 __ bind(&runtime); |
3627 __ pop(tmp1); // Return address. | 3626 __ pop(tmp1); // Return address. |
3628 __ push(left); | 3627 __ push(left); |
3629 __ push(right); | 3628 __ push(right); |
3630 __ push(tmp1); | 3629 __ push(tmp1); |
3631 if (equality) { | 3630 if (equality) { |
3632 __ TailCallRuntime(Runtime::kStringEquals, 2); | 3631 __ TailCallRuntime(Runtime::kStringEquals); |
3633 } else { | 3632 } else { |
3634 __ TailCallRuntime(Runtime::kStringCompare, 2); | 3633 __ TailCallRuntime(Runtime::kStringCompare); |
3635 } | 3634 } |
3636 | 3635 |
3637 __ bind(&miss); | 3636 __ bind(&miss); |
3638 GenerateMiss(masm); | 3637 GenerateMiss(masm); |
3639 } | 3638 } |
3640 | 3639 |
3641 | 3640 |
3642 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { | 3641 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { |
3643 DCHECK_EQ(CompareICState::RECEIVER, state()); | 3642 DCHECK_EQ(CompareICState::RECEIVER, state()); |
3644 Label miss; | 3643 Label miss; |
(...skipping 26 matching lines...) Expand all Loading... |
3671 __ GetWeakValue(edi, cell); | 3670 __ GetWeakValue(edi, cell); |
3672 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); | 3671 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); |
3673 __ j(not_equal, &miss, Label::kNear); | 3672 __ j(not_equal, &miss, Label::kNear); |
3674 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 3673 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
3675 __ j(not_equal, &miss, Label::kNear); | 3674 __ j(not_equal, &miss, Label::kNear); |
3676 | 3675 |
3677 if (Token::IsEqualityOp(op())) { | 3676 if (Token::IsEqualityOp(op())) { |
3678 __ sub(eax, edx); | 3677 __ sub(eax, edx); |
3679 __ ret(0); | 3678 __ ret(0); |
3680 } else if (is_strong(strength())) { | 3679 } else if (is_strong(strength())) { |
3681 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); | 3680 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); |
3682 } else { | 3681 } else { |
3683 __ PopReturnAddressTo(ecx); | 3682 __ PopReturnAddressTo(ecx); |
3684 __ Push(edx); | 3683 __ Push(edx); |
3685 __ Push(eax); | 3684 __ Push(eax); |
3686 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); | 3685 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); |
3687 __ PushReturnAddressFrom(ecx); | 3686 __ PushReturnAddressFrom(ecx); |
3688 __ TailCallRuntime(Runtime::kCompare, 3); | 3687 __ TailCallRuntime(Runtime::kCompare); |
3689 } | 3688 } |
3690 | 3689 |
3691 __ bind(&miss); | 3690 __ bind(&miss); |
3692 GenerateMiss(masm); | 3691 GenerateMiss(masm); |
3693 } | 3692 } |
3694 | 3693 |
3695 | 3694 |
3696 void CompareICStub::GenerateMiss(MacroAssembler* masm) { | 3695 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
3697 { | 3696 { |
3698 // Call the runtime system in a fresh internal frame. | 3697 // Call the runtime system in a fresh internal frame. |
3699 FrameScope scope(masm, StackFrame::INTERNAL); | 3698 FrameScope scope(masm, StackFrame::INTERNAL); |
3700 __ push(edx); // Preserve edx and eax. | 3699 __ push(edx); // Preserve edx and eax. |
3701 __ push(eax); | 3700 __ push(eax); |
3702 __ push(edx); // And also use them as the arguments. | 3701 __ push(edx); // And also use them as the arguments. |
3703 __ push(eax); | 3702 __ push(eax); |
3704 __ push(Immediate(Smi::FromInt(op()))); | 3703 __ push(Immediate(Smi::FromInt(op()))); |
3705 __ CallRuntime(Runtime::kCompareIC_Miss, 3); | 3704 __ CallRuntime(Runtime::kCompareIC_Miss); |
3706 // Compute the entry point of the rewritten stub. | 3705 // Compute the entry point of the rewritten stub. |
3707 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); | 3706 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); |
3708 __ pop(eax); | 3707 __ pop(eax); |
3709 __ pop(edx); | 3708 __ pop(edx); |
3710 } | 3709 } |
3711 | 3710 |
3712 // Do a tail call to the rewritten stub. | 3711 // Do a tail call to the rewritten stub. |
3713 __ jmp(edi); | 3712 __ jmp(edi); |
3714 } | 3713 } |
3715 | 3714 |
(...skipping 1434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5150 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); | 5149 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); |
5151 __ j(equal, &slow_case, Label::kNear); | 5150 __ j(equal, &slow_case, Label::kNear); |
5152 __ Ret(); | 5151 __ Ret(); |
5153 | 5152 |
5154 // Fallback to the runtime. | 5153 // Fallback to the runtime. |
5155 __ bind(&slow_case); | 5154 __ bind(&slow_case); |
5156 __ SmiTag(slot_reg); | 5155 __ SmiTag(slot_reg); |
5157 __ Pop(result_reg); // Pop return address. | 5156 __ Pop(result_reg); // Pop return address. |
5158 __ Push(slot_reg); | 5157 __ Push(slot_reg); |
5159 __ Push(result_reg); // Push return address. | 5158 __ Push(result_reg); // Push return address. |
5160 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1); | 5159 __ TailCallRuntime(Runtime::kLoadGlobalViaContext); |
5161 } | 5160 } |
5162 | 5161 |
5163 | 5162 |
5164 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | 5163 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { |
5165 Register context_reg = esi; | 5164 Register context_reg = esi; |
5166 Register slot_reg = ebx; | 5165 Register slot_reg = ebx; |
5167 Register value_reg = eax; | 5166 Register value_reg = eax; |
5168 Register cell_reg = edi; | 5167 Register cell_reg = edi; |
5169 Register cell_details_reg = edx; | 5168 Register cell_details_reg = edx; |
5170 Register cell_value_reg = ecx; | 5169 Register cell_value_reg = ecx; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5273 | 5272 |
5274 // Fallback to the runtime. | 5273 // Fallback to the runtime. |
5275 __ bind(&slow_case); | 5274 __ bind(&slow_case); |
5276 __ SmiTag(slot_reg); | 5275 __ SmiTag(slot_reg); |
5277 __ Pop(cell_reg); // Pop return address. | 5276 __ Pop(cell_reg); // Pop return address. |
5278 __ Push(slot_reg); | 5277 __ Push(slot_reg); |
5279 __ Push(value_reg); | 5278 __ Push(value_reg); |
5280 __ Push(cell_reg); // Push return address. | 5279 __ Push(cell_reg); // Push return address. |
5281 __ TailCallRuntime(is_strict(language_mode()) | 5280 __ TailCallRuntime(is_strict(language_mode()) |
5282 ? Runtime::kStoreGlobalViaContext_Strict | 5281 ? Runtime::kStoreGlobalViaContext_Strict |
5283 : Runtime::kStoreGlobalViaContext_Sloppy, | 5282 : Runtime::kStoreGlobalViaContext_Sloppy); |
5284 2); | |
5285 } | 5283 } |
5286 | 5284 |
5287 | 5285 |
5288 // Generates an Operand for saving parameters after PrepareCallApiFunction. | 5286 // Generates an Operand for saving parameters after PrepareCallApiFunction. |
5289 static Operand ApiParameterOperand(int index) { | 5287 static Operand ApiParameterOperand(int index) { |
5290 return Operand(esp, index * kPointerSize); | 5288 return Operand(esp, index * kPointerSize); |
5291 } | 5289 } |
5292 | 5290 |
5293 | 5291 |
5294 // Prepares stack to put arguments (aligns and so on). Reserves | 5292 // Prepares stack to put arguments (aligns and so on). Reserves |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5445 DCHECK_EQ(0, stack_space); | 5443 DCHECK_EQ(0, stack_space); |
5446 __ pop(ecx); | 5444 __ pop(ecx); |
5447 __ add(esp, ebx); | 5445 __ add(esp, ebx); |
5448 __ jmp(ecx); | 5446 __ jmp(ecx); |
5449 } else { | 5447 } else { |
5450 __ ret(stack_space * kPointerSize); | 5448 __ ret(stack_space * kPointerSize); |
5451 } | 5449 } |
5452 | 5450 |
5453 // Re-throw by promoting a scheduled exception. | 5451 // Re-throw by promoting a scheduled exception. |
5454 __ bind(&promote_scheduled_exception); | 5452 __ bind(&promote_scheduled_exception); |
5455 __ TailCallRuntime(Runtime::kPromoteScheduledException, 0); | 5453 __ TailCallRuntime(Runtime::kPromoteScheduledException); |
5456 | 5454 |
5457 // HandleScope limit has changed. Delete allocated extensions. | 5455 // HandleScope limit has changed. Delete allocated extensions. |
5458 ExternalReference delete_extensions = | 5456 ExternalReference delete_extensions = |
5459 ExternalReference::delete_handle_scope_extensions(isolate); | 5457 ExternalReference::delete_handle_scope_extensions(isolate); |
5460 __ bind(&delete_allocated_handles); | 5458 __ bind(&delete_allocated_handles); |
5461 __ mov(Operand::StaticVariable(limit_address), edi); | 5459 __ mov(Operand::StaticVariable(limit_address), edi); |
5462 __ mov(edi, eax); | 5460 __ mov(edi, eax); |
5463 __ mov(Operand(esp, 0), | 5461 __ mov(Operand(esp, 0), |
5464 Immediate(ExternalReference::isolate_address(isolate))); | 5462 Immediate(ExternalReference::isolate_address(isolate))); |
5465 __ mov(eax, Immediate(delete_extensions)); | 5463 __ mov(eax, Immediate(delete_extensions)); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5668 Operand(ebp, 7 * kPointerSize), NULL); | 5666 Operand(ebp, 7 * kPointerSize), NULL); |
5669 } | 5667 } |
5670 | 5668 |
5671 | 5669 |
5672 #undef __ | 5670 #undef __ |
5673 | 5671 |
5674 } // namespace internal | 5672 } // namespace internal |
5675 } // namespace v8 | 5673 } // namespace v8 |
5676 | 5674 |
5677 #endif // V8_TARGET_ARCH_IA32 | 5675 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |