Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as | 212 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
| 213 // floating point numbers in XMM registers. | 213 // floating point numbers in XMM registers. |
| 214 static void LoadFloatOperands(MacroAssembler* masm, | 214 static void LoadFloatOperands(MacroAssembler* masm, |
| 215 XMMRegister dst1, | 215 XMMRegister dst1, |
| 216 XMMRegister dst2); | 216 XMMRegister dst2); |
| 217 | 217 |
| 218 // Code pattern for loading floating point values onto the fp stack. | 218 // Code pattern for loading floating point values onto the fp stack. |
| 219 // Input values must be either smi or heap number objects (fp values). | 219 // Input values must be either smi or heap number objects (fp values). |
| 220 // Requirements: | 220 // Requirements: |
| 221 // Register version: operands in registers lhs and rhs. | 221 // Register version: operands in registers lhs and rhs. |
| 222 // Version without scratch memory pushes and pops the stack to get a | |
| 223 // memory cell, the version with scratch memory uses 8 bytes (64 bits) | |
| 224 // at that location. | |
| 222 // Stack version: operands on TOS+1 and TOS+2. | 225 // Stack version: operands on TOS+1 and TOS+2. |
| 223 // Returns operands as floating point numbers on fp stack. | 226 // Returns operands as floating point numbers on fp stack. |
| 224 static void LoadFloatOperands(MacroAssembler* masm); | 227 static void LoadFloatOperands(MacroAssembler* masm); |
| 225 static void LoadFloatOperands(MacroAssembler* masm, | 228 static void LoadFloatOperands(MacroAssembler* masm, |
| 226 Register lhs, | 229 Register lhs, |
| 227 Register rhs); | 230 Register rhs); |
| 231 static void LoadFloatOperands(MacroAssembler* masm, | |
| 232 Register lhs, | |
| 233 Register rhs, | |
| 234 const Operand& scratch_memory); | |
| 228 | 235 |
| 229 // Code pattern for loading a floating point value and converting it | 236 // Code pattern for loading a floating point value and converting it |
| 230 // to a 32 bit integer. Input value must be either a smi or a heap number | 237 // to a 32 bit integer. Input value must be either a smi or a heap number |
| 231 // object. | 238 // object. |
| 232 // Returns operands as 32-bit sign extended integers in a general purpose | 239 // Returns operands as 32-bit sign extended integers in a general purpose |
| 233 // registers. | 240 // registers. |
| 234 static void LoadInt32Operand(MacroAssembler* masm, | 241 static void LoadInt32Operand(MacroAssembler* masm, |
| 235 const Operand& src, | 242 const Operand& src, |
| 236 Register dst); | 243 Register dst); |
| 237 | 244 |
| (...skipping 3758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3996 answer = frame_->CallRuntime(Runtime::kMath_sin, 1); | 4003 answer = frame_->CallRuntime(Runtime::kMath_sin, 1); |
| 3997 break; | 4004 break; |
| 3998 case COS: | 4005 case COS: |
| 3999 answer = frame_->CallRuntime(Runtime::kMath_cos, 1); | 4006 answer = frame_->CallRuntime(Runtime::kMath_cos, 1); |
| 4000 break; | 4007 break; |
| 4001 } | 4008 } |
| 4002 frame_->Push(&answer); | 4009 frame_->Push(&answer); |
| 4003 done.Bind(); | 4010 done.Bind(); |
| 4004 } | 4011 } |
| 4005 | 4012 |
| 4006 | 4013 |
|
William Hesse
2009/10/20 14:50:51
Could this function be documented more, explaining
| |
| 4014 void CodeGenerator::GenerateNumberMod(ZoneList<Expression*>* args) { | |
| 4015 ASSERT_EQ(2, args->length()); | |
| 4016 #ifdef _WIN64 | |
| 4017 Load(args->at(0)); | |
| 4018 Load(args->at(1)); | |
| 4019 // Allocate rax for using fnstsw_ax. | |
| 4020 Result tmp = allocator_->Allocate(rax); | |
| 4021 // Allocate callee save register, for storing value while calling runtime. | |
| 4022 Result callee_save_result = allocator_->Allocate(r15); | |
| 4023 Result divisor_result = frame_->Pop(); | |
| 4024 Result dividend_result = frame_->Pop(); | |
| 4025 divisor_result.ToRegister(); | |
| 4026 dividend_result.ToRegister(); | |
| 4027 { | |
| 4028 // Code uses the physical stack, so it must be in sync. | |
| 4029 VirtualFrame::SpilledScope scope; | |
| 4030 Register dividend = dividend_result.reg(); | |
| 4031 Register divisor = divisor_result.reg(); | |
| 4032 Register callee_save = callee_save_result.reg(); | |
| 4033 | |
| 4034 Label done; | |
| 4035 // Make room on stack for temporary value. | |
| 4036 __ subq(rsp, Immediate(kPointerSize)); | |
| 4037 | |
| 4038 // Load operands onto FPU stack. | |
| 4039 // Divisor must go first on stack, so order of operands is really rhs, lhs. | |
| 4040 FloatingPointHelper::LoadFloatOperands(masm_, | |
| 4041 divisor, | |
| 4042 dividend, | |
| 4043 Operand(rsp, 0)); | |
| 4044 | |
| 4045 // Compute the remainder. | |
| 4046 { | |
| 4047 Label partial_remainder_loop; | |
| 4048 __ bind(&partial_remainder_loop); | |
| 4049 __ fprem(); | |
| 4050 __ fwait(); | |
| 4051 __ fnstsw_ax(); | |
| 4052 __ testl(rax, Immediate(kCondition2)); | |
| 4053 __ j(not_zero, &partial_remainder_loop); | |
| 4054 } | |
| 4055 | |
| 4056 // Result is in ST(0), garbage in ST(1), and original value | |
| 4057 // of dividend in ST(2). Return ST(0) unless a division by zero or | |
| 4058 // invalid operation exception has been raised. Status word is in rax. | |
| 4059 | |
| 4060 Label valid_result; | |
| 4061 Label allocate_result; | |
| 4062 // Test for InvalidOperation or division by zero. | |
| 4063 // In those cases, discard the result and use NaN instead. | |
| 4064 __ testb(rax, Immediate(kInvalidOperandException | kZeroDivideException)); | |
| 4065 __ j(zero, &valid_result); | |
| 4066 | |
| 4067 __ fstp(0); // Pop (garbage) result | |
| 4068 __ addq(rsp, Immediate(kPointerSize)); // Free stack cell. | |
| 4069 int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000); | |
| 4070 // Move NaN to (callee save) register for later storing into new HeapNumber. | |
| 4071 __ movq(callee_save, kNaNValue, RelocInfo::NONE); | |
| 4072 __ jmp(&allocate_result); | |
| 4073 | |
| 4074 // Allocate new space for a HeapNumber (is branched back to if direct heap | |
| 4075 // allocation fails in the following code). | |
| 4076 Label gc_req; | |
| 4077 Label heap_number_allocated; | |
| 4078 __ bind(&gc_req); | |
| 4079 // Garbage collection required before allocating a heap number. | |
| 4080 // Call runtime to do the allocation, and handle the allocation failure. | |
| 4081 __ CallRuntime(Runtime::kAllocateHeapNumber, 0); | |
| 4082 __ jmp(&heap_number_allocated); | |
| 4083 | |
| 4084 __ bind(&valid_result); | |
| 4085 | |
| 4086 // Result in ST(0), garbage in ST(1) and ST(2). | |
| 4087 // Pop result and free stack cell. | |
| 4088 __ fstp_d(Operand(rsp, 0)); | |
| 4089 __ pop(callee_save); | |
| 4090 | |
| 4091 __ bind(&allocate_result); | |
| 4092 // Free FPU stack and clear pending FPU exceptions (e.g., Denormal). | |
| 4093 __ fstp(0); | |
| 4094 Label no_exceptions_set; | |
| 4095 __ testb(rax, Immediate(kAnyExceptionMask)); | |
| 4096 __ j(zero, &no_exceptions_set); | |
| 4097 __ fnclex(); | |
| 4098 __ bind(&no_exceptions_set); | |
| 4099 | |
| 4100 FloatingPointHelper::AllocateHeapNumber(masm_, &gc_req, dividend, rax); | |
| 4101 __ bind(&heap_number_allocated); // Return point for gc_req branch. | |
| 4102 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), callee_save); | |
| 4103 | |
| 4104 __ bind(&done); | |
| 4105 } | |
| 4106 frame_->Push(&tmp); | |
| 4107 | |
| 4108 #else | |
| 4109 // Simply call the runtime function. Arguments must be numbers. | |
| 4110 ASSERT(args->length() == 2); | |
| 4111 Load(args->at(0)); | |
| 4112 Load(args->at(1)); | |
| 4113 | |
| 4114 Result answer = frame_->CallRuntime(Runtime::kNumberMod, 2); | |
| 4115 frame_->Push(&answer); | |
| 4116 #endif | |
| 4117 } | |
| 4118 | |
| 4119 | |
| 4007 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 4120 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
| 4008 ASSERT(args->length() == 1); | 4121 ASSERT(args->length() == 1); |
| 4009 JumpTarget leave, null, function, non_function_constructor; | 4122 JumpTarget leave, null, function, non_function_constructor; |
| 4010 Load(args->at(0)); // Load the object. | 4123 Load(args->at(0)); // Load the object. |
| 4011 Result obj = frame_->Pop(); | 4124 Result obj = frame_->Pop(); |
| 4012 obj.ToRegister(); | 4125 obj.ToRegister(); |
| 4013 frame_->Spill(obj.reg()); | 4126 frame_->Spill(obj.reg()); |
| 4014 | 4127 |
| 4015 // If the object is a smi, we return null. | 4128 // If the object is a smi, we return null. |
| 4016 Condition is_smi = masm_->CheckSmi(obj.reg()); | 4129 Condition is_smi = masm_->CheckSmi(obj.reg()); |
| (...skipping 3300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7317 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done; | 7430 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done; |
| 7318 __ JumpIfSmi(lhs, &load_smi_lhs); | 7431 __ JumpIfSmi(lhs, &load_smi_lhs); |
| 7319 __ fld_d(FieldOperand(lhs, HeapNumber::kValueOffset)); | 7432 __ fld_d(FieldOperand(lhs, HeapNumber::kValueOffset)); |
| 7320 __ bind(&done_load_lhs); | 7433 __ bind(&done_load_lhs); |
| 7321 | 7434 |
| 7322 __ JumpIfSmi(rhs, &load_smi_rhs); | 7435 __ JumpIfSmi(rhs, &load_smi_rhs); |
| 7323 __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset)); | 7436 __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset)); |
| 7324 __ jmp(&done); | 7437 __ jmp(&done); |
| 7325 | 7438 |
| 7326 __ bind(&load_smi_lhs); | 7439 __ bind(&load_smi_lhs); |
| 7327 __ SmiToInteger64(kScratchRegister, lhs); | 7440 __ push(lhs); |
| 7328 __ push(kScratchRegister); | 7441 __ FLoadSmi(Operand(rsp, 0)); |
| 7329 __ fild_d(Operand(rsp, 0)); | 7442 __ addq(rsp, Immediate(kPointerSize)); |
| 7330 __ pop(kScratchRegister); | |
| 7331 __ jmp(&done_load_lhs); | 7443 __ jmp(&done_load_lhs); |
| 7332 | 7444 |
| 7333 __ bind(&load_smi_rhs); | 7445 __ bind(&load_smi_rhs); |
| 7334 __ SmiToInteger64(kScratchRegister, rhs); | 7446 __ push(rhs); |
| 7335 __ push(kScratchRegister); | 7447 __ FLoadSmi(Operand(rsp, 0)); |
| 7336 __ fild_d(Operand(rsp, 0)); | 7448 __ addq(rsp, Immediate(kPointerSize)); |
| 7337 __ pop(kScratchRegister); | |
| 7338 | 7449 |
| 7339 __ bind(&done); | 7450 __ bind(&done); |
| 7340 } | 7451 } |
| 7452 | |
| 7453 | |
| 7454 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | |
| 7455 Register lhs, | |
| 7456 Register rhs, | |
| 7457 const Operand& scratch_memory) { | |
| 7458 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done; | |
| 7459 __ JumpIfSmi(lhs, &load_smi_lhs); | |
| 7460 __ fld_d(FieldOperand(lhs, HeapNumber::kValueOffset)); | |
| 7461 __ bind(&done_load_lhs); | |
| 7462 | |
| 7463 __ JumpIfSmi(rhs, &load_smi_rhs); | |
| 7464 __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset)); | |
| 7465 __ jmp(&done); | |
| 7466 | |
| 7467 __ bind(&load_smi_lhs); | |
| 7468 __ movq(scratch_memory, lhs); | |
| 7469 __ FLoadSmi(scratch_memory); | |
| 7470 __ jmp(&done_load_lhs); | |
| 7471 | |
| 7472 __ bind(&load_smi_rhs); | |
| 7473 __ movq(scratch_memory, rhs); | |
| 7474 __ FLoadSmi(scratch_memory); | |
| 7475 | |
| 7476 __ bind(&done); | |
| 7477 } | |
| 7341 | 7478 |
| 7342 | 7479 |
| 7343 void FloatingPointHelper::CheckNumberOperands(MacroAssembler* masm, | 7480 void FloatingPointHelper::CheckNumberOperands(MacroAssembler* masm, |
| 7344 Label* non_float) { | 7481 Label* non_float) { |
| 7345 Label test_other, done; | 7482 Label test_other, done; |
| 7346 // Test if both operands are numbers (heap_numbers or smis). | 7483 // Test if both operands are numbers (heap_numbers or smis). |
| 7347 // If not, jump to label non_float. | 7484 // If not, jump to label non_float. |
| 7348 __ JumpIfSmi(rdx, &test_other); // argument in rdx is OK | 7485 __ JumpIfSmi(rdx, &test_other); // argument in rdx is OK |
| 7349 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), Factory::heap_number_map()); | 7486 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), Factory::heap_number_map()); |
| 7350 __ j(not_equal, non_float); // The argument in rdx is not a number. | 7487 __ j(not_equal, non_float); // The argument in rdx is not a number. |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7692 int CompareStub::MinorKey() { | 7829 int CompareStub::MinorKey() { |
| 7693 // Encode the two parameters in a unique 16 bit value. | 7830 // Encode the two parameters in a unique 16 bit value. |
| 7694 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 7831 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); |
| 7695 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 7832 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); |
| 7696 } | 7833 } |
| 7697 | 7834 |
| 7698 | 7835 |
| 7699 #undef __ | 7836 #undef __ |
| 7700 | 7837 |
| 7701 } } // namespace v8::internal | 7838 } } // namespace v8::internal |
| OLD | NEW |