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 |