| 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_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 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 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 void MathPowStub::Generate(MacroAssembler* masm) { | 327 void MathPowStub::Generate(MacroAssembler* masm) { |
| 328 const Register base = edx; | 328 const Register base = edx; |
| 329 const Register scratch = ecx; | 329 const Register scratch = ecx; |
| 330 Counters* counters = isolate()->counters(); | 330 Counters* counters = isolate()->counters(); |
| 331 Label call_runtime; | 331 Label call_runtime; |
| 332 | 332 |
| 333 // We will call runtime helper function directly. | 333 // We will call runtime helper function directly. |
| 334 if (exponent_type() == ON_STACK) { | 334 if (exponent_type() == ON_STACK) { |
| 335 // The arguments are still on the stack. | 335 // The arguments are still on the stack. |
| 336 __ bind(&call_runtime); | 336 __ bind(&call_runtime); |
| 337 __ TailCallRuntime(Runtime::kMathPowRT, 2); | 337 __ TailCallRuntime(Runtime::kMathPowRT); |
| 338 | 338 |
| 339 // The stub is called from non-optimized code, which expects the result | 339 // The stub is called from non-optimized code, which expects the result |
| 340 // as heap number in exponent. | 340 // as heap number in exponent. |
| 341 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); | 341 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); |
| 342 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 342 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 343 __ IncrementCounter(counters->math_pow(), 1); | 343 __ IncrementCounter(counters->math_pow(), 1); |
| 344 __ ret(2 * kPointerSize); | 344 __ ret(2 * kPointerSize); |
| 345 } else { | 345 } else { |
| 346 // Currently it's only called from full-compiler and exponent type is | 346 // Currently it's only called from full-compiler and exponent type is |
| 347 // ON_STACK. | 347 // ON_STACK. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 __ test(key, Immediate(kSmiTagMask | kSmiSignMask)); | 381 __ test(key, Immediate(kSmiTagMask | kSmiSignMask)); |
| 382 __ j(not_zero, &slow); | 382 __ j(not_zero, &slow); |
| 383 | 383 |
| 384 // Everything is fine, call runtime. | 384 // Everything is fine, call runtime. |
| 385 __ pop(scratch); | 385 __ pop(scratch); |
| 386 __ push(receiver); // receiver | 386 __ push(receiver); // receiver |
| 387 __ push(key); // key | 387 __ push(key); // key |
| 388 __ push(scratch); // return address | 388 __ push(scratch); // return address |
| 389 | 389 |
| 390 // Perform tail call to the entry. | 390 // Perform tail call to the entry. |
| 391 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2); | 391 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor); |
| 392 | 392 |
| 393 __ bind(&slow); | 393 __ bind(&slow); |
| 394 PropertyAccessCompiler::TailCallBuiltin( | 394 PropertyAccessCompiler::TailCallBuiltin( |
| 395 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 395 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
| 396 } | 396 } |
| 397 | 397 |
| 398 | 398 |
| 399 void LoadIndexedStringStub::Generate(MacroAssembler* masm) { | 399 void LoadIndexedStringStub::Generate(MacroAssembler* masm) { |
| 400 // Return address is on the stack. | 400 // Return address is on the stack. |
| 401 Label miss; | 401 Label miss; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 __ neg(edx); | 481 __ neg(edx); |
| 482 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); | 482 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); |
| 483 __ ret(0); | 483 __ ret(0); |
| 484 | 484 |
| 485 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 485 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 486 // by calling the runtime system. | 486 // by calling the runtime system. |
| 487 __ bind(&slow); | 487 __ bind(&slow); |
| 488 __ pop(ebx); // Return address. | 488 __ pop(ebx); // Return address. |
| 489 __ push(edx); | 489 __ push(edx); |
| 490 __ push(ebx); | 490 __ push(ebx); |
| 491 __ TailCallRuntime(Runtime::kArguments, 1); | 491 __ TailCallRuntime(Runtime::kArguments); |
| 492 } | 492 } |
| 493 | 493 |
| 494 | 494 |
| 495 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | 495 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { |
| 496 // ecx : number of parameters (tagged) | 496 // ecx : number of parameters (tagged) |
| 497 // edx : parameters pointer | 497 // edx : parameters pointer |
| 498 // edi : function | 498 // edi : function |
| 499 // esp[0] : return address | 499 // esp[0] : return address |
| 500 | 500 |
| 501 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | 501 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 513 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 513 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 514 __ lea(edx, | 514 __ lea(edx, |
| 515 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | 515 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); |
| 516 | 516 |
| 517 __ bind(&runtime); | 517 __ bind(&runtime); |
| 518 __ pop(eax); // Pop return address. | 518 __ pop(eax); // Pop return address. |
| 519 __ push(edi); // Push function. | 519 __ push(edi); // Push function. |
| 520 __ push(edx); // Push parameters pointer. | 520 __ push(edx); // Push parameters pointer. |
| 521 __ push(ecx); // Push parameter count. | 521 __ push(ecx); // Push parameter count. |
| 522 __ push(eax); // Push return address. | 522 __ push(eax); // Push return address. |
| 523 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); | 523 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
| 524 } | 524 } |
| 525 | 525 |
| 526 | 526 |
| 527 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | 527 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
| 528 // ecx : number of parameters (tagged) | 528 // ecx : number of parameters (tagged) |
| 529 // edx : parameters pointer | 529 // edx : parameters pointer |
| 530 // edi : function | 530 // edi : function |
| 531 // esp[0] : return address | 531 // esp[0] : return address |
| 532 | 532 |
| 533 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | 533 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 // Do the runtime call to allocate the arguments object. | 748 // Do the runtime call to allocate the arguments object. |
| 749 __ bind(&runtime); | 749 __ bind(&runtime); |
| 750 __ pop(eax); // Remove saved mapped parameter count. | 750 __ pop(eax); // Remove saved mapped parameter count. |
| 751 __ pop(edi); // Pop saved function. | 751 __ pop(edi); // Pop saved function. |
| 752 __ pop(eax); // Remove saved parameter count. | 752 __ pop(eax); // Remove saved parameter count. |
| 753 __ pop(eax); // Pop return address. | 753 __ pop(eax); // Pop return address. |
| 754 __ push(edi); // Push function. | 754 __ push(edi); // Push function. |
| 755 __ push(edx); // Push parameters pointer. | 755 __ push(edx); // Push parameters pointer. |
| 756 __ push(ecx); // Push parameter count. | 756 __ push(ecx); // Push parameter count. |
| 757 __ push(eax); // Push return address. | 757 __ push(eax); // Push return address. |
| 758 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); | 758 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
| 759 } | 759 } |
| 760 | 760 |
| 761 | 761 |
| 762 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | 762 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
| 763 // ecx : number of parameters (tagged) | 763 // ecx : number of parameters (tagged) |
| 764 // edx : parameters pointer | 764 // edx : parameters pointer |
| 765 // edi : function | 765 // edi : function |
| 766 // esp[0] : return address | 766 // esp[0] : return address |
| 767 | 767 |
| 768 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | 768 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 842 __ bind(&done); | 842 __ bind(&done); |
| 843 __ ret(0); | 843 __ ret(0); |
| 844 | 844 |
| 845 // Do the runtime call to allocate the arguments object. | 845 // Do the runtime call to allocate the arguments object. |
| 846 __ bind(&runtime); | 846 __ bind(&runtime); |
| 847 __ pop(eax); // Pop return address. | 847 __ pop(eax); // Pop return address. |
| 848 __ push(edi); // Push function. | 848 __ push(edi); // Push function. |
| 849 __ push(edx); // Push parameters pointer. | 849 __ push(edx); // Push parameters pointer. |
| 850 __ push(ecx); // Push parameter count. | 850 __ push(ecx); // Push parameter count. |
| 851 __ push(eax); // Push return address. | 851 __ push(eax); // Push return address. |
| 852 __ TailCallRuntime(Runtime::kNewStrictArguments, 3); | 852 __ TailCallRuntime(Runtime::kNewStrictArguments); |
| 853 } | 853 } |
| 854 | 854 |
| 855 | 855 |
| 856 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) { | 856 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) { |
| 857 // esp[0] : return address | 857 // esp[0] : return address |
| 858 // esp[4] : language mode | 858 // esp[4] : language mode |
| 859 // esp[8] : index of rest parameter | 859 // esp[8] : index of rest parameter |
| 860 // esp[12] : number of parameters | 860 // esp[12] : number of parameters |
| 861 // esp[16] : receiver displacement | 861 // esp[16] : receiver displacement |
| 862 | 862 |
| 863 // Check if the calling frame is an arguments adaptor frame. | 863 // Check if the calling frame is an arguments adaptor frame. |
| 864 Label runtime; | 864 Label runtime; |
| 865 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 865 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 866 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | 866 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); |
| 867 __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 867 __ cmp(ecx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 868 __ j(not_equal, &runtime); | 868 __ j(not_equal, &runtime); |
| 869 | 869 |
| 870 // Patch the arguments.length and the parameters pointer. | 870 // Patch the arguments.length and the parameters pointer. |
| 871 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 871 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 872 __ mov(Operand(esp, 3 * kPointerSize), ecx); | 872 __ mov(Operand(esp, 3 * kPointerSize), ecx); |
| 873 __ lea(edx, | 873 __ lea(edx, |
| 874 Operand(edx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | 874 Operand(edx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); |
| 875 __ mov(Operand(esp, 4 * kPointerSize), edx); | 875 __ mov(Operand(esp, 4 * kPointerSize), edx); |
| 876 | 876 |
| 877 __ bind(&runtime); | 877 __ bind(&runtime); |
| 878 __ TailCallRuntime(Runtime::kNewRestParam, 4); | 878 __ TailCallRuntime(Runtime::kNewRestParam); |
| 879 } | 879 } |
| 880 | 880 |
| 881 | 881 |
| 882 void RegExpExecStub::Generate(MacroAssembler* masm) { | 882 void RegExpExecStub::Generate(MacroAssembler* masm) { |
| 883 // Just jump directly to runtime if native RegExp is not selected at compile | 883 // Just jump directly to runtime if native RegExp is not selected at compile |
| 884 // time or if regexp entry in generated code is turned off runtime switch or | 884 // time or if regexp entry in generated code is turned off runtime switch or |
| 885 // at compilation. | 885 // at compilation. |
| 886 #ifdef V8_INTERPRETED_REGEXP | 886 #ifdef V8_INTERPRETED_REGEXP |
| 887 __ TailCallRuntime(Runtime::kRegExpExec, 4); | 887 __ TailCallRuntime(Runtime::kRegExpExec); |
| 888 #else // V8_INTERPRETED_REGEXP | 888 #else // V8_INTERPRETED_REGEXP |
| 889 | 889 |
| 890 // Stack frame on entry. | 890 // Stack frame on entry. |
| 891 // esp[0]: return address | 891 // esp[0]: return address |
| 892 // esp[4]: last_match_info (expected JSArray) | 892 // esp[4]: last_match_info (expected JSArray) |
| 893 // esp[8]: previous index | 893 // esp[8]: previous index |
| 894 // esp[12]: subject string | 894 // esp[12]: subject string |
| 895 // esp[16]: JSRegExp object | 895 // esp[16]: JSRegExp object |
| 896 | 896 |
| 897 static const int kLastMatchInfoOffset = 1 * kPointerSize; | 897 static const int kLastMatchInfoOffset = 1 * kPointerSize; |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 // haven't created the exception yet. Handle that in the runtime system. | 1155 // haven't created the exception yet. Handle that in the runtime system. |
| 1156 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 1156 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 1157 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 1157 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
| 1158 isolate()); | 1158 isolate()); |
| 1159 __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); | 1159 __ mov(edx, Immediate(isolate()->factory()->the_hole_value())); |
| 1160 __ mov(eax, Operand::StaticVariable(pending_exception)); | 1160 __ mov(eax, Operand::StaticVariable(pending_exception)); |
| 1161 __ cmp(edx, eax); | 1161 __ cmp(edx, eax); |
| 1162 __ j(equal, &runtime); | 1162 __ j(equal, &runtime); |
| 1163 | 1163 |
| 1164 // For exception, throw the exception again. | 1164 // For exception, throw the exception again. |
| 1165 __ TailCallRuntime(Runtime::kRegExpExecReThrow, 4); | 1165 __ TailCallRuntime(Runtime::kRegExpExecReThrow); |
| 1166 | 1166 |
| 1167 __ bind(&failure); | 1167 __ bind(&failure); |
| 1168 // For failure to match, return null. | 1168 // For failure to match, return null. |
| 1169 __ mov(eax, factory->null_value()); | 1169 __ mov(eax, factory->null_value()); |
| 1170 __ ret(4 * kPointerSize); | 1170 __ ret(4 * kPointerSize); |
| 1171 | 1171 |
| 1172 // Load RegExp data. | 1172 // Load RegExp data. |
| 1173 __ bind(&success); | 1173 __ bind(&success); |
| 1174 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 1174 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
| 1175 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 1175 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 edi); | 1241 edi); |
| 1242 __ jmp(&next_capture); | 1242 __ jmp(&next_capture); |
| 1243 __ bind(&done); | 1243 __ bind(&done); |
| 1244 | 1244 |
| 1245 // Return last match info. | 1245 // Return last match info. |
| 1246 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 1246 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
| 1247 __ ret(4 * kPointerSize); | 1247 __ ret(4 * kPointerSize); |
| 1248 | 1248 |
| 1249 // Do the runtime call to execute the regexp. | 1249 // Do the runtime call to execute the regexp. |
| 1250 __ bind(&runtime); | 1250 __ bind(&runtime); |
| 1251 __ TailCallRuntime(Runtime::kRegExpExec, 4); | 1251 __ TailCallRuntime(Runtime::kRegExpExec); |
| 1252 | 1252 |
| 1253 // Deferred code for string handling. | 1253 // Deferred code for string handling. |
| 1254 // (7) Not a long external string? If yes, go to (10). | 1254 // (7) Not a long external string? If yes, go to (10). |
| 1255 __ bind(¬_seq_nor_cons); | 1255 __ bind(¬_seq_nor_cons); |
| 1256 // Compare flags are still set from (3). | 1256 // Compare flags are still set from (3). |
| 1257 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). | 1257 __ j(greater, ¬_long_external, Label::kNear); // Go to (10). |
| 1258 | 1258 |
| 1259 // (8) External string. Short external strings have been ruled out. | 1259 // (8) External string. Short external strings have been ruled out. |
| 1260 __ bind(&external_string); | 1260 __ bind(&external_string); |
| 1261 // Reload instance type. | 1261 // Reload instance type. |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1606 __ bind(&runtime_call); | 1606 __ bind(&runtime_call); |
| 1607 | 1607 |
| 1608 // Push arguments below the return address. | 1608 // Push arguments below the return address. |
| 1609 __ pop(ecx); | 1609 __ pop(ecx); |
| 1610 __ push(edx); | 1610 __ push(edx); |
| 1611 __ push(eax); | 1611 __ push(eax); |
| 1612 | 1612 |
| 1613 // Figure out which native to call and setup the arguments. | 1613 // Figure out which native to call and setup the arguments. |
| 1614 if (cc == equal) { | 1614 if (cc == equal) { |
| 1615 __ push(ecx); | 1615 __ push(ecx); |
| 1616 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2); | 1616 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); |
| 1617 } else { | 1617 } else { |
| 1618 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 1618 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
| 1619 | 1619 |
| 1620 // Restore return address on the stack. | 1620 // Restore return address on the stack. |
| 1621 __ push(ecx); | 1621 __ push(ecx); |
| 1622 | 1622 |
| 1623 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1623 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
| 1624 // tagged as a small integer. | 1624 // tagged as a small integer. |
| 1625 __ TailCallRuntime( | 1625 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong |
| 1626 is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, | 1626 : Runtime::kCompare); |
| 1627 3); | |
| 1628 } | 1627 } |
| 1629 | 1628 |
| 1630 __ bind(&miss); | 1629 __ bind(&miss); |
| 1631 GenerateMiss(masm); | 1630 GenerateMiss(masm); |
| 1632 } | 1631 } |
| 1633 | 1632 |
| 1634 | 1633 |
| 1635 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1634 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
| 1636 // eax : number of arguments to the construct function | 1635 // eax : number of arguments to the construct function |
| 1637 // ebx : feedback vector | 1636 // ebx : feedback vector |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1949 | 1948 |
| 1950 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 1949 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
| 1951 FrameScope scope(masm, StackFrame::INTERNAL); | 1950 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1952 | 1951 |
| 1953 // Push the function and feedback info. | 1952 // Push the function and feedback info. |
| 1954 __ push(edi); | 1953 __ push(edi); |
| 1955 __ push(ebx); | 1954 __ push(ebx); |
| 1956 __ push(edx); | 1955 __ push(edx); |
| 1957 | 1956 |
| 1958 // Call the entry. | 1957 // Call the entry. |
| 1959 __ CallRuntime(Runtime::kCallIC_Miss, 3); | 1958 __ CallRuntime(Runtime::kCallIC_Miss); |
| 1960 | 1959 |
| 1961 // Move result to edi and exit the internal frame. | 1960 // Move result to edi and exit the internal frame. |
| 1962 __ mov(edi, eax); | 1961 __ mov(edi, eax); |
| 1963 } | 1962 } |
| 1964 | 1963 |
| 1965 | 1964 |
| 1966 bool CEntryStub::NeedsImmovableCode() { | 1965 bool CEntryStub::NeedsImmovableCode() { |
| 1967 return false; | 1966 return false; |
| 1968 } | 1967 } |
| 1969 | 1968 |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2319 | 2318 |
| 2320 // Found Proxy or access check needed: Call the runtime. | 2319 // Found Proxy or access check needed: Call the runtime. |
| 2321 __ bind(&fast_runtime_fallback); | 2320 __ bind(&fast_runtime_fallback); |
| 2322 __ PopReturnAddressTo(scratch); | 2321 __ PopReturnAddressTo(scratch); |
| 2323 __ Push(object); | 2322 __ Push(object); |
| 2324 __ Push(function_prototype); | 2323 __ Push(function_prototype); |
| 2325 __ PushReturnAddressFrom(scratch); | 2324 __ PushReturnAddressFrom(scratch); |
| 2326 // Invalidate the instanceof cache. | 2325 // Invalidate the instanceof cache. |
| 2327 __ Move(eax, Immediate(Smi::FromInt(0))); | 2326 __ Move(eax, Immediate(Smi::FromInt(0))); |
| 2328 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); | 2327 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); |
| 2329 __ TailCallRuntime(Runtime::kHasInPrototypeChain, 2); | 2328 __ TailCallRuntime(Runtime::kHasInPrototypeChain); |
| 2330 | 2329 |
| 2331 // Slow-case: Call the %InstanceOf runtime function. | 2330 // Slow-case: Call the %InstanceOf runtime function. |
| 2332 __ bind(&slow_case); | 2331 __ bind(&slow_case); |
| 2333 __ PopReturnAddressTo(scratch); | 2332 __ PopReturnAddressTo(scratch); |
| 2334 __ Push(object); | 2333 __ Push(object); |
| 2335 __ Push(function); | 2334 __ Push(function); |
| 2336 __ PushReturnAddressFrom(scratch); | 2335 __ PushReturnAddressFrom(scratch); |
| 2337 __ TailCallRuntime(Runtime::kInstanceOf, 2); | 2336 __ TailCallRuntime(Runtime::kInstanceOf); |
| 2338 } | 2337 } |
| 2339 | 2338 |
| 2340 | 2339 |
| 2341 // ------------------------------------------------------------------------- | 2340 // ------------------------------------------------------------------------- |
| 2342 // StringCharCodeAtGenerator | 2341 // StringCharCodeAtGenerator |
| 2343 | 2342 |
| 2344 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2343 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
| 2345 // If the receiver is a smi trigger the non-string case. | 2344 // If the receiver is a smi trigger the non-string case. |
| 2346 if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 2345 if (check_mode_ == RECEIVER_IS_UNKNOWN) { |
| 2347 __ JumpIfSmi(object_, receiver_not_string_); | 2346 __ JumpIfSmi(object_, receiver_not_string_); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2386 index_not_number_, | 2385 index_not_number_, |
| 2387 DONT_DO_SMI_CHECK); | 2386 DONT_DO_SMI_CHECK); |
| 2388 call_helper.BeforeCall(masm); | 2387 call_helper.BeforeCall(masm); |
| 2389 if (embed_mode == PART_OF_IC_HANDLER) { | 2388 if (embed_mode == PART_OF_IC_HANDLER) { |
| 2390 __ push(LoadWithVectorDescriptor::VectorRegister()); | 2389 __ push(LoadWithVectorDescriptor::VectorRegister()); |
| 2391 __ push(LoadDescriptor::SlotRegister()); | 2390 __ push(LoadDescriptor::SlotRegister()); |
| 2392 } | 2391 } |
| 2393 __ push(object_); | 2392 __ push(object_); |
| 2394 __ push(index_); // Consumed by runtime conversion function. | 2393 __ push(index_); // Consumed by runtime conversion function. |
| 2395 if (index_flags_ == STRING_INDEX_IS_NUMBER) { | 2394 if (index_flags_ == STRING_INDEX_IS_NUMBER) { |
| 2396 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); | 2395 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero); |
| 2397 } else { | 2396 } else { |
| 2398 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); | 2397 DCHECK(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); |
| 2399 // NumberToSmi discards numbers that are not exact integers. | 2398 // NumberToSmi discards numbers that are not exact integers. |
| 2400 __ CallRuntime(Runtime::kNumberToSmi, 1); | 2399 __ CallRuntime(Runtime::kNumberToSmi); |
| 2401 } | 2400 } |
| 2402 if (!index_.is(eax)) { | 2401 if (!index_.is(eax)) { |
| 2403 // Save the conversion result before the pop instructions below | 2402 // Save the conversion result before the pop instructions below |
| 2404 // have a chance to overwrite it. | 2403 // have a chance to overwrite it. |
| 2405 __ mov(index_, eax); | 2404 __ mov(index_, eax); |
| 2406 } | 2405 } |
| 2407 __ pop(object_); | 2406 __ pop(object_); |
| 2408 if (embed_mode == PART_OF_IC_HANDLER) { | 2407 if (embed_mode == PART_OF_IC_HANDLER) { |
| 2409 __ pop(LoadDescriptor::SlotRegister()); | 2408 __ pop(LoadDescriptor::SlotRegister()); |
| 2410 __ pop(LoadWithVectorDescriptor::VectorRegister()); | 2409 __ pop(LoadWithVectorDescriptor::VectorRegister()); |
| 2411 } | 2410 } |
| 2412 // Reload the instance type. | 2411 // Reload the instance type. |
| 2413 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 2412 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
| 2414 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 2413 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
| 2415 call_helper.AfterCall(masm); | 2414 call_helper.AfterCall(masm); |
| 2416 // If index is still not a smi, it must be out of range. | 2415 // If index is still not a smi, it must be out of range. |
| 2417 STATIC_ASSERT(kSmiTag == 0); | 2416 STATIC_ASSERT(kSmiTag == 0); |
| 2418 __ JumpIfNotSmi(index_, index_out_of_range_); | 2417 __ JumpIfNotSmi(index_, index_out_of_range_); |
| 2419 // Otherwise, return to the fast path. | 2418 // Otherwise, return to the fast path. |
| 2420 __ jmp(&got_smi_index_); | 2419 __ jmp(&got_smi_index_); |
| 2421 | 2420 |
| 2422 // Call runtime. We get here when the receiver is a string and the | 2421 // Call runtime. We get here when the receiver is a string and the |
| 2423 // index is a number, but the code of getting the actual character | 2422 // index is a number, but the code of getting the actual character |
| 2424 // is too complex (e.g., when the string needs to be flattened). | 2423 // is too complex (e.g., when the string needs to be flattened). |
| 2425 __ bind(&call_runtime_); | 2424 __ bind(&call_runtime_); |
| 2426 call_helper.BeforeCall(masm); | 2425 call_helper.BeforeCall(masm); |
| 2427 __ push(object_); | 2426 __ push(object_); |
| 2428 __ SmiTag(index_); | 2427 __ SmiTag(index_); |
| 2429 __ push(index_); | 2428 __ push(index_); |
| 2430 __ CallRuntime(Runtime::kStringCharCodeAtRT, 2); | 2429 __ CallRuntime(Runtime::kStringCharCodeAtRT); |
| 2431 if (!result_.is(eax)) { | 2430 if (!result_.is(eax)) { |
| 2432 __ mov(result_, eax); | 2431 __ mov(result_, eax); |
| 2433 } | 2432 } |
| 2434 call_helper.AfterCall(masm); | 2433 call_helper.AfterCall(masm); |
| 2435 __ jmp(&exit_); | 2434 __ jmp(&exit_); |
| 2436 | 2435 |
| 2437 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); | 2436 __ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase); |
| 2438 } | 2437 } |
| 2439 | 2438 |
| 2440 | 2439 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2466 | 2465 |
| 2467 | 2466 |
| 2468 void StringCharFromCodeGenerator::GenerateSlow( | 2467 void StringCharFromCodeGenerator::GenerateSlow( |
| 2469 MacroAssembler* masm, | 2468 MacroAssembler* masm, |
| 2470 const RuntimeCallHelper& call_helper) { | 2469 const RuntimeCallHelper& call_helper) { |
| 2471 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); | 2470 __ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase); |
| 2472 | 2471 |
| 2473 __ bind(&slow_case_); | 2472 __ bind(&slow_case_); |
| 2474 call_helper.BeforeCall(masm); | 2473 call_helper.BeforeCall(masm); |
| 2475 __ push(code_); | 2474 __ push(code_); |
| 2476 __ CallRuntime(Runtime::kStringCharFromCode, 1); | 2475 __ CallRuntime(Runtime::kStringCharFromCode); |
| 2477 if (!result_.is(eax)) { | 2476 if (!result_.is(eax)) { |
| 2478 __ mov(result_, eax); | 2477 __ mov(result_, eax); |
| 2479 } | 2478 } |
| 2480 call_helper.AfterCall(masm); | 2479 call_helper.AfterCall(masm); |
| 2481 __ jmp(&exit_); | 2480 __ jmp(&exit_); |
| 2482 | 2481 |
| 2483 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); | 2482 __ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase); |
| 2484 } | 2483 } |
| 2485 | 2484 |
| 2486 | 2485 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2716 masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); | 2715 masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); |
| 2717 __ IncrementCounter(counters->sub_string_native(), 1); | 2716 __ IncrementCounter(counters->sub_string_native(), 1); |
| 2718 __ ret(3 * kPointerSize); | 2717 __ ret(3 * kPointerSize); |
| 2719 | 2718 |
| 2720 // Drop pushed values on the stack before tail call. | 2719 // Drop pushed values on the stack before tail call. |
| 2721 __ bind(&runtime_drop_two); | 2720 __ bind(&runtime_drop_two); |
| 2722 __ Drop(2); | 2721 __ Drop(2); |
| 2723 | 2722 |
| 2724 // Just jump to runtime to create the sub string. | 2723 // Just jump to runtime to create the sub string. |
| 2725 __ bind(&runtime); | 2724 __ bind(&runtime); |
| 2726 __ TailCallRuntime(Runtime::kSubString, 3); | 2725 __ TailCallRuntime(Runtime::kSubString); |
| 2727 | 2726 |
| 2728 __ bind(&single_char); | 2727 __ bind(&single_char); |
| 2729 // eax: string | 2728 // eax: string |
| 2730 // ebx: instance type | 2729 // ebx: instance type |
| 2731 // ecx: sub string length (smi) | 2730 // ecx: sub string length (smi) |
| 2732 // edx: from index (smi) | 2731 // edx: from index (smi) |
| 2733 StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime, | 2732 StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime, |
| 2734 &runtime, STRING_INDEX_IS_NUMBER, | 2733 &runtime, STRING_INDEX_IS_NUMBER, |
| 2735 RECEIVER_IS_STRING); | 2734 RECEIVER_IS_STRING); |
| 2736 generator.GenerateFast(masm); | 2735 generator.GenerateFast(masm); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2761 __ test(FieldOperand(eax, String::kHashFieldOffset), | 2760 __ test(FieldOperand(eax, String::kHashFieldOffset), |
| 2762 Immediate(String::kContainsCachedArrayIndexMask)); | 2761 Immediate(String::kContainsCachedArrayIndexMask)); |
| 2763 __ j(not_zero, &slow_string, Label::kNear); | 2762 __ j(not_zero, &slow_string, Label::kNear); |
| 2764 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | 2763 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); |
| 2765 __ IndexFromHash(eax, eax); | 2764 __ IndexFromHash(eax, eax); |
| 2766 __ Ret(); | 2765 __ Ret(); |
| 2767 __ bind(&slow_string); | 2766 __ bind(&slow_string); |
| 2768 __ pop(ecx); // Pop return address. | 2767 __ pop(ecx); // Pop return address. |
| 2769 __ push(eax); // Push argument. | 2768 __ push(eax); // Push argument. |
| 2770 __ push(ecx); // Push return address. | 2769 __ push(ecx); // Push return address. |
| 2771 __ TailCallRuntime(Runtime::kStringToNumber, 1); | 2770 __ TailCallRuntime(Runtime::kStringToNumber); |
| 2772 __ bind(¬_string); | 2771 __ bind(¬_string); |
| 2773 | 2772 |
| 2774 Label not_oddball; | 2773 Label not_oddball; |
| 2775 __ CmpInstanceType(edi, ODDBALL_TYPE); | 2774 __ CmpInstanceType(edi, ODDBALL_TYPE); |
| 2776 __ j(not_equal, ¬_oddball, Label::kNear); | 2775 __ j(not_equal, ¬_oddball, Label::kNear); |
| 2777 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 2776 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
| 2778 __ Ret(); | 2777 __ Ret(); |
| 2779 __ bind(¬_oddball); | 2778 __ bind(¬_oddball); |
| 2780 | 2779 |
| 2781 __ pop(ecx); // Pop return address. | 2780 __ pop(ecx); // Pop return address. |
| 2782 __ push(eax); // Push argument. | 2781 __ push(eax); // Push argument. |
| 2783 __ push(ecx); // Push return address. | 2782 __ push(ecx); // Push return address. |
| 2784 __ TailCallRuntime(Runtime::kToNumber, 1); | 2783 __ TailCallRuntime(Runtime::kToNumber); |
| 2785 } | 2784 } |
| 2786 | 2785 |
| 2787 | 2786 |
| 2788 void ToLengthStub::Generate(MacroAssembler* masm) { | 2787 void ToLengthStub::Generate(MacroAssembler* masm) { |
| 2789 // The ToLength stub takes on argument in eax. | 2788 // The ToLength stub takes on argument in eax. |
| 2790 Label not_smi, positive_smi; | 2789 Label not_smi, positive_smi; |
| 2791 __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); | 2790 __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); |
| 2792 STATIC_ASSERT(kSmiTag == 0); | 2791 STATIC_ASSERT(kSmiTag == 0); |
| 2793 __ test(eax, eax); | 2792 __ test(eax, eax); |
| 2794 __ j(greater_equal, &positive_smi, Label::kNear); | 2793 __ j(greater_equal, &positive_smi, Label::kNear); |
| 2795 __ xor_(eax, eax); | 2794 __ xor_(eax, eax); |
| 2796 __ bind(&positive_smi); | 2795 __ bind(&positive_smi); |
| 2797 __ Ret(); | 2796 __ Ret(); |
| 2798 __ bind(¬_smi); | 2797 __ bind(¬_smi); |
| 2799 | 2798 |
| 2800 __ pop(ecx); // Pop return address. | 2799 __ pop(ecx); // Pop return address. |
| 2801 __ push(eax); // Push argument. | 2800 __ push(eax); // Push argument. |
| 2802 __ push(ecx); // Push return address. | 2801 __ push(ecx); // Push return address. |
| 2803 __ TailCallRuntime(Runtime::kToLength, 1); | 2802 __ TailCallRuntime(Runtime::kToLength); |
| 2804 } | 2803 } |
| 2805 | 2804 |
| 2806 | 2805 |
| 2807 void ToStringStub::Generate(MacroAssembler* masm) { | 2806 void ToStringStub::Generate(MacroAssembler* masm) { |
| 2808 // The ToString stub takes one argument in eax. | 2807 // The ToString stub takes one argument in eax. |
| 2809 Label is_number; | 2808 Label is_number; |
| 2810 __ JumpIfSmi(eax, &is_number, Label::kNear); | 2809 __ JumpIfSmi(eax, &is_number, Label::kNear); |
| 2811 | 2810 |
| 2812 Label not_string; | 2811 Label not_string; |
| 2813 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); | 2812 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2828 Label not_oddball; | 2827 Label not_oddball; |
| 2829 __ CmpInstanceType(edi, ODDBALL_TYPE); | 2828 __ CmpInstanceType(edi, ODDBALL_TYPE); |
| 2830 __ j(not_equal, ¬_oddball, Label::kNear); | 2829 __ j(not_equal, ¬_oddball, Label::kNear); |
| 2831 __ mov(eax, FieldOperand(eax, Oddball::kToStringOffset)); | 2830 __ mov(eax, FieldOperand(eax, Oddball::kToStringOffset)); |
| 2832 __ Ret(); | 2831 __ Ret(); |
| 2833 __ bind(¬_oddball); | 2832 __ bind(¬_oddball); |
| 2834 | 2833 |
| 2835 __ pop(ecx); // Pop return address. | 2834 __ pop(ecx); // Pop return address. |
| 2836 __ push(eax); // Push argument. | 2835 __ push(eax); // Push argument. |
| 2837 __ push(ecx); // Push return address. | 2836 __ push(ecx); // Push return address. |
| 2838 __ TailCallRuntime(Runtime::kToString, 1); | 2837 __ TailCallRuntime(Runtime::kToString); |
| 2839 } | 2838 } |
| 2840 | 2839 |
| 2841 | 2840 |
| 2842 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, | 2841 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, |
| 2843 Register left, | 2842 Register left, |
| 2844 Register right, | 2843 Register right, |
| 2845 Register scratch1, | 2844 Register scratch1, |
| 2846 Register scratch2) { | 2845 Register scratch2) { |
| 2847 Register length = scratch1; | 2846 Register length = scratch1; |
| 2848 | 2847 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2991 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, | 2990 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, |
| 2992 edi); | 2991 edi); |
| 2993 | 2992 |
| 2994 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 2993 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 2995 // tagged as a small integer. | 2994 // tagged as a small integer. |
| 2996 __ bind(&runtime); | 2995 __ bind(&runtime); |
| 2997 __ PopReturnAddressTo(ecx); | 2996 __ PopReturnAddressTo(ecx); |
| 2998 __ Push(edx); | 2997 __ Push(edx); |
| 2999 __ Push(eax); | 2998 __ Push(eax); |
| 3000 __ PushReturnAddressFrom(ecx); | 2999 __ PushReturnAddressFrom(ecx); |
| 3001 __ TailCallRuntime(Runtime::kStringCompare, 2); | 3000 __ TailCallRuntime(Runtime::kStringCompare); |
| 3002 } | 3001 } |
| 3003 | 3002 |
| 3004 | 3003 |
| 3005 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3004 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
| 3006 // ----------- S t a t e ------------- | 3005 // ----------- S t a t e ------------- |
| 3007 // -- edx : left | 3006 // -- edx : left |
| 3008 // -- eax : right | 3007 // -- eax : right |
| 3009 // -- esp[0] : return address | 3008 // -- esp[0] : return address |
| 3010 // ----------------------------------- | 3009 // ----------------------------------- |
| 3011 | 3010 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3036 Label::Distance const miss_distance = | 3035 Label::Distance const miss_distance = |
| 3037 masm->emit_debug_code() ? Label::kFar : Label::kNear; | 3036 masm->emit_debug_code() ? Label::kFar : Label::kNear; |
| 3038 | 3037 |
| 3039 __ JumpIfSmi(edx, &miss, miss_distance); | 3038 __ JumpIfSmi(edx, &miss, miss_distance); |
| 3040 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 3039 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 3041 __ JumpIfSmi(eax, &miss, miss_distance); | 3040 __ JumpIfSmi(eax, &miss, miss_distance); |
| 3042 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3041 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3043 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3042 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
| 3044 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3043 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
| 3045 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 3044 if (op() != Token::EQ_STRICT && is_strong(strength())) { |
| 3046 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); | 3045 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); |
| 3047 } else { | 3046 } else { |
| 3048 if (!Token::IsEqualityOp(op())) { | 3047 if (!Token::IsEqualityOp(op())) { |
| 3049 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 3048 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
| 3050 __ AssertSmi(eax); | 3049 __ AssertSmi(eax); |
| 3051 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); | 3050 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); |
| 3052 __ AssertSmi(edx); | 3051 __ AssertSmi(edx); |
| 3053 __ xchg(eax, edx); | 3052 __ xchg(eax, edx); |
| 3054 } | 3053 } |
| 3055 __ sub(eax, edx); | 3054 __ sub(eax, edx); |
| 3056 __ Ret(); | 3055 __ Ret(); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3304 tmp2, tmp3); | 3303 tmp2, tmp3); |
| 3305 } | 3304 } |
| 3306 | 3305 |
| 3307 // Handle more complex cases in runtime. | 3306 // Handle more complex cases in runtime. |
| 3308 __ bind(&runtime); | 3307 __ bind(&runtime); |
| 3309 __ pop(tmp1); // Return address. | 3308 __ pop(tmp1); // Return address. |
| 3310 __ push(left); | 3309 __ push(left); |
| 3311 __ push(right); | 3310 __ push(right); |
| 3312 __ push(tmp1); | 3311 __ push(tmp1); |
| 3313 if (equality) { | 3312 if (equality) { |
| 3314 __ TailCallRuntime(Runtime::kStringEquals, 2); | 3313 __ TailCallRuntime(Runtime::kStringEquals); |
| 3315 } else { | 3314 } else { |
| 3316 __ TailCallRuntime(Runtime::kStringCompare, 2); | 3315 __ TailCallRuntime(Runtime::kStringCompare); |
| 3317 } | 3316 } |
| 3318 | 3317 |
| 3319 __ bind(&miss); | 3318 __ bind(&miss); |
| 3320 GenerateMiss(masm); | 3319 GenerateMiss(masm); |
| 3321 } | 3320 } |
| 3322 | 3321 |
| 3323 | 3322 |
| 3324 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { | 3323 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { |
| 3325 DCHECK_EQ(CompareICState::RECEIVER, state()); | 3324 DCHECK_EQ(CompareICState::RECEIVER, state()); |
| 3326 Label miss; | 3325 Label miss; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3353 __ GetWeakValue(edi, cell); | 3352 __ GetWeakValue(edi, cell); |
| 3354 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); | 3353 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3355 __ j(not_equal, &miss, Label::kNear); | 3354 __ j(not_equal, &miss, Label::kNear); |
| 3356 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 3355 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
| 3357 __ j(not_equal, &miss, Label::kNear); | 3356 __ j(not_equal, &miss, Label::kNear); |
| 3358 | 3357 |
| 3359 if (Token::IsEqualityOp(op())) { | 3358 if (Token::IsEqualityOp(op())) { |
| 3360 __ sub(eax, edx); | 3359 __ sub(eax, edx); |
| 3361 __ ret(0); | 3360 __ ret(0); |
| 3362 } else if (is_strong(strength())) { | 3361 } else if (is_strong(strength())) { |
| 3363 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); | 3362 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); |
| 3364 } else { | 3363 } else { |
| 3365 __ PopReturnAddressTo(ecx); | 3364 __ PopReturnAddressTo(ecx); |
| 3366 __ Push(edx); | 3365 __ Push(edx); |
| 3367 __ Push(eax); | 3366 __ Push(eax); |
| 3368 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); | 3367 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); |
| 3369 __ PushReturnAddressFrom(ecx); | 3368 __ PushReturnAddressFrom(ecx); |
| 3370 __ TailCallRuntime(Runtime::kCompare, 3); | 3369 __ TailCallRuntime(Runtime::kCompare); |
| 3371 } | 3370 } |
| 3372 | 3371 |
| 3373 __ bind(&miss); | 3372 __ bind(&miss); |
| 3374 GenerateMiss(masm); | 3373 GenerateMiss(masm); |
| 3375 } | 3374 } |
| 3376 | 3375 |
| 3377 | 3376 |
| 3378 void CompareICStub::GenerateMiss(MacroAssembler* masm) { | 3377 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
| 3379 { | 3378 { |
| 3380 // Call the runtime system in a fresh internal frame. | 3379 // Call the runtime system in a fresh internal frame. |
| 3381 FrameScope scope(masm, StackFrame::INTERNAL); | 3380 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3382 __ push(edx); // Preserve edx and eax. | 3381 __ push(edx); // Preserve edx and eax. |
| 3383 __ push(eax); | 3382 __ push(eax); |
| 3384 __ push(edx); // And also use them as the arguments. | 3383 __ push(edx); // And also use them as the arguments. |
| 3385 __ push(eax); | 3384 __ push(eax); |
| 3386 __ push(Immediate(Smi::FromInt(op()))); | 3385 __ push(Immediate(Smi::FromInt(op()))); |
| 3387 __ CallRuntime(Runtime::kCompareIC_Miss, 3); | 3386 __ CallRuntime(Runtime::kCompareIC_Miss); |
| 3388 // Compute the entry point of the rewritten stub. | 3387 // Compute the entry point of the rewritten stub. |
| 3389 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); | 3388 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); |
| 3390 __ pop(eax); | 3389 __ pop(eax); |
| 3391 __ pop(edx); | 3390 __ pop(edx); |
| 3392 } | 3391 } |
| 3393 | 3392 |
| 3394 // Do a tail call to the rewritten stub. | 3393 // Do a tail call to the rewritten stub. |
| 3395 __ jmp(edi); | 3394 __ jmp(edi); |
| 3396 } | 3395 } |
| 3397 | 3396 |
| (...skipping 1434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4832 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); | 4831 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); |
| 4833 __ j(equal, &slow_case, Label::kNear); | 4832 __ j(equal, &slow_case, Label::kNear); |
| 4834 __ Ret(); | 4833 __ Ret(); |
| 4835 | 4834 |
| 4836 // Fallback to the runtime. | 4835 // Fallback to the runtime. |
| 4837 __ bind(&slow_case); | 4836 __ bind(&slow_case); |
| 4838 __ SmiTag(slot_reg); | 4837 __ SmiTag(slot_reg); |
| 4839 __ Pop(result_reg); // Pop return address. | 4838 __ Pop(result_reg); // Pop return address. |
| 4840 __ Push(slot_reg); | 4839 __ Push(slot_reg); |
| 4841 __ Push(result_reg); // Push return address. | 4840 __ Push(result_reg); // Push return address. |
| 4842 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1); | 4841 __ TailCallRuntime(Runtime::kLoadGlobalViaContext); |
| 4843 } | 4842 } |
| 4844 | 4843 |
| 4845 | 4844 |
| 4846 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | 4845 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { |
| 4847 Register context_reg = esi; | 4846 Register context_reg = esi; |
| 4848 Register slot_reg = ebx; | 4847 Register slot_reg = ebx; |
| 4849 Register value_reg = eax; | 4848 Register value_reg = eax; |
| 4850 Register cell_reg = edi; | 4849 Register cell_reg = edi; |
| 4851 Register cell_details_reg = edx; | 4850 Register cell_details_reg = edx; |
| 4852 Register cell_value_reg = ecx; | 4851 Register cell_value_reg = ecx; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4955 | 4954 |
| 4956 // Fallback to the runtime. | 4955 // Fallback to the runtime. |
| 4957 __ bind(&slow_case); | 4956 __ bind(&slow_case); |
| 4958 __ SmiTag(slot_reg); | 4957 __ SmiTag(slot_reg); |
| 4959 __ Pop(cell_reg); // Pop return address. | 4958 __ Pop(cell_reg); // Pop return address. |
| 4960 __ Push(slot_reg); | 4959 __ Push(slot_reg); |
| 4961 __ Push(value_reg); | 4960 __ Push(value_reg); |
| 4962 __ Push(cell_reg); // Push return address. | 4961 __ Push(cell_reg); // Push return address. |
| 4963 __ TailCallRuntime(is_strict(language_mode()) | 4962 __ TailCallRuntime(is_strict(language_mode()) |
| 4964 ? Runtime::kStoreGlobalViaContext_Strict | 4963 ? Runtime::kStoreGlobalViaContext_Strict |
| 4965 : Runtime::kStoreGlobalViaContext_Sloppy, | 4964 : Runtime::kStoreGlobalViaContext_Sloppy); |
| 4966 2); | |
| 4967 } | 4965 } |
| 4968 | 4966 |
| 4969 | 4967 |
| 4970 // Generates an Operand for saving parameters after PrepareCallApiFunction. | 4968 // Generates an Operand for saving parameters after PrepareCallApiFunction. |
| 4971 static Operand ApiParameterOperand(int index) { | 4969 static Operand ApiParameterOperand(int index) { |
| 4972 return Operand(esp, index * kPointerSize); | 4970 return Operand(esp, index * kPointerSize); |
| 4973 } | 4971 } |
| 4974 | 4972 |
| 4975 | 4973 |
| 4976 // Prepares stack to put arguments (aligns and so on). Reserves | 4974 // Prepares stack to put arguments (aligns and so on). Reserves |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5127 DCHECK_EQ(0, stack_space); | 5125 DCHECK_EQ(0, stack_space); |
| 5128 __ pop(ecx); | 5126 __ pop(ecx); |
| 5129 __ add(esp, ebx); | 5127 __ add(esp, ebx); |
| 5130 __ jmp(ecx); | 5128 __ jmp(ecx); |
| 5131 } else { | 5129 } else { |
| 5132 __ ret(stack_space * kPointerSize); | 5130 __ ret(stack_space * kPointerSize); |
| 5133 } | 5131 } |
| 5134 | 5132 |
| 5135 // Re-throw by promoting a scheduled exception. | 5133 // Re-throw by promoting a scheduled exception. |
| 5136 __ bind(&promote_scheduled_exception); | 5134 __ bind(&promote_scheduled_exception); |
| 5137 __ TailCallRuntime(Runtime::kPromoteScheduledException, 0); | 5135 __ TailCallRuntime(Runtime::kPromoteScheduledException); |
| 5138 | 5136 |
| 5139 // HandleScope limit has changed. Delete allocated extensions. | 5137 // HandleScope limit has changed. Delete allocated extensions. |
| 5140 ExternalReference delete_extensions = | 5138 ExternalReference delete_extensions = |
| 5141 ExternalReference::delete_handle_scope_extensions(isolate); | 5139 ExternalReference::delete_handle_scope_extensions(isolate); |
| 5142 __ bind(&delete_allocated_handles); | 5140 __ bind(&delete_allocated_handles); |
| 5143 __ mov(Operand::StaticVariable(limit_address), edi); | 5141 __ mov(Operand::StaticVariable(limit_address), edi); |
| 5144 __ mov(edi, eax); | 5142 __ mov(edi, eax); |
| 5145 __ mov(Operand(esp, 0), | 5143 __ mov(Operand(esp, 0), |
| 5146 Immediate(ExternalReference::isolate_address(isolate))); | 5144 Immediate(ExternalReference::isolate_address(isolate))); |
| 5147 __ mov(eax, Immediate(delete_extensions)); | 5145 __ mov(eax, Immediate(delete_extensions)); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5350 Operand(ebp, 7 * kPointerSize), NULL); | 5348 Operand(ebp, 7 * kPointerSize), NULL); |
| 5351 } | 5349 } |
| 5352 | 5350 |
| 5353 | 5351 |
| 5354 #undef __ | 5352 #undef __ |
| 5355 | 5353 |
| 5356 } // namespace internal | 5354 } // namespace internal |
| 5357 } // namespace v8 | 5355 } // namespace v8 |
| 5358 | 5356 |
| 5359 #endif // V8_TARGET_ARCH_X87 | 5357 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |