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