OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 // Return and remove the on-stack parameters. | 235 // Return and remove the on-stack parameters. |
236 __ ret(3 * kPointerSize); | 236 __ ret(3 * kPointerSize); |
237 | 237 |
238 __ bind(&slow_case); | 238 __ bind(&slow_case); |
239 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); | 239 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). | 243 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). |
244 void ToBooleanStub::Generate(MacroAssembler* masm) { | 244 void ToBooleanStub::Generate(MacroAssembler* masm) { |
245 // This stub overrides SometimesSetsUpAFrame() to return false. That means | |
246 // we cannot call anything that could cause a GC from this stub. | |
247 Label false_result, true_result, not_string; | 245 Label false_result, true_result, not_string; |
248 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 246 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
249 Factory* factory = masm->isolate()->factory(); | 247 Factory* factory = masm->isolate()->factory(); |
250 | 248 |
251 // undefined -> false | 249 // undefined -> false |
252 __ cmp(eax, factory->undefined_value()); | 250 __ cmp(eax, factory->undefined_value()); |
253 __ j(equal, &false_result); | 251 __ j(equal, &false_result); |
254 | 252 |
255 // Boolean -> its value | 253 // Boolean -> its value |
256 __ cmp(eax, factory->true_value()); | 254 __ cmp(eax, factory->true_value()); |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 Immediate(HeapNumber::kSignMask)); // Flip sign. | 714 Immediate(HeapNumber::kSignMask)); // Flip sign. |
717 } else { | 715 } else { |
718 __ mov(edx, Operand(eax)); | 716 __ mov(edx, Operand(eax)); |
719 // edx: operand | 717 // edx: operand |
720 | 718 |
721 Label slow_allocate_heapnumber, heapnumber_allocated; | 719 Label slow_allocate_heapnumber, heapnumber_allocated; |
722 __ AllocateHeapNumber(eax, ebx, ecx, &slow_allocate_heapnumber); | 720 __ AllocateHeapNumber(eax, ebx, ecx, &slow_allocate_heapnumber); |
723 __ jmp(&heapnumber_allocated); | 721 __ jmp(&heapnumber_allocated); |
724 | 722 |
725 __ bind(&slow_allocate_heapnumber); | 723 __ bind(&slow_allocate_heapnumber); |
726 { | 724 __ EnterInternalFrame(); |
727 FrameScope scope(masm, StackFrame::INTERNAL); | 725 __ push(edx); |
728 __ push(edx); | 726 __ CallRuntime(Runtime::kNumberAlloc, 0); |
729 __ CallRuntime(Runtime::kNumberAlloc, 0); | 727 __ pop(edx); |
730 __ pop(edx); | 728 __ LeaveInternalFrame(); |
731 } | |
732 | 729 |
733 __ bind(&heapnumber_allocated); | 730 __ bind(&heapnumber_allocated); |
734 // eax: allocated 'empty' number | 731 // eax: allocated 'empty' number |
735 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 732 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
736 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | 733 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. |
737 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | 734 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); |
738 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | 735 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); |
739 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 736 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
740 } | 737 } |
741 __ ret(0); | 738 __ ret(0); |
(...skipping 22 matching lines...) Expand all Loading... |
764 | 761 |
765 // Try to store the result in a heap number. | 762 // Try to store the result in a heap number. |
766 __ bind(&try_float); | 763 __ bind(&try_float); |
767 if (mode_ == UNARY_NO_OVERWRITE) { | 764 if (mode_ == UNARY_NO_OVERWRITE) { |
768 Label slow_allocate_heapnumber, heapnumber_allocated; | 765 Label slow_allocate_heapnumber, heapnumber_allocated; |
769 __ mov(ebx, eax); | 766 __ mov(ebx, eax); |
770 __ AllocateHeapNumber(eax, edx, edi, &slow_allocate_heapnumber); | 767 __ AllocateHeapNumber(eax, edx, edi, &slow_allocate_heapnumber); |
771 __ jmp(&heapnumber_allocated); | 768 __ jmp(&heapnumber_allocated); |
772 | 769 |
773 __ bind(&slow_allocate_heapnumber); | 770 __ bind(&slow_allocate_heapnumber); |
774 { | 771 __ EnterInternalFrame(); |
775 FrameScope scope(masm, StackFrame::INTERNAL); | 772 // Push the original HeapNumber on the stack. The integer value can't |
776 // Push the original HeapNumber on the stack. The integer value can't | 773 // be stored since it's untagged and not in the smi range (so we can't |
777 // be stored since it's untagged and not in the smi range (so we can't | 774 // smi-tag it). We'll recalculate the value after the GC instead. |
778 // smi-tag it). We'll recalculate the value after the GC instead. | 775 __ push(ebx); |
779 __ push(ebx); | 776 __ CallRuntime(Runtime::kNumberAlloc, 0); |
780 __ CallRuntime(Runtime::kNumberAlloc, 0); | 777 // New HeapNumber is in eax. |
781 // New HeapNumber is in eax. | 778 __ pop(edx); |
782 __ pop(edx); | 779 __ LeaveInternalFrame(); |
783 } | |
784 // IntegerConvert uses ebx and edi as scratch registers. | 780 // IntegerConvert uses ebx and edi as scratch registers. |
785 // This conversion won't go slow-case. | 781 // This conversion won't go slow-case. |
786 IntegerConvert(masm, edx, CpuFeatures::IsSupported(SSE3), slow); | 782 IntegerConvert(masm, edx, CpuFeatures::IsSupported(SSE3), slow); |
787 __ not_(ecx); | 783 __ not_(ecx); |
788 | 784 |
789 __ bind(&heapnumber_allocated); | 785 __ bind(&heapnumber_allocated); |
790 } | 786 } |
791 if (CpuFeatures::IsSupported(SSE2)) { | 787 if (CpuFeatures::IsSupported(SSE2)) { |
792 CpuFeatures::Scope use_sse2(SSE2); | 788 CpuFeatures::Scope use_sse2(SSE2); |
793 __ cvtsi2sd(xmm0, Operand(ecx)); | 789 __ cvtsi2sd(xmm0, Operand(ecx)); |
(...skipping 1491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2285 __ bind(&skip_cache); | 2281 __ bind(&skip_cache); |
2286 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2282 __ sub(Operand(esp), Immediate(kDoubleSize)); |
2287 __ movdbl(Operand(esp, 0), xmm1); | 2283 __ movdbl(Operand(esp, 0), xmm1); |
2288 __ fld_d(Operand(esp, 0)); | 2284 __ fld_d(Operand(esp, 0)); |
2289 GenerateOperation(masm); | 2285 GenerateOperation(masm); |
2290 __ fstp_d(Operand(esp, 0)); | 2286 __ fstp_d(Operand(esp, 0)); |
2291 __ movdbl(xmm1, Operand(esp, 0)); | 2287 __ movdbl(xmm1, Operand(esp, 0)); |
2292 __ add(Operand(esp), Immediate(kDoubleSize)); | 2288 __ add(Operand(esp), Immediate(kDoubleSize)); |
2293 // We return the value in xmm1 without adding it to the cache, but | 2289 // We return the value in xmm1 without adding it to the cache, but |
2294 // we cause a scavenging GC so that future allocations will succeed. | 2290 // we cause a scavenging GC so that future allocations will succeed. |
2295 { | 2291 __ EnterInternalFrame(); |
2296 FrameScope scope(masm, StackFrame::INTERNAL); | 2292 // Allocate an unused object bigger than a HeapNumber. |
2297 // Allocate an unused object bigger than a HeapNumber. | 2293 __ push(Immediate(Smi::FromInt(2 * kDoubleSize))); |
2298 __ push(Immediate(Smi::FromInt(2 * kDoubleSize))); | 2294 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); |
2299 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace); | 2295 __ LeaveInternalFrame(); |
2300 } | |
2301 __ Ret(); | 2296 __ Ret(); |
2302 } | 2297 } |
2303 | 2298 |
2304 // Call runtime, doing whatever allocation and cleanup is necessary. | 2299 // Call runtime, doing whatever allocation and cleanup is necessary. |
2305 if (tagged) { | 2300 if (tagged) { |
2306 __ bind(&runtime_call_clear_stack); | 2301 __ bind(&runtime_call_clear_stack); |
2307 __ fstp(0); | 2302 __ fstp(0); |
2308 __ bind(&runtime_call); | 2303 __ bind(&runtime_call); |
2309 ExternalReference runtime = | 2304 ExternalReference runtime = |
2310 ExternalReference(RuntimeFunction(), masm->isolate()); | 2305 ExternalReference(RuntimeFunction(), masm->isolate()); |
2311 __ TailCallExternalReference(runtime, 1, 1); | 2306 __ TailCallExternalReference(runtime, 1, 1); |
2312 } else { // UNTAGGED. | 2307 } else { // UNTAGGED. |
2313 __ bind(&runtime_call_clear_stack); | 2308 __ bind(&runtime_call_clear_stack); |
2314 __ bind(&runtime_call); | 2309 __ bind(&runtime_call); |
2315 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); | 2310 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); |
2316 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); | 2311 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); |
2317 { | 2312 __ EnterInternalFrame(); |
2318 FrameScope scope(masm, StackFrame::INTERNAL); | 2313 __ push(eax); |
2319 __ push(eax); | 2314 __ CallRuntime(RuntimeFunction(), 1); |
2320 __ CallRuntime(RuntimeFunction(), 1); | 2315 __ LeaveInternalFrame(); |
2321 } | |
2322 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2316 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
2323 __ Ret(); | 2317 __ Ret(); |
2324 } | 2318 } |
2325 } | 2319 } |
2326 | 2320 |
2327 | 2321 |
2328 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { | 2322 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { |
2329 switch (type_) { | 2323 switch (type_) { |
2330 case TranscendentalCache::SIN: return Runtime::kMath_sin; | 2324 case TranscendentalCache::SIN: return Runtime::kMath_sin; |
2331 case TranscendentalCache::COS: return Runtime::kMath_cos; | 2325 case TranscendentalCache::COS: return Runtime::kMath_cos; |
(...skipping 2192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4524 if (HasArgsInRegisters()) { | 4518 if (HasArgsInRegisters()) { |
4525 // Push arguments below return address. | 4519 // Push arguments below return address. |
4526 __ pop(scratch); | 4520 __ pop(scratch); |
4527 __ push(object); | 4521 __ push(object); |
4528 __ push(function); | 4522 __ push(function); |
4529 __ push(scratch); | 4523 __ push(scratch); |
4530 } | 4524 } |
4531 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 4525 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
4532 } else { | 4526 } else { |
4533 // Call the builtin and convert 0/1 to true/false. | 4527 // Call the builtin and convert 0/1 to true/false. |
4534 { | 4528 __ EnterInternalFrame(); |
4535 FrameScope scope(masm, StackFrame::INTERNAL); | 4529 __ push(object); |
4536 __ push(object); | 4530 __ push(function); |
4537 __ push(function); | 4531 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); |
4538 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); | 4532 __ LeaveInternalFrame(); |
4539 } | |
4540 Label true_value, done; | 4533 Label true_value, done; |
4541 __ test(eax, Operand(eax)); | 4534 __ test(eax, Operand(eax)); |
4542 __ j(zero, &true_value, Label::kNear); | 4535 __ j(zero, &true_value, Label::kNear); |
4543 __ mov(eax, factory->false_value()); | 4536 __ mov(eax, factory->false_value()); |
4544 __ jmp(&done, Label::kNear); | 4537 __ jmp(&done, Label::kNear); |
4545 __ bind(&true_value); | 4538 __ bind(&true_value); |
4546 __ mov(eax, factory->true_value()); | 4539 __ mov(eax, factory->true_value()); |
4547 __ bind(&done); | 4540 __ bind(&done); |
4548 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4541 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4549 } | 4542 } |
(...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5959 } | 5952 } |
5960 | 5953 |
5961 | 5954 |
5962 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { | 5955 void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
5963 // Save the registers. | 5956 // Save the registers. |
5964 __ pop(ecx); | 5957 __ pop(ecx); |
5965 __ push(edx); | 5958 __ push(edx); |
5966 __ push(eax); | 5959 __ push(eax); |
5967 __ push(ecx); | 5960 __ push(ecx); |
5968 | 5961 |
5969 { | 5962 // Call the runtime system in a fresh internal frame. |
5970 // Call the runtime system in a fresh internal frame. | 5963 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), |
5971 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss), | 5964 masm->isolate()); |
5972 masm->isolate()); | 5965 __ EnterInternalFrame(); |
5973 FrameScope scope(masm, StackFrame::INTERNAL); | 5966 __ push(edx); |
5974 __ push(edx); | 5967 __ push(eax); |
5975 __ push(eax); | 5968 __ push(Immediate(Smi::FromInt(op_))); |
5976 __ push(Immediate(Smi::FromInt(op_))); | 5969 __ CallExternalReference(miss, 3); |
5977 __ CallExternalReference(miss, 3); | 5970 __ LeaveInternalFrame(); |
5978 } | |
5979 | 5971 |
5980 // Compute the entry point of the rewritten stub. | 5972 // Compute the entry point of the rewritten stub. |
5981 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); | 5973 __ lea(edi, FieldOperand(eax, Code::kHeaderSize)); |
5982 | 5974 |
5983 // Restore registers. | 5975 // Restore registers. |
5984 __ pop(ecx); | 5976 __ pop(ecx); |
5985 __ pop(eax); | 5977 __ pop(eax); |
5986 __ pop(edx); | 5978 __ pop(edx); |
5987 __ push(ecx); | 5979 __ push(ecx); |
5988 | 5980 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6109 __ push(r0); | 6101 __ push(r0); |
6110 __ CallStub(&stub); | 6102 __ CallStub(&stub); |
6111 | 6103 |
6112 __ test(r1, Operand(r1)); | 6104 __ test(r1, Operand(r1)); |
6113 __ j(zero, miss); | 6105 __ j(zero, miss); |
6114 __ jmp(done); | 6106 __ jmp(done); |
6115 } | 6107 } |
6116 | 6108 |
6117 | 6109 |
6118 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { | 6110 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { |
6119 // This stub overrides SometimesSetsUpAFrame() to return false. That means | |
6120 // we cannot call anything that could cause a GC from this stub. | |
6121 // Stack frame on entry: | 6111 // Stack frame on entry: |
6122 // esp[0 * kPointerSize]: return address. | 6112 // esp[0 * kPointerSize]: return address. |
6123 // esp[1 * kPointerSize]: key's hash. | 6113 // esp[1 * kPointerSize]: key's hash. |
6124 // esp[2 * kPointerSize]: key. | 6114 // esp[2 * kPointerSize]: key. |
6125 // Registers: | 6115 // Registers: |
6126 // dictionary_: StringDictionary to probe. | 6116 // dictionary_: StringDictionary to probe. |
6127 // result_: used as scratch. | 6117 // result_: used as scratch. |
6128 // index_: will hold an index of entry if lookup is successful. | 6118 // index_: will hold an index of entry if lookup is successful. |
6129 // might alias with result_. | 6119 // might alias with result_. |
6130 // Returns: | 6120 // Returns: |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6203 __ Drop(1); | 6193 __ Drop(1); |
6204 __ ret(2 * kPointerSize); | 6194 __ ret(2 * kPointerSize); |
6205 } | 6195 } |
6206 | 6196 |
6207 | 6197 |
6208 #undef __ | 6198 #undef __ |
6209 | 6199 |
6210 } } // namespace v8::internal | 6200 } } // namespace v8::internal |
6211 | 6201 |
6212 #endif // V8_TARGET_ARCH_IA32 | 6202 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |