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, 1); | 337 __ TailCallRuntime(Runtime::kMathPowRT, 2); |
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, 1); | 391 __ TailCallRuntime(Runtime::kLoadElementWithInterceptor, 2); |
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, 1); | 491 __ TailCallRuntime(Runtime::kArguments, 1); |
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, 1); | 523 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); |
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, 1); | 758 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3); |
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, 1); | 852 __ TailCallRuntime(Runtime::kNewStrictArguments, 3); |
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, 1); | 878 __ TailCallRuntime(Runtime::kNewRestParam, 4); |
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, 1); | 887 __ TailCallRuntime(Runtime::kRegExpExec, 4); |
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, 1); | 1165 __ TailCallRuntime(Runtime::kRegExpExecReThrow, 4); |
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, 1); | 1251 __ TailCallRuntime(Runtime::kRegExpExec, 4); |
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, 2); |
1617 1); | |
1618 } else { | 1617 } else { |
1619 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 1618 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
1620 | 1619 |
1621 // Restore return address on the stack. | 1620 // Restore return address on the stack. |
1622 __ push(ecx); | 1621 __ push(ecx); |
1623 | 1622 |
1624 // 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) |
1625 // tagged as a small integer. | 1624 // tagged as a small integer. |
1626 __ TailCallRuntime( | 1625 __ TailCallRuntime( |
1627 is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, 3, | 1626 is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, |
1628 1); | 1627 3); |
1629 } | 1628 } |
1630 | 1629 |
1631 __ bind(&miss); | 1630 __ bind(&miss); |
1632 GenerateMiss(masm); | 1631 GenerateMiss(masm); |
1633 } | 1632 } |
1634 | 1633 |
1635 | 1634 |
1636 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1635 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
1637 // eax : number of arguments to the construct function | 1636 // eax : number of arguments to the construct function |
1638 // ebx : feedback vector | 1637 // ebx : feedback vector |
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2320 | 2319 |
2321 // Found Proxy or access check needed: Call the runtime. | 2320 // Found Proxy or access check needed: Call the runtime. |
2322 __ bind(&fast_runtime_fallback); | 2321 __ bind(&fast_runtime_fallback); |
2323 __ PopReturnAddressTo(scratch); | 2322 __ PopReturnAddressTo(scratch); |
2324 __ Push(object); | 2323 __ Push(object); |
2325 __ Push(function_prototype); | 2324 __ Push(function_prototype); |
2326 __ PushReturnAddressFrom(scratch); | 2325 __ PushReturnAddressFrom(scratch); |
2327 // Invalidate the instanceof cache. | 2326 // Invalidate the instanceof cache. |
2328 __ Move(eax, Immediate(Smi::FromInt(0))); | 2327 __ Move(eax, Immediate(Smi::FromInt(0))); |
2329 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); | 2328 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheFunctionRootIndex); |
2330 __ TailCallRuntime(Runtime::kHasInPrototypeChain, 2, 1); | 2329 __ TailCallRuntime(Runtime::kHasInPrototypeChain, 2); |
2331 | 2330 |
2332 // Slow-case: Call the %InstanceOf runtime function. | 2331 // Slow-case: Call the %InstanceOf runtime function. |
2333 __ bind(&slow_case); | 2332 __ bind(&slow_case); |
2334 __ PopReturnAddressTo(scratch); | 2333 __ PopReturnAddressTo(scratch); |
2335 __ Push(object); | 2334 __ Push(object); |
2336 __ Push(function); | 2335 __ Push(function); |
2337 __ PushReturnAddressFrom(scratch); | 2336 __ PushReturnAddressFrom(scratch); |
2338 __ TailCallRuntime(Runtime::kInstanceOf, 2, 1); | 2337 __ TailCallRuntime(Runtime::kInstanceOf, 2); |
2339 } | 2338 } |
2340 | 2339 |
2341 | 2340 |
2342 // ------------------------------------------------------------------------- | 2341 // ------------------------------------------------------------------------- |
2343 // StringCharCodeAtGenerator | 2342 // StringCharCodeAtGenerator |
2344 | 2343 |
2345 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2344 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
2346 // If the receiver is a smi trigger the non-string case. | 2345 // If the receiver is a smi trigger the non-string case. |
2347 if (check_mode_ == RECEIVER_IS_UNKNOWN) { | 2346 if (check_mode_ == RECEIVER_IS_UNKNOWN) { |
2348 __ JumpIfSmi(object_, receiver_not_string_); | 2347 __ JumpIfSmi(object_, receiver_not_string_); |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2717 masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); | 2716 masm, edi, edx, ecx, ebx, String::TWO_BYTE_ENCODING); |
2718 __ IncrementCounter(counters->sub_string_native(), 1); | 2717 __ IncrementCounter(counters->sub_string_native(), 1); |
2719 __ ret(3 * kPointerSize); | 2718 __ ret(3 * kPointerSize); |
2720 | 2719 |
2721 // Drop pushed values on the stack before tail call. | 2720 // Drop pushed values on the stack before tail call. |
2722 __ bind(&runtime_drop_two); | 2721 __ bind(&runtime_drop_two); |
2723 __ Drop(2); | 2722 __ Drop(2); |
2724 | 2723 |
2725 // Just jump to runtime to create the sub string. | 2724 // Just jump to runtime to create the sub string. |
2726 __ bind(&runtime); | 2725 __ bind(&runtime); |
2727 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 2726 __ TailCallRuntime(Runtime::kSubString, 3); |
2728 | 2727 |
2729 __ bind(&single_char); | 2728 __ bind(&single_char); |
2730 // eax: string | 2729 // eax: string |
2731 // ebx: instance type | 2730 // ebx: instance type |
2732 // ecx: sub string length (smi) | 2731 // ecx: sub string length (smi) |
2733 // edx: from index (smi) | 2732 // edx: from index (smi) |
2734 StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime, | 2733 StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime, |
2735 &runtime, STRING_INDEX_IS_NUMBER, | 2734 &runtime, STRING_INDEX_IS_NUMBER, |
2736 RECEIVER_IS_STRING); | 2735 RECEIVER_IS_STRING); |
2737 generator.GenerateFast(masm); | 2736 generator.GenerateFast(masm); |
(...skipping 24 matching lines...) Expand all Loading... |
2762 __ test(FieldOperand(eax, String::kHashFieldOffset), | 2761 __ test(FieldOperand(eax, String::kHashFieldOffset), |
2763 Immediate(String::kContainsCachedArrayIndexMask)); | 2762 Immediate(String::kContainsCachedArrayIndexMask)); |
2764 __ j(not_zero, &slow_string, Label::kNear); | 2763 __ j(not_zero, &slow_string, Label::kNear); |
2765 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); | 2764 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); |
2766 __ IndexFromHash(eax, eax); | 2765 __ IndexFromHash(eax, eax); |
2767 __ Ret(); | 2766 __ Ret(); |
2768 __ bind(&slow_string); | 2767 __ bind(&slow_string); |
2769 __ pop(ecx); // Pop return address. | 2768 __ pop(ecx); // Pop return address. |
2770 __ push(eax); // Push argument. | 2769 __ push(eax); // Push argument. |
2771 __ push(ecx); // Push return address. | 2770 __ push(ecx); // Push return address. |
2772 __ TailCallRuntime(Runtime::kStringToNumber, 1, 1); | 2771 __ TailCallRuntime(Runtime::kStringToNumber, 1); |
2773 __ bind(¬_string); | 2772 __ bind(¬_string); |
2774 | 2773 |
2775 Label not_oddball; | 2774 Label not_oddball; |
2776 __ CmpInstanceType(edi, ODDBALL_TYPE); | 2775 __ CmpInstanceType(edi, ODDBALL_TYPE); |
2777 __ j(not_equal, ¬_oddball, Label::kNear); | 2776 __ j(not_equal, ¬_oddball, Label::kNear); |
2778 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 2777 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
2779 __ Ret(); | 2778 __ Ret(); |
2780 __ bind(¬_oddball); | 2779 __ bind(¬_oddball); |
2781 | 2780 |
2782 __ pop(ecx); // Pop return address. | 2781 __ pop(ecx); // Pop return address. |
2783 __ push(eax); // Push argument. | 2782 __ push(eax); // Push argument. |
2784 __ push(ecx); // Push return address. | 2783 __ push(ecx); // Push return address. |
2785 __ TailCallRuntime(Runtime::kToNumber, 1, 1); | 2784 __ TailCallRuntime(Runtime::kToNumber, 1); |
2786 } | 2785 } |
2787 | 2786 |
2788 | 2787 |
2789 void ToLengthStub::Generate(MacroAssembler* masm) { | 2788 void ToLengthStub::Generate(MacroAssembler* masm) { |
2790 // The ToLength stub takes on argument in eax. | 2789 // The ToLength stub takes on argument in eax. |
2791 Label not_smi, positive_smi; | 2790 Label not_smi, positive_smi; |
2792 __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); | 2791 __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); |
2793 STATIC_ASSERT(kSmiTag == 0); | 2792 STATIC_ASSERT(kSmiTag == 0); |
2794 __ test(eax, eax); | 2793 __ test(eax, eax); |
2795 __ j(greater_equal, &positive_smi, Label::kNear); | 2794 __ j(greater_equal, &positive_smi, Label::kNear); |
2796 __ xor_(eax, eax); | 2795 __ xor_(eax, eax); |
2797 __ bind(&positive_smi); | 2796 __ bind(&positive_smi); |
2798 __ Ret(); | 2797 __ Ret(); |
2799 __ bind(¬_smi); | 2798 __ bind(¬_smi); |
2800 | 2799 |
2801 __ pop(ecx); // Pop return address. | 2800 __ pop(ecx); // Pop return address. |
2802 __ push(eax); // Push argument. | 2801 __ push(eax); // Push argument. |
2803 __ push(ecx); // Push return address. | 2802 __ push(ecx); // Push return address. |
2804 __ TailCallRuntime(Runtime::kToLength, 1, 1); | 2803 __ TailCallRuntime(Runtime::kToLength, 1); |
2805 } | 2804 } |
2806 | 2805 |
2807 | 2806 |
2808 void ToStringStub::Generate(MacroAssembler* masm) { | 2807 void ToStringStub::Generate(MacroAssembler* masm) { |
2809 // The ToString stub takes one argument in eax. | 2808 // The ToString stub takes one argument in eax. |
2810 Label is_number; | 2809 Label is_number; |
2811 __ JumpIfSmi(eax, &is_number, Label::kNear); | 2810 __ JumpIfSmi(eax, &is_number, Label::kNear); |
2812 | 2811 |
2813 Label not_string; | 2812 Label not_string; |
2814 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); | 2813 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi); |
(...skipping 14 matching lines...) Expand all Loading... |
2829 Label not_oddball; | 2828 Label not_oddball; |
2830 __ CmpInstanceType(edi, ODDBALL_TYPE); | 2829 __ CmpInstanceType(edi, ODDBALL_TYPE); |
2831 __ j(not_equal, ¬_oddball, Label::kNear); | 2830 __ j(not_equal, ¬_oddball, Label::kNear); |
2832 __ mov(eax, FieldOperand(eax, Oddball::kToStringOffset)); | 2831 __ mov(eax, FieldOperand(eax, Oddball::kToStringOffset)); |
2833 __ Ret(); | 2832 __ Ret(); |
2834 __ bind(¬_oddball); | 2833 __ bind(¬_oddball); |
2835 | 2834 |
2836 __ pop(ecx); // Pop return address. | 2835 __ pop(ecx); // Pop return address. |
2837 __ push(eax); // Push argument. | 2836 __ push(eax); // Push argument. |
2838 __ push(ecx); // Push return address. | 2837 __ push(ecx); // Push return address. |
2839 __ TailCallRuntime(Runtime::kToString, 1, 1); | 2838 __ TailCallRuntime(Runtime::kToString, 1); |
2840 } | 2839 } |
2841 | 2840 |
2842 | 2841 |
2843 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, | 2842 void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm, |
2844 Register left, | 2843 Register left, |
2845 Register right, | 2844 Register right, |
2846 Register scratch1, | 2845 Register scratch1, |
2847 Register scratch2) { | 2846 Register scratch2) { |
2848 Register length = scratch1; | 2847 Register length = scratch1; |
2849 | 2848 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2992 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, | 2991 StringHelper::GenerateCompareFlatOneByteStrings(masm, edx, eax, ecx, ebx, |
2993 edi); | 2992 edi); |
2994 | 2993 |
2995 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 2994 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
2996 // tagged as a small integer. | 2995 // tagged as a small integer. |
2997 __ bind(&runtime); | 2996 __ bind(&runtime); |
2998 __ PopReturnAddressTo(ecx); | 2997 __ PopReturnAddressTo(ecx); |
2999 __ Push(edx); | 2998 __ Push(edx); |
3000 __ Push(eax); | 2999 __ Push(eax); |
3001 __ PushReturnAddressFrom(ecx); | 3000 __ PushReturnAddressFrom(ecx); |
3002 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3001 __ TailCallRuntime(Runtime::kStringCompare, 2); |
3003 } | 3002 } |
3004 | 3003 |
3005 | 3004 |
3006 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3005 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
3007 // ----------- S t a t e ------------- | 3006 // ----------- S t a t e ------------- |
3008 // -- edx : left | 3007 // -- edx : left |
3009 // -- eax : right | 3008 // -- eax : right |
3010 // -- esp[0] : return address | 3009 // -- esp[0] : return address |
3011 // ----------------------------------- | 3010 // ----------------------------------- |
3012 | 3011 |
(...skipping 24 matching lines...) Expand all Loading... |
3037 Label::Distance const miss_distance = | 3036 Label::Distance const miss_distance = |
3038 masm->emit_debug_code() ? Label::kFar : Label::kNear; | 3037 masm->emit_debug_code() ? Label::kFar : Label::kNear; |
3039 | 3038 |
3040 __ JumpIfSmi(edx, &miss, miss_distance); | 3039 __ JumpIfSmi(edx, &miss, miss_distance); |
3041 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 3040 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
3042 __ JumpIfSmi(eax, &miss, miss_distance); | 3041 __ JumpIfSmi(eax, &miss, miss_distance); |
3043 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3042 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3044 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3043 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
3045 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3044 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
3046 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 3045 if (op() != Token::EQ_STRICT && is_strong(strength())) { |
3047 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1); | 3046 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); |
3048 } else { | 3047 } else { |
3049 if (!Token::IsEqualityOp(op())) { | 3048 if (!Token::IsEqualityOp(op())) { |
3050 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 3049 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
3051 __ AssertSmi(eax); | 3050 __ AssertSmi(eax); |
3052 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); | 3051 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); |
3053 __ AssertSmi(edx); | 3052 __ AssertSmi(edx); |
3054 __ xchg(eax, edx); | 3053 __ xchg(eax, edx); |
3055 } | 3054 } |
3056 __ sub(eax, edx); | 3055 __ sub(eax, edx); |
3057 __ Ret(); | 3056 __ Ret(); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3305 tmp2, tmp3); | 3304 tmp2, tmp3); |
3306 } | 3305 } |
3307 | 3306 |
3308 // Handle more complex cases in runtime. | 3307 // Handle more complex cases in runtime. |
3309 __ bind(&runtime); | 3308 __ bind(&runtime); |
3310 __ pop(tmp1); // Return address. | 3309 __ pop(tmp1); // Return address. |
3311 __ push(left); | 3310 __ push(left); |
3312 __ push(right); | 3311 __ push(right); |
3313 __ push(tmp1); | 3312 __ push(tmp1); |
3314 if (equality) { | 3313 if (equality) { |
3315 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 3314 __ TailCallRuntime(Runtime::kStringEquals, 2); |
3316 } else { | 3315 } else { |
3317 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3316 __ TailCallRuntime(Runtime::kStringCompare, 2); |
3318 } | 3317 } |
3319 | 3318 |
3320 __ bind(&miss); | 3319 __ bind(&miss); |
3321 GenerateMiss(masm); | 3320 GenerateMiss(masm); |
3322 } | 3321 } |
3323 | 3322 |
3324 | 3323 |
3325 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { | 3324 void CompareICStub::GenerateReceivers(MacroAssembler* masm) { |
3326 DCHECK_EQ(CompareICState::RECEIVER, state()); | 3325 DCHECK_EQ(CompareICState::RECEIVER, state()); |
3327 Label miss; | 3326 Label miss; |
(...skipping 26 matching lines...) Expand all Loading... |
3354 __ GetWeakValue(edi, cell); | 3353 __ GetWeakValue(edi, cell); |
3355 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); | 3354 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); |
3356 __ j(not_equal, &miss, Label::kNear); | 3355 __ j(not_equal, &miss, Label::kNear); |
3357 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 3356 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
3358 __ j(not_equal, &miss, Label::kNear); | 3357 __ j(not_equal, &miss, Label::kNear); |
3359 | 3358 |
3360 if (Token::IsEqualityOp(op())) { | 3359 if (Token::IsEqualityOp(op())) { |
3361 __ sub(eax, edx); | 3360 __ sub(eax, edx); |
3362 __ ret(0); | 3361 __ ret(0); |
3363 } else if (is_strong(strength())) { | 3362 } else if (is_strong(strength())) { |
3364 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0, 1); | 3363 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion, 0); |
3365 } else { | 3364 } else { |
3366 __ PopReturnAddressTo(ecx); | 3365 __ PopReturnAddressTo(ecx); |
3367 __ Push(edx); | 3366 __ Push(edx); |
3368 __ Push(eax); | 3367 __ Push(eax); |
3369 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); | 3368 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); |
3370 __ PushReturnAddressFrom(ecx); | 3369 __ PushReturnAddressFrom(ecx); |
3371 __ TailCallRuntime(Runtime::kCompare, 3, 1); | 3370 __ TailCallRuntime(Runtime::kCompare, 3); |
3372 } | 3371 } |
3373 | 3372 |
3374 __ bind(&miss); | 3373 __ bind(&miss); |
3375 GenerateMiss(masm); | 3374 GenerateMiss(masm); |
3376 } | 3375 } |
3377 | 3376 |
3378 | 3377 |
3379 void CompareICStub::GenerateMiss(MacroAssembler* masm) { | 3378 void CompareICStub::GenerateMiss(MacroAssembler* masm) { |
3380 { | 3379 { |
3381 // Call the runtime system in a fresh internal frame. | 3380 // Call the runtime system in a fresh internal frame. |
(...skipping 1451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4833 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); | 4832 __ CompareRoot(result_reg, Heap::kTheHoleValueRootIndex); |
4834 __ j(equal, &slow_case, Label::kNear); | 4833 __ j(equal, &slow_case, Label::kNear); |
4835 __ Ret(); | 4834 __ Ret(); |
4836 | 4835 |
4837 // Fallback to the runtime. | 4836 // Fallback to the runtime. |
4838 __ bind(&slow_case); | 4837 __ bind(&slow_case); |
4839 __ SmiTag(slot_reg); | 4838 __ SmiTag(slot_reg); |
4840 __ Pop(result_reg); // Pop return address. | 4839 __ Pop(result_reg); // Pop return address. |
4841 __ Push(slot_reg); | 4840 __ Push(slot_reg); |
4842 __ Push(result_reg); // Push return address. | 4841 __ Push(result_reg); // Push return address. |
4843 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1, 1); | 4842 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1); |
4844 } | 4843 } |
4845 | 4844 |
4846 | 4845 |
4847 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | 4846 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { |
4848 Register context_reg = esi; | 4847 Register context_reg = esi; |
4849 Register slot_reg = ebx; | 4848 Register slot_reg = ebx; |
4850 Register value_reg = eax; | 4849 Register value_reg = eax; |
4851 Register cell_reg = edi; | 4850 Register cell_reg = edi; |
4852 Register cell_details_reg = edx; | 4851 Register cell_details_reg = edx; |
4853 Register cell_value_reg = ecx; | 4852 Register cell_value_reg = ecx; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4957 // Fallback to the runtime. | 4956 // Fallback to the runtime. |
4958 __ bind(&slow_case); | 4957 __ bind(&slow_case); |
4959 __ SmiTag(slot_reg); | 4958 __ SmiTag(slot_reg); |
4960 __ Pop(cell_reg); // Pop return address. | 4959 __ Pop(cell_reg); // Pop return address. |
4961 __ Push(slot_reg); | 4960 __ Push(slot_reg); |
4962 __ Push(value_reg); | 4961 __ Push(value_reg); |
4963 __ Push(cell_reg); // Push return address. | 4962 __ Push(cell_reg); // Push return address. |
4964 __ TailCallRuntime(is_strict(language_mode()) | 4963 __ TailCallRuntime(is_strict(language_mode()) |
4965 ? Runtime::kStoreGlobalViaContext_Strict | 4964 ? Runtime::kStoreGlobalViaContext_Strict |
4966 : Runtime::kStoreGlobalViaContext_Sloppy, | 4965 : Runtime::kStoreGlobalViaContext_Sloppy, |
4967 2, 1); | 4966 2); |
4968 } | 4967 } |
4969 | 4968 |
4970 | 4969 |
4971 // Generates an Operand for saving parameters after PrepareCallApiFunction. | 4970 // Generates an Operand for saving parameters after PrepareCallApiFunction. |
4972 static Operand ApiParameterOperand(int index) { | 4971 static Operand ApiParameterOperand(int index) { |
4973 return Operand(esp, index * kPointerSize); | 4972 return Operand(esp, index * kPointerSize); |
4974 } | 4973 } |
4975 | 4974 |
4976 | 4975 |
4977 // Prepares stack to put arguments (aligns and so on). Reserves | 4976 // Prepares stack to put arguments (aligns and so on). Reserves |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5128 DCHECK_EQ(0, stack_space); | 5127 DCHECK_EQ(0, stack_space); |
5129 __ pop(ecx); | 5128 __ pop(ecx); |
5130 __ add(esp, ebx); | 5129 __ add(esp, ebx); |
5131 __ jmp(ecx); | 5130 __ jmp(ecx); |
5132 } else { | 5131 } else { |
5133 __ ret(stack_space * kPointerSize); | 5132 __ ret(stack_space * kPointerSize); |
5134 } | 5133 } |
5135 | 5134 |
5136 // Re-throw by promoting a scheduled exception. | 5135 // Re-throw by promoting a scheduled exception. |
5137 __ bind(&promote_scheduled_exception); | 5136 __ bind(&promote_scheduled_exception); |
5138 __ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); | 5137 __ TailCallRuntime(Runtime::kPromoteScheduledException, 0); |
5139 | 5138 |
5140 // HandleScope limit has changed. Delete allocated extensions. | 5139 // HandleScope limit has changed. Delete allocated extensions. |
5141 ExternalReference delete_extensions = | 5140 ExternalReference delete_extensions = |
5142 ExternalReference::delete_handle_scope_extensions(isolate); | 5141 ExternalReference::delete_handle_scope_extensions(isolate); |
5143 __ bind(&delete_allocated_handles); | 5142 __ bind(&delete_allocated_handles); |
5144 __ mov(Operand::StaticVariable(limit_address), edi); | 5143 __ mov(Operand::StaticVariable(limit_address), edi); |
5145 __ mov(edi, eax); | 5144 __ mov(edi, eax); |
5146 __ mov(Operand(esp, 0), | 5145 __ mov(Operand(esp, 0), |
5147 Immediate(ExternalReference::isolate_address(isolate))); | 5146 Immediate(ExternalReference::isolate_address(isolate))); |
5148 __ mov(eax, Immediate(delete_extensions)); | 5147 __ mov(eax, Immediate(delete_extensions)); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5351 Operand(ebp, 7 * kPointerSize), NULL); | 5350 Operand(ebp, 7 * kPointerSize), NULL); |
5352 } | 5351 } |
5353 | 5352 |
5354 | 5353 |
5355 #undef __ | 5354 #undef __ |
5356 | 5355 |
5357 } // namespace internal | 5356 } // namespace internal |
5358 } // namespace v8 | 5357 } // namespace v8 |
5359 | 5358 |
5360 #endif // V8_TARGET_ARCH_X87 | 5359 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |