Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 5258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5269 Load(args->at(0)); | 5269 Load(args->at(0)); |
| 5270 Result value = frame_->Pop(); | 5270 Result value = frame_->Pop(); |
| 5271 value.ToRegister(); | 5271 value.ToRegister(); |
| 5272 ASSERT(value.is_valid()); | 5272 ASSERT(value.is_valid()); |
| 5273 __ test(value.reg(), Immediate(kSmiTagMask | 0x80000000)); | 5273 __ test(value.reg(), Immediate(kSmiTagMask | 0x80000000)); |
| 5274 value.Unuse(); | 5274 value.Unuse(); |
| 5275 destination()->Split(zero); | 5275 destination()->Split(zero); |
| 5276 } | 5276 } |
| 5277 | 5277 |
| 5278 | 5278 |
| 5279 // Generates the Math.pow method - only handles special cases and branches to | |
| 5280 // the runtime system if not. Uses eax to store result and as temporary reg. | |
| 5281 void CodeGenerator::GeneratePow(ZoneList<Expression*>* args) { | |
| 5282 ASSERT(args->length() == 2); | |
| 5283 if (CpuFeatures::IsSupported(SSE2)) { | |
| 5284 CpuFeatures::Scope use_sse2(SSE2); | |
| 5285 Load(args->at(0)); | |
| 5286 Load(args->at(1)); | |
| 5287 Label go_runtime; | |
| 5288 Label return_preg; | |
| 5289 Result p = allocator()->Allocate(eax); | |
| 5290 Result y = frame_->Pop(); | |
| 5291 Result x= frame_->Pop(); | |
| 5292 if (p.is_valid() && p.reg().is(eax)) { | |
| 5293 x.ToRegister(); | |
| 5294 y.ToRegister(); | |
| 5295 frame_->Spill(x.reg()); | |
| 5296 frame_->Spill(y.reg()); | |
| 5297 ASSERT(x.is_valid()); | |
| 5298 ASSERT(y.is_valid()); | |
| 5299 | |
| 5300 // Save 1 in xmm3 - we need this several times later on | |
| 5301 __ mov(p.reg(), Immediate(1)); | |
| 5302 __ cvtsi2sd(xmm3, Operand(p.reg())); | |
| 5303 | |
| 5304 Label y_nonsmi; | |
| 5305 Label x_is_double; | |
| 5306 // If y is a heap number go to that specific case. | |
| 5307 __ test(y.reg(), Immediate(kSmiTagMask)); | |
| 5308 __ j(not_zero, &y_nonsmi); | |
| 5309 __ test(x.reg(), Immediate(kSmiTagMask)); | |
| 5310 __ j(not_zero, &x_is_double); | |
| 5311 | |
| 5312 // Bot numbers are smis. | |
| 5313 Label powi; | |
| 5314 __ SmiUntag(x.reg()); | |
| 5315 __ cvtsi2sd(xmm0, Operand(x.reg())); | |
| 5316 __ jmp(&powi); | |
| 5317 // Y is smi and x is a double. | |
| 5318 __ bind(&x_is_double); | |
| 5319 __ cmp(FieldOperand(x.reg(), HeapObject::kMapOffset), | |
| 5320 Factory::heap_number_map()); | |
| 5321 __ j(not_equal, &go_runtime); | |
| 5322 __ movdbl(xmm0, FieldOperand(x.reg(), HeapNumber::kValueOffset)); | |
| 5323 | |
| 5324 __ bind(&powi); | |
| 5325 __ SmiUntag(y.reg()); | |
| 5326 | |
| 5327 // Save y in x as we need to check if y is negative later. | |
| 5328 __ mov(x.reg(), y.reg()); | |
| 5329 | |
| 5330 | |
| 5331 // Get absolute value of y. | |
| 5332 Label no_neg; | |
| 5333 __ cmp(y.reg(), 0); | |
| 5334 __ j(greater_equal, &no_neg); | |
| 5335 __ neg(y.reg()); | |
| 5336 __ bind(&no_neg); | |
| 5337 | |
| 5338 // Optimized version of pow if y is an integer. | |
| 5339 // Load xmm1 with 1. | |
| 5340 __ movsd(xmm1, xmm3); | |
| 5341 Label while_true; | |
| 5342 Label no_multiply; | |
| 5343 Label powi_done; | |
| 5344 Label allocate_and_return; | |
| 5345 __ bind(&while_true); | |
| 5346 __ shr(y.reg(), 1); | |
| 5347 __ j(not_carry, &no_multiply); | |
| 5348 __ mulsd(xmm1, xmm0); | |
| 5349 __ bind(&no_multiply); | |
| 5350 __ test(y.reg(), Operand(y.reg())); | |
| 5351 __ mulsd(xmm0, xmm0); | |
| 5352 __ j(not_zero, &while_true); | |
| 5353 | |
| 5354 __ bind(&powi_done); | |
| 5355 // x has the original value of y - if y is negative return 1/result. | |
| 5356 __ test(x.reg(), Operand(x.reg())); | |
| 5357 __ j(positive, &allocate_and_return); | |
| 5358 // Special case if xmm1 has reached infinity | |
| 5359 __ mov(p.reg(), Immediate(0x7FB00000)); | |
| 5360 __ movd(xmm0, Operand(p.reg())); | |
| 5361 __ cvtss2sd(xmm0, xmm0); | |
| 5362 __ ucomisd(xmm0, xmm1); | |
| 5363 __ j(equal, &go_runtime); | |
| 5364 __ divsd(xmm3, xmm1); | |
| 5365 __ movsd(xmm1, xmm3); | |
| 5366 __ jmp(&allocate_and_return); | |
| 5367 | |
| 5368 // y (or both) is a double - no matter what we should now work | |
| 5369 // on doubles. | |
| 5370 __ bind(&y_nonsmi); | |
| 5371 __ cmp(FieldOperand(y.reg(), HeapObject::kMapOffset), | |
| 5372 Factory::heap_number_map()); | |
| 5373 __ j(not_equal, &go_runtime); | |
| 5374 // Y must be a double. | |
| 5375 __ movdbl(xmm1, FieldOperand(y.reg(), HeapNumber::kValueOffset)); | |
| 5376 // Test if y is nan. | |
| 5377 __ ucomisd(xmm1, xmm1); | |
| 5378 __ j(parity_even, &go_runtime); | |
| 5379 | |
| 5380 Label x_not_smi; | |
| 5381 Label handle_special_cases; | |
| 5382 __ test(x.reg(), Immediate(kSmiTagMask)); | |
| 5383 __ j(not_zero, &x_not_smi); | |
| 5384 __ SmiUntag(x.reg()); | |
| 5385 __ cvtsi2sd(xmm0, Operand(x.reg())); | |
| 5386 __ jmp(&handle_special_cases); | |
| 5387 __ bind(&x_not_smi); | |
| 5388 __ cmp(FieldOperand(x.reg(), HeapObject::kMapOffset), | |
| 5389 Factory::heap_number_map()); | |
| 5390 __ j(not_equal, &go_runtime); | |
| 5391 __ mov(p.reg(), FieldOperand(x.reg(), HeapNumber::kExponentOffset)); | |
| 5392 __ and_(p.reg(), HeapNumber::kExponentMask); | |
| 5393 __ cmp(Operand(p.reg()), Immediate(HeapNumber::kExponentMask)); | |
| 5394 // x is NaN or +/-Infinity | |
| 5395 __ j(greater_equal, &go_runtime); | |
| 5396 __ movdbl(xmm0, FieldOperand(x.reg(), HeapNumber::kValueOffset)); | |
| 5397 | |
| 5398 // x is in xmm0 and y is in xmm1. | |
| 5399 __ bind(&handle_special_cases); | |
| 5400 Label not_minus_half; | |
| 5401 // Test for -0.5. | |
| 5402 // Load xmm2 with -0.5. | |
| 5403 __ mov(p.reg(), Immediate(0xBF000000)); | |
| 5404 __ movd(xmm2, Operand(p.reg())); | |
| 5405 __ cvtss2sd(xmm2, xmm2); | |
| 5406 // xmm2 now has -0.5. | |
| 5407 __ ucomisd(xmm2, xmm1); | |
| 5408 __ j(not_equal, ¬_minus_half); | |
| 5409 | |
| 5410 // Calculates reciprocal of square root. | |
| 5411 // Note that 1/sqrt(x) = sqrt(1/x)) | |
| 5412 __ divsd(xmm3, xmm0); | |
| 5413 __ movsd(xmm1, xmm3); | |
| 5414 __ sqrtsd(xmm1, xmm1); | |
| 5415 __ jmp(&allocate_and_return); | |
| 5416 | |
| 5417 // Test for 0.5. | |
| 5418 __ bind(¬_minus_half); | |
| 5419 // Load xmm2 with 0.5. | |
| 5420 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 = xmm3 | |
| 5421 __ addsd(xmm2, xmm3); | |
| 5422 // xmm2 now has 0.5. | |
| 5423 __ ucomisd(xmm2, xmm1); | |
| 5424 __ j(not_equal, &go_runtime); | |
| 5425 // Calculates square root. | |
| 5426 __ movsd(xmm1, xmm0); | |
| 5427 __ sqrtsd(xmm1, xmm1); | |
| 5428 | |
| 5429 __ bind(&allocate_and_return); | |
| 5430 __ AllocateHeapNumber(p.reg(), y.reg(), x.reg(), &go_runtime); | |
| 5431 __ movdbl(FieldOperand(p.reg(), HeapNumber::kValueOffset), xmm1); | |
| 5432 __ jmp(&return_preg); | |
| 5433 } | |
| 5434 __ bind(&go_runtime); | |
| 5435 x.Unuse(); | |
| 5436 y.Unuse(); | |
| 5437 p.Unuse(); | |
| 5438 Load(args->at(0)); | |
| 5439 Load(args->at(1)); | |
| 5440 frame_->CallRuntime(Runtime::kMath_pow_cfunction, 2); | |
| 5441 | |
| 5442 // Since we store the result in p.reg() which is eax - return this value. | |
| 5443 // If we called runtime the result is also in eax. | |
| 5444 __ bind(&return_preg); | |
| 5445 frame_->Push(eax); | |
| 5446 } else { // Simply call runtime. | |
| 5447 Load(args->at(0)); | |
| 5448 Load(args->at(1)); | |
| 5449 Result res = frame_->CallRuntime(Runtime::kMath_pow, 2); | |
| 5450 frame_->Push(&res); | |
| 5451 } | |
| 5452 } | |
| 5453 | |
| 5454 | |
| 5455 // This generates code that performs a charCodeAt() call or returns | 5279 // This generates code that performs a charCodeAt() call or returns |
| 5456 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. | 5280 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. |
| 5457 // It can handle flat, 8 and 16 bit characters and cons strings where the | 5281 // It can handle flat, 8 and 16 bit characters and cons strings where the |
| 5458 // answer is found in the left hand branch of the cons. The slow case will | 5282 // answer is found in the left hand branch of the cons. The slow case will |
| 5459 // flatten the string, which will ensure that the answer is in the left hand | 5283 // flatten the string, which will ensure that the answer is in the left hand |
| 5460 // side the next time around. | 5284 // side the next time around. |
| 5461 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 5285 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { |
| 5462 Comment(masm_, "[ GenerateFastCharCodeAt"); | 5286 Comment(masm_, "[ GenerateFastCharCodeAt"); |
| 5463 ASSERT(args->length() == 2); | 5287 ASSERT(args->length() == 2); |
| 5464 | 5288 |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6033 ASSERT_EQ(args->length(), 1); | 5857 ASSERT_EQ(args->length(), 1); |
| 6034 | 5858 |
| 6035 // Load the argument on the stack and call the stub. | 5859 // Load the argument on the stack and call the stub. |
| 6036 Load(args->at(0)); | 5860 Load(args->at(0)); |
| 6037 NumberToStringStub stub; | 5861 NumberToStringStub stub; |
| 6038 Result result = frame_->CallStub(&stub, 1); | 5862 Result result = frame_->CallStub(&stub, 1); |
| 6039 frame_->Push(&result); | 5863 frame_->Push(&result); |
| 6040 } | 5864 } |
| 6041 | 5865 |
| 6042 | 5866 |
| 5867 // Generates the Math.pow method - only handles special cases and branches to | |
| 5868 // the runtime system if not.Please note - this function assumes that | |
| 5869 // the callsite has executed ToNumber on both arguments and that the | |
| 5870 // arguments are not the same identifier. | |
| 5871 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { | |
| 5872 ASSERT(args->length() == 2); | |
| 5873 Load(args->at(0)); | |
| 5874 Load(args->at(1)); | |
| 5875 if (!CpuFeatures::IsSupported(SSE2)) { | |
| 5876 Result res = frame_->CallRuntime(Runtime::kMath_pow, 2); | |
| 5877 frame_->Push(&res); | |
| 5878 } else { | |
| 5879 CpuFeatures::Scope use_sse2(SSE2); | |
| 5880 Label allocate_return; | |
| 5881 // Load the two operands while leaving the values on the frame. | |
| 5882 frame()->Dup(); | |
| 5883 Result exponent = frame()->Pop(); | |
| 5884 exponent.ToRegister(); | |
| 5885 frame()->Spill(exponent.reg()); | |
| 5886 frame()->PushElementAt(1); | |
| 5887 Result base = frame()->Pop(); | |
| 5888 base.ToRegister(); | |
| 5889 frame()->Spill(base.reg()); | |
| 5890 | |
| 5891 Result answer = allocator()->Allocate(); | |
| 5892 ASSERT(answer.is_valid()); | |
| 5893 // We can safely assume that the base and exponent is not in the same | |
| 5894 // register since we only call this from one callsite (math.js). | |
| 5895 ASSERT(!exponent.reg().is(base.reg())); | |
| 5896 JumpTarget call_runtime; | |
| 5897 | |
| 5898 // Save 1 in xmm3 - we need this several times later on. | |
| 5899 __ mov(answer.reg(), Immediate(1)); | |
| 5900 __ cvtsi2sd(xmm3, Operand(answer.reg())); | |
| 5901 | |
| 5902 Label exponent_nonsmi; | |
| 5903 Label base_nonsmi; | |
| 5904 // If the exponent is a heap number go to that specific case. | |
| 5905 __ test(exponent.reg(), Immediate(kSmiTagMask)); | |
| 5906 __ j(not_zero, &exponent_nonsmi); | |
| 5907 __ test(base.reg(), Immediate(kSmiTagMask)); | |
| 5908 __ j(not_zero, &base_nonsmi); | |
| 5909 | |
| 5910 // Optimized version when y is an integer. | |
| 5911 Label powi; | |
| 5912 __ SmiUntag(base.reg()); | |
| 5913 __ cvtsi2sd(xmm0, Operand(base.reg())); | |
| 5914 __ jmp(&powi); | |
| 5915 // exponent is smi and base is a heapnumber. | |
| 5916 __ bind(&base_nonsmi); | |
| 5917 __ cmp(FieldOperand(base.reg(), HeapObject::kMapOffset), | |
| 5918 Factory::heap_number_map()); | |
|
Lasse Reichstein
2010/03/08 13:17:01
Indentation? Ditto for other two.
| |
| 5919 call_runtime.Branch(not_zero); | |
|
Lasse Reichstein
2010/03/08 13:17:01
not_zero->not_equal (I know they are identical, bu
| |
| 5920 | |
| 5921 __ movdbl(xmm0, FieldOperand(base.reg(), HeapNumber::kValueOffset)); | |
| 5922 | |
| 5923 // Optimized version of pow if y is an integer. | |
| 5924 __ bind(&powi); | |
| 5925 __ SmiUntag(exponent.reg()); | |
| 5926 | |
| 5927 // Save exponent in base as we need to check if exponent is negative later. | |
| 5928 // We know that base and exponent are in different registers. | |
| 5929 __ mov(base.reg(), exponent.reg()); | |
| 5930 | |
| 5931 // Get absolute value of exponent. | |
| 5932 Label no_neg; | |
| 5933 __ cmp(exponent.reg(), 0); | |
| 5934 __ j(greater_equal, &no_neg); | |
| 5935 __ neg(exponent.reg()); | |
| 5936 __ bind(&no_neg); | |
| 5937 | |
| 5938 // Load xmm1 with 1. | |
| 5939 __ movsd(xmm1, xmm3); | |
| 5940 Label while_true; | |
| 5941 Label no_multiply; | |
| 5942 | |
| 5943 // Label allocate_and_return; | |
| 5944 __ bind(&while_true); | |
| 5945 __ shr(exponent.reg(), 1); | |
| 5946 __ j(not_carry, &no_multiply); | |
| 5947 __ mulsd(xmm1, xmm0); | |
| 5948 __ bind(&no_multiply); | |
| 5949 __ test(exponent.reg(), Operand(exponent.reg())); | |
| 5950 __ mulsd(xmm0, xmm0); | |
| 5951 __ j(not_zero, &while_true); | |
| 5952 | |
| 5953 // x has the original value of y - if y is negative return 1/result. | |
| 5954 __ test(base.reg(), Operand(base.reg())); | |
| 5955 __ j(positive, &allocate_return); | |
| 5956 // Special case if xmm1 has reached infinity. | |
| 5957 __ mov(answer.reg(), Immediate(0x7FB00000)); | |
| 5958 __ movd(xmm0, Operand(answer.reg())); | |
| 5959 __ cvtss2sd(xmm0, xmm0); | |
| 5960 __ ucomisd(xmm0, xmm1); | |
| 5961 call_runtime.Branch(equal); | |
| 5962 __ divsd(xmm3, xmm1); | |
| 5963 __ movsd(xmm1, xmm3); | |
| 5964 __ jmp(&allocate_return); | |
| 5965 | |
| 5966 // exponent (or both) is a heapnumber - no matter what we should now work | |
| 5967 // on doubles. | |
| 5968 __ bind(&exponent_nonsmi); | |
| 5969 __ cmp(FieldOperand(exponent.reg(), HeapObject::kMapOffset), | |
| 5970 Factory::heap_number_map()); | |
| 5971 call_runtime.Branch(not_zero); | |
| 5972 __ movdbl(xmm1, FieldOperand(exponent.reg(), HeapNumber::kValueOffset)); | |
| 5973 // Test if exponent is nan. | |
| 5974 __ ucomisd(xmm1, xmm1); | |
| 5975 call_runtime.Branch(parity_even); | |
| 5976 | |
| 5977 Label base_not_smi; | |
| 5978 Label handle_special_cases; | |
| 5979 __ test(base.reg(), Immediate(kSmiTagMask)); | |
| 5980 __ j(not_zero, &base_not_smi); | |
| 5981 __ SmiUntag(base.reg()); | |
| 5982 __ cvtsi2sd(xmm0, Operand(base.reg())); | |
| 5983 __ jmp(&handle_special_cases); | |
| 5984 __ bind(&base_not_smi); | |
| 5985 __ cmp(FieldOperand(base.reg(), HeapObject::kMapOffset), | |
| 5986 Factory::heap_number_map()); | |
| 5987 call_runtime.Branch(not_zero); | |
| 5988 __ mov(answer.reg(), FieldOperand(base.reg(), HeapNumber::kExponentOffset)); | |
| 5989 __ and_(answer.reg(), HeapNumber::kExponentMask); | |
| 5990 __ cmp(Operand(answer.reg()), Immediate(HeapNumber::kExponentMask)); | |
| 5991 // base is NaN or +/-Infinity | |
| 5992 call_runtime.Branch(greater_equal); | |
| 5993 __ movdbl(xmm0, FieldOperand(base.reg(), HeapNumber::kValueOffset)); | |
| 5994 | |
| 5995 // base is in xmm0 and exponent is in xmm1. | |
| 5996 __ bind(&handle_special_cases); | |
| 5997 Label not_minus_half; | |
| 5998 // Test for -0.5. | |
| 5999 // Load xmm2 with -0.5. | |
| 6000 __ mov(answer.reg(), Immediate(0xBF000000)); | |
| 6001 __ movd(xmm2, Operand(answer.reg())); | |
| 6002 __ cvtss2sd(xmm2, xmm2); | |
| 6003 // xmm2 now has -0.5. | |
| 6004 __ ucomisd(xmm2, xmm1); | |
| 6005 __ j(not_equal, ¬_minus_half); | |
| 6006 | |
| 6007 // Calculates reciprocal of square root. | |
| 6008 // Note that 1/sqrt(x) = sqrt(1/x)) | |
| 6009 __ divsd(xmm3, xmm0); | |
| 6010 __ movsd(xmm1, xmm3); | |
| 6011 __ sqrtsd(xmm1, xmm1); | |
| 6012 __ jmp(&allocate_return); | |
| 6013 | |
| 6014 // Test for 0.5. | |
| 6015 __ bind(¬_minus_half); | |
| 6016 // Load xmm2 with 0.5. | |
| 6017 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3. | |
| 6018 __ addsd(xmm2, xmm3); | |
| 6019 // xmm2 now has 0.5. | |
| 6020 __ comisd(xmm2, xmm1); | |
| 6021 call_runtime.Branch(not_equal); | |
| 6022 // Calculates square root. | |
| 6023 __ movsd(xmm1, xmm0); | |
| 6024 __ sqrtsd(xmm1, xmm1); | |
| 6025 | |
| 6026 JumpTarget done; | |
| 6027 Label failure, success; | |
| 6028 __ bind(&allocate_return); | |
| 6029 // Make a copy of the frame to enable us to handle allocation | |
| 6030 // failure after the JumpTarget jump. | |
| 6031 VirtualFrame* clone = new VirtualFrame(frame()); | |
| 6032 __ AllocateHeapNumber(answer.reg(), exponent.reg(), | |
| 6033 base.reg(), &failure); | |
| 6034 __ movdbl(FieldOperand(answer.reg(), HeapNumber::kValueOffset), xmm1); | |
| 6035 // Remove the two original values from the frame - we only need those | |
| 6036 // in the case where we branch to runtime. | |
| 6037 frame()->Drop(2); | |
| 6038 exponent.Unuse(); | |
| 6039 base.Unuse(); | |
| 6040 done.Jump(&answer); | |
| 6041 // Use the copy of the original frame as our current frame. | |
| 6042 RegisterFile empty_regs; | |
| 6043 SetFrame(clone, &empty_regs); | |
| 6044 // If we experience an allocation failure we branch to runtime. | |
| 6045 __ bind(&failure); | |
| 6046 call_runtime.Bind(); | |
| 6047 answer = frame()->CallRuntime(Runtime::kMath_pow_cfunction, 2); | |
| 6048 | |
| 6049 done.Bind(&answer); | |
| 6050 frame()->Push(&answer); | |
| 6051 } | |
| 6052 } | |
| 6053 | |
| 6054 | |
| 6043 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { | 6055 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| 6044 ASSERT_EQ(args->length(), 1); | 6056 ASSERT_EQ(args->length(), 1); |
| 6045 Load(args->at(0)); | 6057 Load(args->at(0)); |
| 6046 TranscendentalCacheStub stub(TranscendentalCache::SIN); | 6058 TranscendentalCacheStub stub(TranscendentalCache::SIN); |
| 6047 Result result = frame_->CallStub(&stub, 1); | 6059 Result result = frame_->CallStub(&stub, 1); |
| 6048 frame_->Push(&result); | 6060 frame_->Push(&result); |
| 6049 } | 6061 } |
| 6050 | 6062 |
| 6051 | 6063 |
| 6052 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { | 6064 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
| 6053 ASSERT_EQ(args->length(), 1); | 6065 ASSERT_EQ(args->length(), 1); |
| 6054 Load(args->at(0)); | 6066 Load(args->at(0)); |
| 6055 TranscendentalCacheStub stub(TranscendentalCache::COS); | 6067 TranscendentalCacheStub stub(TranscendentalCache::COS); |
| 6056 Result result = frame_->CallStub(&stub, 1); | 6068 Result result = frame_->CallStub(&stub, 1); |
| 6057 frame_->Push(&result); | 6069 frame_->Push(&result); |
| 6058 } | 6070 } |
| 6059 | 6071 |
| 6060 | 6072 |
| 6073 // Generates the Math.sqrt method. Please note - this function assumes that | |
| 6074 // the callsite has executed ToNumber on the argument. | |
| 6075 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { | |
| 6076 ASSERT_EQ(args->length(), 1); | |
| 6077 Load(args->at(0)); | |
| 6078 | |
| 6079 if (!CpuFeatures::IsSupported(SSE2)) { | |
| 6080 Result result = frame()->CallRuntime(Runtime::kMath_sqrt, 1); | |
| 6081 frame()->Push(&result); | |
| 6082 } else { | |
| 6083 CpuFeatures::Scope use_sse2(SSE2); | |
| 6084 // Leave original value on the frame if we need to call runtime. | |
| 6085 frame()->Dup(); | |
| 6086 Result result = frame()->Pop(); | |
| 6087 result.ToRegister(); | |
| 6088 frame()->Spill(result.reg()); | |
| 6089 Label runtime; | |
| 6090 Label non_smi; | |
| 6091 Label load_done; | |
| 6092 JumpTarget end; | |
| 6093 | |
| 6094 __ test(result.reg(), Immediate(kSmiTagMask)); | |
| 6095 __ j(not_zero, &non_smi); | |
| 6096 __ SmiUntag(result.reg()); | |
| 6097 __ cvtsi2sd(xmm0, Operand(result.reg())); | |
| 6098 __ jmp(&load_done); | |
| 6099 __ bind(&non_smi); | |
| 6100 __ cmp(FieldOperand(result.reg(), HeapObject::kMapOffset), | |
| 6101 Factory::heap_number_map()); | |
| 6102 __ j(not_zero, &runtime); | |
| 6103 __ movdbl(xmm0, FieldOperand(result.reg(), HeapNumber::kValueOffset)); | |
| 6104 | |
| 6105 __ bind(&load_done); | |
| 6106 __ sqrtsd(xmm0, xmm0); | |
| 6107 // A copy of the virtual frame to allow us to go to runtime after the | |
| 6108 // JumpTarget jump. | |
| 6109 Result scratch = allocator()->Allocate(); | |
| 6110 VirtualFrame* clone = new VirtualFrame(frame()); | |
| 6111 __ AllocateHeapNumber(result.reg(), scratch.reg(), no_reg, &runtime); | |
| 6112 | |
| 6113 __ movdbl(FieldOperand(result.reg(), HeapNumber::kValueOffset), xmm0); | |
| 6114 frame()->Drop(1); | |
| 6115 scratch.Unuse(); | |
| 6116 end.Jump(&result); | |
| 6117 // We only branch to runtime if we have an allocation error. | |
| 6118 // Use the copy of the original frame as our current frame. | |
| 6119 RegisterFile empty_regs; | |
| 6120 SetFrame(clone, &empty_regs); | |
| 6121 __ bind(&runtime); | |
| 6122 result = frame()->CallRuntime(Runtime::kMath_sqrt, 1); | |
| 6123 | |
| 6124 end.Bind(&result); | |
| 6125 frame()->Push(&result); | |
| 6126 } | |
| 6127 } | |
| 6128 | |
| 6129 | |
| 6061 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 6130 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
| 6062 if (CheckForInlineRuntimeCall(node)) { | 6131 if (CheckForInlineRuntimeCall(node)) { |
| 6063 return; | 6132 return; |
| 6064 } | 6133 } |
| 6065 | 6134 |
| 6066 ZoneList<Expression*>* args = node->arguments(); | 6135 ZoneList<Expression*>* args = node->arguments(); |
| 6067 Comment cmnt(masm_, "[ CallRuntime"); | 6136 Comment cmnt(masm_, "[ CallRuntime"); |
| 6068 Runtime::Function* function = node->function(); | 6137 Runtime::Function* function = node->function(); |
| 6069 | 6138 |
| 6070 if (function == NULL) { | 6139 if (function == NULL) { |
| (...skipping 5313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11384 | 11453 |
| 11385 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 11454 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 11386 // tagged as a small integer. | 11455 // tagged as a small integer. |
| 11387 __ bind(&runtime); | 11456 __ bind(&runtime); |
| 11388 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 11457 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 11389 } | 11458 } |
| 11390 | 11459 |
| 11391 #undef __ | 11460 #undef __ |
| 11392 | 11461 |
| 11393 } } // namespace v8::internal | 11462 } } // namespace v8::internal |
| OLD | NEW |