Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-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 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 971 if (left_is_smi && right_is_smi) { | 971 if (left_is_smi && right_is_smi) { |
| 972 // Compute the constant result at compile time, and leave it on the frame. | 972 // Compute the constant result at compile time, and leave it on the frame. |
| 973 int left_int = Smi::cast(*left.handle())->value(); | 973 int left_int = Smi::cast(*left.handle())->value(); |
| 974 int right_int = Smi::cast(*right.handle())->value(); | 974 int right_int = Smi::cast(*right.handle())->value(); |
| 975 if (FoldConstantSmis(op, left_int, right_int)) return; | 975 if (FoldConstantSmis(op, left_int, right_int)) return; |
| 976 } | 976 } |
| 977 | 977 |
| 978 Result answer; | 978 Result answer; |
| 979 if (left_is_non_smi || right_is_non_smi) { | 979 if (left_is_non_smi || right_is_non_smi) { |
| 980 // Go straight to the slow case, with no smi code. | 980 // Go straight to the slow case, with no smi code. |
| 981 frame_->Push(&left); | |
| 982 frame_->Push(&right); | |
| 983 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB); | 981 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB); |
| 984 answer = frame_->CallStub(&stub, 2); | 982 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
| 985 } else if (right_is_smi) { | 983 } else if (right_is_smi) { |
| 986 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), | 984 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), |
| 987 type, false, overwrite_mode); | 985 type, false, overwrite_mode); |
| 988 } else if (left_is_smi) { | 986 } else if (left_is_smi) { |
| 989 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), | 987 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), |
| 990 type, true, overwrite_mode); | 988 type, true, overwrite_mode); |
| 991 } else { | 989 } else { |
| 992 // Set the flags based on the operation, type and loop nesting level. | 990 // Set the flags based on the operation, type and loop nesting level. |
| 993 // Bit operations always assume they likely operate on Smis. Still only | 991 // Bit operations always assume they likely operate on Smis. Still only |
| 994 // generate the inline Smi check code if this operation is part of a loop. | 992 // generate the inline Smi check code if this operation is part of a loop. |
| 995 // For all other operations only inline the Smi check code for likely smis | 993 // For all other operations only inline the Smi check code for likely smis |
| 996 // if the operation is part of a loop. | 994 // if the operation is part of a loop. |
| 997 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { | 995 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { |
| 998 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); | 996 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); |
| 999 } else { | 997 } else { |
| 1000 frame_->Push(&left); | |
| 1001 frame_->Push(&right); | |
| 1002 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS); | 998 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS); |
| 1003 answer = frame_->CallStub(&stub, 2); | 999 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
| 1004 } | 1000 } |
| 1005 } | 1001 } |
| 1006 frame_->Push(&answer); | 1002 frame_->Push(&answer); |
| 1007 } | 1003 } |
| 1008 | 1004 |
| 1009 | 1005 |
| 1010 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { | 1006 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { |
| 1011 Object* answer_object = Heap::undefined_value(); | 1007 Object* answer_object = Heap::undefined_value(); |
| 1012 switch (op) { | 1008 switch (op) { |
| 1013 case Token::ADD: | 1009 case Token::ADD: |
| (...skipping 6055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7069 // Update flags to indicate that arguments are in registers. | 7065 // Update flags to indicate that arguments are in registers. |
| 7070 SetArgsInRegisters(); | 7066 SetArgsInRegisters(); |
| 7071 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); | 7067 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); |
| 7072 } | 7068 } |
| 7073 | 7069 |
| 7074 // Call the stub. | 7070 // Call the stub. |
| 7075 __ CallStub(this); | 7071 __ CallStub(this); |
| 7076 } | 7072 } |
| 7077 | 7073 |
| 7078 | 7074 |
| 7075 Result GenericBinaryOpStub::GenerateCall(MacroAssembler* masm, | |
| 7076 VirtualFrame* frame, | |
| 7077 Result* left, | |
| 7078 Result* right) { | |
| 7079 if (ArgsInRegistersSupported()) { | |
| 7080 SetArgsInRegisters(); | |
| 7081 return frame->CallStub(this, left, right); | |
| 7082 } else { | |
| 7083 frame->Push(left); | |
| 7084 frame->Push(right); | |
| 7085 return frame->CallStub(this, 2); | |
| 7086 } | |
| 7087 } | |
| 7088 | |
| 7089 | |
| 7079 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { | 7090 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { |
| 7080 if (HasArgsInRegisters()) { | 7091 if (HasArgsInRegisters()) { |
| 7081 __ mov(ebx, eax); | 7092 __ mov(ebx, eax); |
| 7082 __ mov(eax, edx); | 7093 __ mov(eax, edx); |
| 7083 } else { | 7094 } else { |
| 7084 __ mov(ebx, Operand(esp, 1 * kPointerSize)); | 7095 __ mov(ebx, Operand(esp, 1 * kPointerSize)); |
| 7085 __ mov(eax, Operand(esp, 2 * kPointerSize)); | 7096 __ mov(eax, Operand(esp, 2 * kPointerSize)); |
| 7086 } | 7097 } |
| 7087 | 7098 |
| 7088 Label not_smis, not_smis_or_overflow, not_smis_undo_optimistic; | 7099 Label not_smis, not_smis_or_overflow, not_smis_undo_optimistic; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 7100 case Token::ADD: | 7111 case Token::ADD: |
| 7101 __ add(eax, Operand(ebx)); // add optimistically | 7112 __ add(eax, Operand(ebx)); // add optimistically |
| 7102 __ j(overflow, ¬_smis_or_overflow, not_taken); | 7113 __ j(overflow, ¬_smis_or_overflow, not_taken); |
| 7103 break; | 7114 break; |
| 7104 | 7115 |
| 7105 case Token::SUB: | 7116 case Token::SUB: |
| 7106 __ sub(eax, Operand(ebx)); // subtract optimistically | 7117 __ sub(eax, Operand(ebx)); // subtract optimistically |
| 7107 __ j(overflow, ¬_smis_or_overflow, not_taken); | 7118 __ j(overflow, ¬_smis_or_overflow, not_taken); |
| 7108 break; | 7119 break; |
| 7109 | 7120 |
| 7121 case Token::MUL: | |
| 7122 __ mov(edi, Operand(eax)); // backup the 1st operand | |
|
Kevin Millikin (Chromium)
2010/01/26 09:07:22
No need for Operand: __ mov(edi, eax).
Comment sh
Vladislav Kaznacheev
2010/01/26 10:21:18
Done.
| |
| 7123 break; | |
| 7124 | |
| 7110 case Token::DIV: | 7125 case Token::DIV: |
| 7126 __ mov(edi, Operand(eax)); // backup the 1st operand | |
| 7127 // Fall through. | |
| 7111 case Token::MOD: | 7128 case Token::MOD: |
| 7112 // Sign extend eax into edx:eax. | 7129 // Sign extend eax into edx:eax. |
| 7113 __ cdq(); | 7130 __ cdq(); |
| 7114 // Check for 0 divisor. | 7131 // Check for 0 divisor. |
| 7115 __ test(ebx, Operand(ebx)); | 7132 __ test(ebx, Operand(ebx)); |
| 7116 __ j(zero, ¬_smis_or_overflow, not_taken); | 7133 __ j(zero, ¬_smis_or_overflow, not_taken); |
| 7117 break; | 7134 break; |
| 7118 | 7135 |
| 7119 default: | 7136 default: |
| 7120 // Fall-through to smi check. | 7137 // Fall-through to smi check. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7236 default: break; | 7253 default: break; |
| 7237 } | 7254 } |
| 7238 ASSERT(kSmiTag == 0); // Adjust zero check if not the case. | 7255 ASSERT(kSmiTag == 0); // Adjust zero check if not the case. |
| 7239 __ test(ecx, Immediate(kSmiTagMask)); | 7256 __ test(ecx, Immediate(kSmiTagMask)); |
| 7240 __ j(not_zero, ¬_smis, not_taken); | 7257 __ j(not_zero, ¬_smis, not_taken); |
| 7241 // Correct operand values are in eax, ebx at this point. | 7258 // Correct operand values are in eax, ebx at this point. |
| 7242 | 7259 |
| 7243 __ bind(&use_fp_on_smis); | 7260 __ bind(&use_fp_on_smis); |
| 7244 // Both operands are known to be SMIs but the result does not fit into a SMI. | 7261 // Both operands are known to be SMIs but the result does not fit into a SMI. |
| 7245 switch (op_) { | 7262 switch (op_) { |
| 7263 case Token::MUL: | |
| 7264 case Token::DIV: | |
| 7265 __ mov(eax, edi); // Restore the 1st operand. | |
| 7266 // Fall through. | |
| 7246 case Token::ADD: | 7267 case Token::ADD: |
| 7247 case Token::SUB: | 7268 case Token::SUB: { |
| 7248 case Token::MUL: | |
| 7249 case Token::DIV: { | |
| 7250 Label after_alloc_failure; | 7269 Label after_alloc_failure; |
| 7251 | 7270 __ AllocateHeapNumber(edx, ecx, no_reg, &after_alloc_failure); |
| 7252 FloatingPointHelper::ArgLocation arg_location = | |
| 7253 (op_ == Token::ADD || op_ == Token::SUB) ? | |
| 7254 FloatingPointHelper::ARGS_IN_REGISTERS : | |
| 7255 FloatingPointHelper::ARGS_ON_STACK; | |
| 7256 | |
| 7257 __ AllocateHeapNumber( | |
| 7258 edx, | |
| 7259 ecx, | |
| 7260 no_reg, | |
| 7261 arg_location == FloatingPointHelper::ARGS_IN_REGISTERS ? | |
| 7262 &after_alloc_failure : | |
| 7263 slow); | |
| 7264 | 7271 |
| 7265 if (CpuFeatures::IsSupported(SSE2)) { | 7272 if (CpuFeatures::IsSupported(SSE2)) { |
| 7266 CpuFeatures::Scope use_sse2(SSE2); | 7273 CpuFeatures::Scope use_sse2(SSE2); |
| 7267 FloatingPointHelper::LoadSse2Smis(masm, ecx, arg_location); | 7274 FloatingPointHelper::LoadSse2Smis( |
| 7275 masm, | |
| 7276 ecx, | |
| 7277 FloatingPointHelper::ARGS_IN_REGISTERS); | |
|
Kevin Millikin (Chromium)
2010/01/26 09:07:22
Does LoadSse2Smis need the ArgLocation argument an
Vladislav Kaznacheev
2010/01/26 10:21:18
Removed (also for LoadFloatSmis).
On 2010/01/26 09
| |
| 7268 switch (op_) { | 7278 switch (op_) { |
| 7269 case Token::ADD: __ addsd(xmm0, xmm1); break; | 7279 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| 7270 case Token::SUB: __ subsd(xmm0, xmm1); break; | 7280 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 7271 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 7281 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 7272 case Token::DIV: __ divsd(xmm0, xmm1); break; | 7282 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 7273 default: UNREACHABLE(); | 7283 default: UNREACHABLE(); |
| 7274 } | 7284 } |
| 7275 __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0); | 7285 __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0); |
| 7276 } else { // SSE2 not available, use FPU. | 7286 } else { // SSE2 not available, use FPU. |
| 7277 FloatingPointHelper::LoadFloatSmis(masm, ecx, arg_location); | 7287 FloatingPointHelper::LoadFloatSmis( |
| 7288 masm, | |
| 7289 ecx, | |
| 7290 FloatingPointHelper::ARGS_IN_REGISTERS); | |
| 7278 switch (op_) { | 7291 switch (op_) { |
| 7279 case Token::ADD: __ faddp(1); break; | 7292 case Token::ADD: __ faddp(1); break; |
| 7280 case Token::SUB: __ fsubp(1); break; | 7293 case Token::SUB: __ fsubp(1); break; |
| 7281 case Token::MUL: __ fmulp(1); break; | 7294 case Token::MUL: __ fmulp(1); break; |
| 7282 case Token::DIV: __ fdivp(1); break; | 7295 case Token::DIV: __ fdivp(1); break; |
| 7283 default: UNREACHABLE(); | 7296 default: UNREACHABLE(); |
| 7284 } | 7297 } |
| 7285 __ fstp_d(FieldOperand(edx, HeapNumber::kValueOffset)); | 7298 __ fstp_d(FieldOperand(edx, HeapNumber::kValueOffset)); |
| 7286 } | 7299 } |
| 7287 __ mov(eax, edx); | 7300 __ mov(eax, edx); |
| 7288 GenerateReturn(masm); | 7301 GenerateReturn(masm); |
| 7289 | 7302 |
| 7290 if (arg_location == FloatingPointHelper::ARGS_IN_REGISTERS) { | 7303 __ bind(&after_alloc_failure); |
| 7291 __ bind(&after_alloc_failure); | 7304 __ mov(edx, eax); |
| 7292 __ mov(edx, eax); | 7305 __ mov(eax, ebx); |
| 7293 __ mov(eax, ebx); | 7306 __ jmp(slow); |
| 7294 __ jmp(slow); | |
| 7295 } | |
| 7296 break; | 7307 break; |
| 7297 } | 7308 } |
| 7298 | 7309 |
| 7299 case Token::BIT_OR: | 7310 case Token::BIT_OR: |
| 7300 case Token::BIT_AND: | 7311 case Token::BIT_AND: |
| 7301 case Token::BIT_XOR: | 7312 case Token::BIT_XOR: |
| 7302 case Token::SAR: | 7313 case Token::SAR: |
| 7303 // Do nothing here as these operations always succeed on a pair of smis. | 7314 // Do nothing here as these operations always succeed on a pair of smis. |
| 7304 break; | 7315 break; |
| 7305 | 7316 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7431 } | 7442 } |
| 7432 // Tag smi result and return. | 7443 // Tag smi result and return. |
| 7433 __ SmiTag(eax); | 7444 __ SmiTag(eax); |
| 7434 GenerateReturn(masm); | 7445 GenerateReturn(masm); |
| 7435 | 7446 |
| 7436 // All ops except SHR return a signed int32 that we load in a HeapNumber. | 7447 // All ops except SHR return a signed int32 that we load in a HeapNumber. |
| 7437 if (op_ != Token::SHR) { | 7448 if (op_ != Token::SHR) { |
| 7438 __ bind(&non_smi_result); | 7449 __ bind(&non_smi_result); |
| 7439 // Allocate a heap number if needed. | 7450 // Allocate a heap number if needed. |
| 7440 __ mov(ebx, Operand(eax)); // ebx: result | 7451 __ mov(ebx, Operand(eax)); // ebx: result |
| 7441 Label skip_allocation; | 7452 Label skip_allocation; |
| 7442 switch (mode_) { | 7453 switch (mode_) { |
| 7443 case OVERWRITE_LEFT: | 7454 case OVERWRITE_LEFT: |
| 7444 case OVERWRITE_RIGHT: | 7455 case OVERWRITE_RIGHT: |
| 7445 // If the operand was an object, we skip the | 7456 // If the operand was an object, we skip the |
| 7446 // allocation of a heap number. | 7457 // allocation of a heap number. |
| 7447 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 7458 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
| 7448 1 * kPointerSize : 2 * kPointerSize)); | 7459 1 * kPointerSize : 2 * kPointerSize)); |
| 7449 __ test(eax, Immediate(kSmiTagMask)); | 7460 __ test(eax, Immediate(kSmiTagMask)); |
| 7450 __ j(not_zero, &skip_allocation, not_taken); | 7461 __ j(not_zero, &skip_allocation, not_taken); |
| 7451 // Fall through! | 7462 // Fall through! |
| (...skipping 2536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9988 | 9999 |
| 9989 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 10000 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 9990 // tagged as a small integer. | 10001 // tagged as a small integer. |
| 9991 __ bind(&runtime); | 10002 __ bind(&runtime); |
| 9992 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); | 10003 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); |
| 9993 } | 10004 } |
| 9994 | 10005 |
| 9995 #undef __ | 10006 #undef __ |
| 9996 | 10007 |
| 9997 } } // namespace v8::internal | 10008 } } // namespace v8::internal |
| OLD | NEW |